사이킷런의 전처리 과정을 간단하게 할 수 있는 방법 중 하나가 pipeline
이다. pipeline이란 여러 단계의 머신러닝 프로세스 (전처리의 각 단계, 모델생성, 학습) 처리 과정을 묶어서 한번에 처리하기 위한 기술을 의미한다. pipeline을 사용하는 모습을 예시로 확인해본다.
<예시>
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
order = [
("scaler",StandardScaler()),
("svm",SVC())
]
from sklearn.pipeline import Pipeline
pipeLine = Pipeline(order, verbose=True) # 파이프라인 생성
# X_train, y_train 데이터 있다고 가정
pipeLine.fit(X_train, y_train) # 파이프라인을 이용한 학습
pred_train = pipeLine.predict(X_train) # 파이프라인을 이용한 예측
pred_test = pipeLine.predict(X_test)
print(accuracy_score(y_train, pred_train))
print(accuracy_score(y_test, pred_test))
위 코드는 X_train데이터를 StandardScaler()로 표준화해주고, 표준화된 데이터를 SVC()모델로 학습시켜주는 일련의 작업을 pipeline으로 한번에 처리하는 코드다.
이때 만약 X_train데이터에 StandardScaler()로 표준화할 수 있는 연속형 feature도 존재하지만 StandardScaler()로 표준화할 수 없는 범주형 feature도 존재할 수 있다. 이럴 경우 X_train의 특정 feature들에만 따로 따로 전처리를 해주고 싶다면 어떻게 해야할까? 이때 사용되는 것이 BaseEstimator
와 TransformerMixin
다.
원리는 다음과 같다. pipeline은 매개변수로 튜플들을 담은 리스트에 원하는 작업들을 튜플형태로 넣어줘야 하는데, 이 때 넣어줄 함수자체를 따로 만들어주는 형식이다.(정확히는 클래스) 다음 예시를 통해 알아본다.
다음과 같은 train데이터프레임이 존재한다고 가정한다.
row_id | date | country | store | product | num_sold | |
---|---|---|---|---|---|---|
0 | 0 | 2017-01-01 | Belgium | KaggleMart | Kaggle Advanced Techniques | 663 |
1 | 1 | 2017-01-01 | Belgium | KaggleMart | Kaggle Getting Started | 615 |
2 | 2 | 2017-01-01 | Belgium | KaggleMart | Kaggle Recipe Book | 480 |
3 | 3 | 2017-01-01 | Belgium | KaggleMart | Kaggle for Kids: One Smart Goose | 710 |
4 | 4 | 2017-01-01 | Belgium | KaggleRama | Kaggle Advanced Techniques | 240 |
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
class myscaler(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
scaler = StandardScaler()
X["num_sold"] = scaler.fit_transform(pd.DataFrame(X["num_sold"]))
le1 = LabelEncoder()
X["country"] = le1.fit_transform(X["country"])
le2 = LabelEncoder()
X["store"] = le2.fit_transform(X["store"])
le3 = LabelEncoder()
X["product"] = le3.fit_transform(X["product"])
return X
pipe = Pipeline([
("first_scaling", myscaler())
])
pipe.fit_transform(train)
위 코드에서 myscaler 클래스의 transform 메서드를 확인해보면 train 데이터프레임의 num sold
feature에는 StandardScaler()로 표준화를 해주고 train 데이터프레임의 country
, store
, product
feature에는 LabelEncoder()로 범주형 전처리를 함을 확인할 수 있다.
위와 같은 class를 만드는 방식을 기억하면, pipeline을 이용할 때 특정 열에만 원하는 작업을 처리할 수 있다. myscaler함수는 BaseEstimator
와 TransformerMixin
이라는 클래스를 상속받고 있다. BaseEstimator는 get_params 메서드와 set_params 메서드를 가지고 있어서 이 두 메서드를 상속받아 하이퍼파라미터를 변경하는데 사용한다. TransformerMixin은 fit_transform 메서드를 가지고 있어서 이 메서드를 상속받아 데이터를 학습 및 변환을 하는데 사용한다.
즉, 우리가 만들어야 할 부분은 fit 메서드와 transform 메서드다. fit 메서드와 transform 메서드는 위에 코드를 참고하여 형태를 익혀놓으면 좋을 듯하다.
참고한 블로그 : https://databuzz-team.github.io/2018/11/11/make_pipeline/