#!/usr/bin/env python3


Grid Search에 pipeline 적용


Grid Search에 pipeline을 사용하는 방식

parameter를 정의하고, 이 parameter 그리드와 pipeline으로 GridSearchCV의 객체를 만듭니다.

객체를 만들 때는 각 parameter가 pipeline의 어떤 단계에 속한 것인지 알려줘야 합니다.

C와 gamma parameter는 두 번째 단계인 SVC의 parameter입니다. 만약 이 단계의 이름이 'svc'라면 pipeline용 parameter 그리드는 단계 이름과 parameter 이름을 '__'로 연결합니다.

그래서 SVC의 parameter C를 Grid Search로 탐색하려면 parameter Grid dictionary의 키를 'svc__C'로 해야합니다.

import numpy as np

from sklearn.pipeline import Pipeline

from sklearn.datasets import load_breast_cancer

from sklearn.model_selection import train_test_split, GridSearchCV

from sklearn.preprocessing import MinMaxScaler

from sklearn.svm import SVC


cancer = load_breast_cancer()

x_train, x_test, y_train, y_test = train_test_split(cancer.data, cancer.target,

                                                    stratify=cancer.target, random_state=0)


scaler_tuple = ('scaler', MinMaxScaler())

model_tuple = ('svc', SVC())


pipe = Pipeline([scaler_tuple, model_tuple])

pipe.fit(x_train, y_train)


values = np.array([0.001, 0.01, 0.1, 1, 10, 100])

params = {'svc__C':values, 'svc__gamma':values}


grid = GridSearchCV(pipe, param_grid=params, cv=5)

grid.fit(x_train, y_train)


print('optimal train score: {:.3f}'.format(grid.best_score_))

# optimal train score: 0.984


print('test score: {:.3f}'.format(grid.score(x_test, y_test)))

# test score: 0.951


print('optimal parameter: {}'.format(grid.best_params_))

# optimal parameter: {'svc__C': 10.0, 'svc__gamma': 0.1}



이전 포스팅 참조하기

Grid Search: [1]pipeline


이전 포스팅에서 본 그리드 서치와 다른 점은 교차 검증의 각 분할에 MinMaxScaler가 훈련 폴드에 매번 적용되어, 매개변수 검색 과정에서 검증 폴더의 정보가 누설되지 않은 것입니다.

import matplotlib.pyplot as plt

from mglearn.plots import plot_proper_processing


plot_proper_processing()

plt.show()

교차 검증 반복 안에서 전처리가 될 때 데이터 사용 형태




교차 검증에서 정보 누설에 의한 영향은 전처리 종류에 따라 다릅니다. 검증 폴드를 사용해 데이터의 스케일을 조정하는 경우엔 심각한 문제가 생기지 않지만, 검증 폴드를 이용해 특성을 추출하거나 선택하면 결과가 확연히 달라집니다. 다음 코드로 이 것을 확인할 수 있습니다.

rnd = np.random.RandomState(seed=0)

x = rnd.normal(size=(100, 10000))

y = rnd.normal(size=(100,))


데이터셋을 무작위로 생성해서 데이터x와 타깃 y사이에는 아무런 관계가 없습니다(즉 독립입니다.) 그러므로 이 데이터셋으로 무언가를 학습하기는 불가능합니다. SelectPercentile로 10,000개 중 가장 유용한 특성을 선택하고 교차 검증을 사용하여 Ridge회귀를 평가 하겠습니다.

from sklearn.feature_selection import SelectPercentile, f_regression


select = SelectPercentile(score_func=f_regression, percentile=5)

select.fit(x, y)


x_selected = select.transform(x)

print('{}'.format(x_selected.shape))

# (100, 500)


from sklearn.model_selection import cross_val_score

from sklearn.linear_model import Ridge


cv_score = cross_val_score(Ridge(), x_selected, y, cv=5)

print('ridge score: {:.3f}'.format(np.mean(cv_score)))

# ridge score: 0.915

교차 검증으로 계산한 평균 R-square는 91.5%로 매우 좋은 모델입니다. 데이터셋을 완전히 무작위로 만들었으니 있을 수 없는 일입니다. 교차 검증 밖에서 특성을 선택했기 때문에 훈련과 테스트 폴드 양쪽에 연관된 특성이 찾아 질 수 있습니다.

테스트 폴드에서 유출된 정보는 매우 중요한 역할을 하기 때문에 비현실적으로 높은 결과가 나왔습니다.



select_tuple = ('select', SelectPercentile(score_func=f_regression, percentile=5))

model_tuple = ('ridge', Ridge())


pipe = Pipeline([select_tuple, model_tuple])

cv_score_pipe = cross_val_score(pipe, x, y, cv=5)

print('ridge score(pipe): {:.3f}'.format(np.mean(cv_score_pipe)))

# ridge score(pipe): -0.086

이번에는 R-square가 음수라 성능이 매우 낮은 모델임을 나타냅니다. 파이프라인을 사용했기 때문에 특성 선택이 교차 검증 반복 안으로 들어갔습니다. 이 말은 훈련 폴드를 사용해서만 특성이 선택되었고 테스트 폴드는 사용하지 않았다는 뜻입니다. 특성 선택 단계에서 훈련 폴드의 타깃값과 연관된 특성을 찾았지만, 전체 테이터가 무작위로 만들어졌으니 테스트 폴드의 타깃과는 연관성이 없습니다. 이 예는 특성 선택 단계에서 일어나는 정보 누설을 막는 것이 모델의 성능을 평가하는데 큰 차이를 만든다는 것을 보여줍니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'algorithm chain & pipeline > pipeline' 카테고리의 다른 글

pipeline  (0) 2018.04.20

+ Recent posts