#!/usr/bin/env python3


asymmetric parameter with grid search


이전 포스팅 참조하기

SVC: [1]Kernelized Support Vector Machines


예를들어 SVCkernel parameter를 가지고 있는데 어떤 kernel을 사용하는지에 따라 관련있는 parameter들이 결정됩니다.

kernel='linear'이면 C parameter만 사용하고

kernel='rbf'이면 C와 gamma를 모두 사용합니다.


이런 경우에 kernel, C, gamma parameter의 모든 조합을 조사하는 것은 낭비입니다.


1. apply asymmetric parameter

이런 조건부 parameter조합을 적용하려면 GridSearchCV에 전달한 param_grid를 딕셔너리의 리스트로 만들기만 하면 됩니다.

# load library

from sklearn.datasets import load_breast_cancer

from sklearn.model_selection import train_test_split, KFold, GridSearchCV

from sklearn.svm import SVC


# datasets

cancer = load_breast_cancer()


# data paritition

x_train, x_test, y_train, y_test =\

  train_test_split(cancer.data, cancer.target,

                   random_state=0, test_size=0.3, stratify=cancer.target)


# create class

svc = SVC()

kfold = KFold(n_splits=5, shuffle=True, random_state=0)


values = [0.001, 0.01, 0.1, 1, 10, 100]

param_grid = [{'kernel':['rbf'], 'C':values, 'gamma':values},

               {'kernel':['linear'], 'C':values}]


grid_search = GridSearchCV(svc, param_grid, cv=kfold)

grid_search.fit(x_train, y_train)


# results

print('optimal parameter ==> {}'.format(grid_search.best_params_))

print('optimal parameter의 점수 ==> {:.3f}'.format(grid_search.best_score_))

print('optimal parameter로 일반화 점수 ==> {:.3f}'.format(grid_search.score(x_test, y_test)))

# optimal parameter ==> {'C': 100, 'kernel': 'linear'}

# optimal parameter의 점수 ==> 0.970

# optimal parameter로 일반화 점수 ==> 0.924



2. cv_results_ 결과 살펴보기

다음으로 cv_results_ 속성을 살펴보기 위해 pandas의 DataFrame으로 csv를 만든 후 일부만 보겠습니다.

# library import

import pandas as pd


results = pd.DataFrame(grid_search.cv_results_)


# write csv

results.T.to_csv('grid_search.cv_results_.csv')

cv_results_의 일부

>> kernel이 'linear'일 때는 'C'값만 변한 것을 확인할 수 있습니다.



참고 자료: 

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


'모델 평가와 성능 향상 > 그리드 서치' 카테고리의 다른 글

nested cross-validation  (1) 2018.04.05
cross-validation result analysis  (2) 2018.04.05
parameter overfitting  (0) 2018.04.04
simple grid search  (1) 2018.04.03

#!/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

'모델 평가와 성능 향상 > 그리드 서치' 카테고리의 다른 글

nested cross-validation  (1) 2018.04.05
asymmetric parameter with grid search  (0) 2018.04.05
parameter overfitting  (0) 2018.04.04
simple grid search  (1) 2018.04.03

#!/usr/bin/env python3


Simple Grid Search


머신러닝의 성능을 높이는 방법에는 여러가지가 있지만

여기서는 매개변수를 튜닝하여 일반화 성능을 높이는 것목표입니다.

가장 널리 사용하는 방법은 grid search그리드 서치 이며

관심있는 매개변수들을 대상으로 가능한 모든 조합을 시도해보는 것입니다.


SVM의 경우 

커널의 폭에 해당하는 gamma와 규제 매개변수 C가 중요합니다.

SVM에 더 자세한 정보는 이전 포스팅을 참조하세요

[1]Kernelized Support Vector Machines

매개변수 C와 gamma에 [0.001, 0.01, 0.1, 1, 10, 100] 값을 적용해보면

조합의 수는 총 6x6=36개가 나오며


모든 조합을 살펴보기 위해 SVM 매개변수 설정 테이블을 다음처럼 만들 수 있습니다.

매개 변수 설정 테이블


간단한 grid search의 경우는 아래처럼 코드를 짤 수 있습니다.

# library import

from sklearn.svm import SVC

from sklearn.model_selection import train_test_split

from sklearn.datasets import load_iris


# data load

iris = load_iris()


# data partition

x_train, x_test, y_train, y_test = \

  train_test_split(iris.data, iris.target,

                   test_size=0.3, random_state=0)


print('train set size:{}, test set size:{}'.format(x_train.shape, x_test.shape))

# train set size:(105, 4), test set size:(45, 4)


# grid search

best_score = 0

values = [0.001, 0.01, 0.1, 1, 10, 100]

for g in values:

    for c in values:

        svc = SVC(gamma=g, C=c).fit(x_train, y_train)

        score = svc.score(x_test, y_test)

        if score > best_score:

            best_score = score

            best_param = {'C':c, 'gamma':g}


print('best score ==> {:.3f}'.format(best_score))

print('best parameter ==> {}'.format(best_parameter))

# best score ==> 0.978

# best parameter ==> {'C': 100, 'gamma': 0.001}

>> grid search를 통해 C=100, gamma: 0.001일 때 가장 좋은 결과가 나온 것을 확인할 수 있습니다.

이 결과를 보면 이 데이터셋에서 모델 정확도가 97.8%라고 보고할 수 있습니다.


하지만 이런 주장은 다음과 같은 이유로 잘못될 수도 있습니다.

1. 이 정확도는 새로운 데이터까지 이어지지 않을 수 있습니다.

매개변수를 조정하기 위해 테스트 세트를 이미 사용했기 때문에 테스트세트는 모델이 얼마나 좋은지 평가하는 데 사용할 수 없습니다.

즉 평가를 위해서는 모델을 만들 때 사용하지 않은 독립된 데이터셋이 필요하고 

다음 장에서 독립된 데이터셋을 다루는 방법을 살펴보겠습니다.



참고 자료: 

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

'모델 평가와 성능 향상 > 그리드 서치' 카테고리의 다른 글

nested cross-validation  (1) 2018.04.05
asymmetric parameter with grid search  (0) 2018.04.05
cross-validation result analysis  (2) 2018.04.05
parameter overfitting  (0) 2018.04.04

+ Recent posts