#!/usr/bin/env python3
cross-validation result analysis
이전 포스팅에서 parameter overfitting을 다뤘습니다.
GridSearchCV를 활용하여 최적 매개변수를 찾고, 이를 이용하여 모델의 성능을 향상시켰습니다.
이번 포스팅에서는 GridSearchCV의 결과를 분석해보겠습니다.
cross-validation의 결과를 시각화 하면 검색 대상 매개변수가 모델의 일반화에 영향을 얼마나 주는지 알 수가 있습니다.
grid search는 연상 비용이 매우 크므로 비교적 간격을 넓게 하여 적은 수의 grid로 시작하는 것이 좋습니다.
그 다음 cross-validation의 결과를 분석하여 검색을 확장해 나갈 수 있습니다.
grid search의 결과는 cv_results_에 담겨 있어 DataFrame형태로 변환해서 보는 것이 도움이 됩니다.
1. iris 데이터셋으로 분석
# load library
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, KFold, GridSearchCV
from sklearn.svm import SVC
# datasets
iris = load_iris()
# data partition
x_train, x_test, y_train, y_test =\
train_test_split(iris.data, iris.target,
random_state=0, test_size=0.3)
# create object
svc = SVC()
kfold = KFold(n_splits=10, shuffle=True, random_state=0) # stratified cross-validation
# param_grid
values = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
param_grid = {'C':values, 'gamma':values}
# GridSearch
grid_search = GridSearchCV(svc, param_grid, cv=kfold)
grid_search.fit(x_train, y_train)
# result
print('최적 매개변수 점수 ==> {:.3f}'.format(grid_search.best_score_))
print('최적 매개변수 ==> {}'.format(grid_search.best_params_))
print('최적 매개변수의 테스트 점수 ==> {:.3f}'.format(grid_search.score(x_test, y_test)))
# 최적 매개변수 점수 ==> 0.981
# 최적 매개변수 ==> {'C': 10, 'gamma': 0.1}
# 최적 매개변수의 테스트 점수 ==> 0.978
import pandas as pd
results = pd.DataFrame(grid_search.cv_results_)
print('results \n{}'.format(results.head()))
DataFrame으로 표현한 grid_search.cv_results_
>> results의 행 하나는 특정한 하나의 매개변수 설정에 대응하며 각 설정에 대해 cross-validation의 모든 분할의 평균값, 표준편차를 포함한 결과가 기록되어 있습니다.
검색 대상 parameter grid가 2개 이므로, heatmap으로 시각화하기에 좋습니다.
2. 검색 결과를 heatmap으로 시각화
heatmap으로 시각화 하려면 각 parameter를 축으로 하는 numpy 배열을 만들어야합니다.
7개의 grid를 사용했으므로 cross-validation의 평균을 7x7형태로 차원을 바꿔야합니다.
# library import
import mglearn
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable # colorbar의 크기를 정하기 위한 축 library
# matplotlib 설정
matplotlib.rc('font', family='AppleGothic') # 한글 출력
plt.rcParams['axes.unicode_minus'] = False # 축 -
# values = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
# param_grid = {'C':values, 'gamma':values}
# 차원 변형
mean_score = results['mean_test_score'].reshape(7, 7)
# 시각화
score_image = mglearn.tools.heatmap(mean_score, xlabel='gamma', xticklabels=param_grid['gamma'],
ylabel='C', yticklabels=param_grid['C'])
ax = plt.gca() # GetCurrentAxis
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad='5%')
plt.colorbar(score_image, cax=cax)
plt.show()
gamma와 C값에 따른 cross-validation 평균 점수의 heatmap
>> heatmap의 각 포인트는 특정 parameter 설정에 대한 cross-validation 실행에 대응됩니다. cross-validation의 정확도가 높을 수록 밝은색으로, 낮을 수록 어두운색으로 표현 됩니다. parameter에 따라서 다양한 색깔 포인트들이 존재하는 것은 그 만큼 모델이 parameter 설정에 민감하다는 것을 나타냅니다.
3. parameter가 적절하게 선택되지 않은 예
parameter 설정에 민감하기 때문에 범위가 중요하며 검색 범위가 적절하게 선택되지 않은 예를 살펴보겠습니다.
# library import
import mglearn
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable # colorbar 조정하기 위한 그래프 축 library
import numpy as np
# subplots
_, axes = plt.subplots(1, 3)
# param_grid
param_grid_linear = {'C':np.linspace(1, 2, num=6),
'gamma': np.linspace(1, 2, num=6)}
param_grid_log = {'C':np.linspace(1, 2, num=6),
'gamma':np.logspace(-3, 2, num=6)}
param_grid_range = {'C':np.logspace(-3, 2, num=6),
'gamma':np.logspace(-7, -2, num=6)}
# visualization
param_grid_sets = [param_grid_linear, param_grid_log, param_grid_range]
for p, ax in zip(param_grid_sets, axes.ravel()):
svc = SVC()
kfold = KFold(n_splits=10, shuffle=True, random_state=0) # [1]stratified cross-validation(교차검증)--은 이전 포스팅 참조 하세요
grid_search = GridSearchCV(svc, param_grid=p, cv=kfold) # GridSearch(estimator, param_grid, cv)
grid_search.fit(x_train, y_train)
mean_score = grid_search.cv_results_['mean_test_score'].reshape(6, 6)
score_image = mglearn.tools.heatmap(mean_score, xlabel='gamma', xticklabels=p['gamma'],
ylabel='C', yticklabels=p['C'], ax=ax)
axis = plt.gca() # GetCurrentAxis
divider = make_axes_locatable(axis)
cax = divider.append_axes('right', size='5%', pad='5%')
plt.colorbar(score_image, ax=axes.tolist() ,cax=cax)
plt.show()
적절하지 않은 parameter grid의 heatmap
>> [1] 첫 번째 그래프는 점수 변화가 전혀 없어서 전체 parameter grid가 거의 같은 색입니다. 이런 결과는 parameter의 스케일 범위가 부적절할 때 발생합니다.
그러나 parameter 설정이 바뀌어도 아무런 변화가 없다면, 그 parameter가 중요하지 않은 것일 수도 있습니다.
처음에는 극단적인 값을 적용하고, parameter를 바꿔가며 정확도를 살펴보는 것을 추천합니다.
[2] 두 번째 그래프는 세로 띠 형태입니다. 이 것은 C에 상관없이 gamma만 정확도에 영향을 준다는 것입니다.
gamma는 적절한 범위지만 C는 그렇지 못한 것이며, 혹은 중요하지 않은 것일 수도 있습니다.
[3] 세 번째 그래프는C와 gamma 둘 모두에 따라 값이 변했습니다. 하지만 그래프 왼쪽 아래 부분에서는 아무런 변화가 없습니다. 최적치가 그래프의 경계에 있으니 이 경계 너머에 더 좋은 값이 있다고 생각할 수 있고, 이 영역이 포함되도록 parameter 검색 범위를 바꿔줘야 함
cross-validation 점수를 토대로 parameter grid를 튜닝하는 것은 아주 안전한 방법이며, parameter들의 중요도를 확인하는데도 좋습니다. 그러나 최종 테스트 세트를 대상으로 여러 parameter 범위를 테스트해서는 안됩니다.
여태까지 대칭적 parameter grid만 탐색했지만(C가 6개면, gamma도 6개) 다음 포스트에서는 비대칭 매개변수 grid 탐색을 다뤄 보겠습니다.
참고 자료:
[1]Introduction to Machine Learning with Python, Sarah Guido