Pipeline 구축

1 minute read

1. Pipeline이란?

  • 연속되는 전처리와 모델을 한꺼번에 학습할 수 있게 만든다.
  • 따라서, 전처리 + 모델의 영향력을 한 번에 알 수 있다.
  • But 일방적으로 전체 데이터를 다 사용해야 하므로 컬럼별 특성을 고려하지 못하는 단점도 있다.
    -> ColumnTransformer를 지원

2. Pipeline 구축

데이터는 iris 데이터를 가져왔다.

import seaborn as sns
from sklearn.model_selection import train_test_split
iris = sns.load_dataset('iris')
X_train, X_test, y_train, y_test = train_test_split(iris.iloc[:, :-1], iris.species)

Pipeline이나 make_pipeline 둘 중 하나를 사용하여 pipeline을 구축할 수 있다.

from sklearn.pipeline import Pipeline, make_pipeline

Pipeline

from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

pipe = Pipeline([('ss', StandardScaler()), ('knn', KNeighborsClassifier())])
pipe.fit(X_train, y_train)
pipe.score(X_test, y_test)

make_pipeline

pipe2 = make_pipeline(StandardScaler(), KNeighborsClassifier())
pipe2.fit(X_train, y_train)
pipe2.score(X_test, y_test)

make_pipeline은 Pipeline과 달리 자동으로 이름을 생성해주므로, 더 간단하다. 맨 끝자리에는 항상 예측모델 관련된 것들이 들어가야 fit, score를 사용할 수 있다.

3. FunctionTransformer

나만의 전처리 함수를 만들어서 적용할 수도 있다.

from sklearn.preprocessing import FunctionTransformer

ft = FunctionTransformer(lambda x:x+1)
ft.fit_transform(iris.sepal_length)

pipe3 = make_pipeline(ft, KNeighborsClassifier())
pipe3.fit(X_train, y_train)
pipe3.score(X_test, y_test)

4. Pipeline + GridSearchCV

다음을 실행해보자.

모델별 파라미터 이름은 get_params()로 확인할 수 있다.

knn = KNeighborsClassifier()
knn.get_params()
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(pipe2, {'n_neighbors':range(2, 10)})
grid.fit(X_train, y_train)

ValueError가 발생한 것을 확인할 수 있을 것이다. GridSearchCV에서 Pipeline을 사용하려면 파라미터의 이름 앞에 모델명__가 추가되어야 한다.

grid = GridSearchCV(pipe2, {'kneighborsclassifier__n_neighbors':range(2, 10)})
grid.fit(X_train, y_train)

cv_results_를 확인해보자.

import pandas as pd
pd.DataFrame(grid.cv_results_).T

GridSearchCV를 통해 알고리즘별 성능을 예측하는 것도 가능하다.

from sklearn.linear_model import LogisticRegression

pipe3 = Pipeline([('ss', StandardScaler()), ('clf', KNeighborsClassifier())])
grid2 = GridSearchCV(pipe3, {'clf': [KNeighborsClassifier(), LogisticRegression()]})
grid2.fit(X_train, y_train)
pd.DataFrame(grid2.cv_results_).T

리스트를 사용해 다른 파라미터들과도 결합해보자.

grid2 = GridSearchCV(pipe3, [
    {'clf': [KNeighborsClassifier()], 'clf__n_neighbors':[2,3,4,5]},
     {'clf': [LogisticRegression()], 'clf__C':[1,2,3,4,5]}])
grid2.fit(X_train, y_train)
pd.DataFrame(grid2.cv_results_)

5. ColumnTransformer

여러 Pipeline을 붙여서 사용할 수 있다.

from sklearn.compose import ColumnTransformer

데이터는 mpg 데이터를 사용한다. mpg 데이터의 origin 컬럼이 object 타입이기 때문에 일괄적으로 StandardScaler를 적용할 수가 없는 것을 확인할 수 있다.

mpg = sns.load_dataset('mpg')
mpg.drop(columns='name', inplace=True)
X_train, X_test, y_train, y_test = train_test_split(mpg.iloc[:, 1:], mpg.mpg)

ss = StandardScaler()
ss.fit_transform(mpg)
# ValueError: could not convert string to float: 'usa'

ColumnTransformer를 적용해보자.

from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder
from sklearn.neighbors import KNeighborsRegressor

pipe1 = Pipeline([('imputer', SimpleImputer(strategy='median'))]) # fit 안할거라서 끝에 estimator 안씀
pipe2 = Pipeline([('oh', OneHotEncoder())])
pipe3 = Pipeline([('ss', StandardScaler())])

ct = ColumnTransformer([
    # 이름, 파이프, 적용시킬 컬럼
    ('im',pipe1,['horsepower']),
    ('o', pipe2,['origin']),
    ('s', pipe3,['cylinders', 'displacement'])
])

pipe = Pipeline([('ct', ct), ('knn', KNeighborsRegressor())])

grid3 = GridSearchCV(pipe, {'ct__im__imputer__strategy':['median', 'mean']})
# 파라미터 이름은 vars(pipe)로 확인

grid3.fit(X_train, y_train)

pd.DataFrame(grid3.cv_results_)

Leave a comment