머신러닝

[머신러닝] Pipeline

서노리 2022. 6. 8. 03:32
반응형

이전 포스팅에서 다룬 GridSearchCV 클래스를 통해 머신러닝 모델의 최적의 파라매터를 찾는 방법을 배웠다.
하지만 실전 데이터를 다루면서 중간에 전처리 과정이 들어가게 되면 GridSearchCV를 사용할 때 주의할 점이 생긴다.
다음 예제를 통해 무엇이 문제인지 생각해보자.

from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(
    X, y,
    test_size=0.3,
    stratify=y,
    random_state=11)
    
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler().fit(X_train)

X_train_scaled=scaler.transform(X_train)
X_test_scaled=scaler.transform(X_test)

데이터를 불러와서 분할한 후 StandardScaler로 전처리를 하는 과정이다.
scaler에 학습 데이터를 모두 적용시키고 변환을 완료하였다.

 

from sklearn.model_selection import KFold, GridSearchCV
from sklearn.linear_model import LogisticRegression

param_grid=[{'penalty' : ['l2'],
            'solver' : ['lbfgs'],
            'C' : [1.0,0.1,10,0.01,100],
            'class_weight': ['balanced',{0:0.9,1:0.1}]},
            {'penalty' : ['elasticnet'],
            'solver' : ['saga'],
            'C' : [1.0,0.1,10,0.01,100],
            'class_weight': ['balanced',{0:0.9,1:0.1}]}]

cv = KFold(n_splits=5,shuffle=True,random_state=11)
base_model = LogisticRegression(n_jobs=-1,random_state=11)
grid_model = GridSearchCV(base_model, param_grid=param_grid, cv=cv,
                          scoring='f1', n_jobs=-1)

grid_model.fit(X_train_scaled,y_train)

# 학습된 머신러닝 모델의 평가
print(f'SCORE(TRAIN) : {grid_model.score(X_train_scaled, y_train)}')
print(f'SCORE(TEST) : {grid_model.score(X_test_scaled, y_test)}')

이제 모델을 불러와 grid search를 수행하여 최적의 파라매터를 찾아주고
완성된 모델로 학습 평가 및 테스트 성능을 평가해준다.

 

보기에는 완벽해보이는 과정이지만 문제점이 있는 코드이다.

문제는 학습 데이터를 모두 전처리한 후 그걸로 교차검증이 이루어진다는 점이다.

 

Pipeline을 사용해 데이터의 전처리 과정 및 모델의 학습 과정을 연결해줌으로써 이런 문제를 해결할 수 있다.


Pipeline

※ 파이프라인 객체의 생성

Pipeline([('1번째 변환기 클래스 객체의 이름', 객체), ('2번째 변환기 클래스 객체의 이름', 객체) ... ])

 

- 파이프라인의 마지막 객체를 제외한 나머지 객체들은 transform, fit_transform 메소드를 제공하는 변환기만 허용
- 파이프라인의 마지막 객체는 predict 메소드를 제공하는 예측기가 될 수 있음

 

※ 파이프라인의 실행 과정

1. fit 메소드가 호출되는 경우

- 입력된 X 데이터를 첫 번째 변환기로 전달하여 fit_transform

- 변환된 결과를 다음 변환기 / 예측기로 전달

- 변환기라면 fit_transform 반복, 예측기라면 fit 후 종료

2. score / predict 메소드가 호출되는 경우

- 입력된 X 데이터를 첫번째 변환기로 전달하여 transform

- 변환된 결과를 다음 변환기 / 예측기로 전달

- 변환기라면 transform 반복, 예측기라면 score / predict 메소드의 실행 결과 반환

Pipeline 예제

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()

# Pipeline을 예측기로 사용하는 GridSearchCV 클래스의
# 파라메터 정보는 키 값의 형태를 
# 파이프라인의예측기객체명__파라메터이름
param_grid=[{'base_model__penalty' : ['l2'],
            'base_model__solver' : ['lbfgs'],
            'base_model__C' : [1.0,0.1,10,0.01,100],
            'base_model__class_weight': ['balanced',{0:0.9,1:0.1}]},
            {'base_model__penalty' : ['elasticnet'],
            'base_model__solver' : ['saga'],
            'base_model__C' : [1.0,0.1,10,0.01,100],
            'base_model__class_weight': ['balanced',{0:0.9,1:0.1}]}]
            
            
cv = KFold(n_splits=5,shuffle=True,random_state=11)
base_model = LogisticRegression(n_jobs=-1,random_state=11)

from sklearn.pipeline import Pipeline
pipe = Pipeline([('s_scaler',scaler),('base_model',base_model)])

grid_model = GridSearchCV(pipe, param_grid=param_grid, cv=cv,
                          scoring='f1', n_jobs=-1)
grid_model.fit(X_train,y_train)

# 학습된 머신러닝 모델의 평가
print(f'SCORE(TRAIN) : {grid_model.score(X_train, y_train)}')
print(f'SCORE(TEST) : {grid_model.score(X_test, y_test)}')

GridSearchCV의 estimator에 pipe를 넣어 객체를 생성한 모습이다.

이렇게 되면 5개의 폴드 중 4개의 폴드를 전처리 한 후 학습을 진행하고
나머지 하나의 폴드는 기존의 4개의 폴드로 전처리된 변환기 클래스에 의해 transform 되어 예측에 사용된다.

GridSearchCV는 이러한 과정을 통해 교차검증 score가 가장 높은 파라메터를 찾아주게 된다.


 

반응형