#!/usr/bin/env python3


parameter overfitting


이전 포스팅에서 평가를 위해서는 모델을 만들 때 사용하지 않은 독립된 데이터셋이 필요하다고 했습니다.

독립된 데이터셋을 사용하는 방법에는 2가지가 있습니다.

첫 번째는 train_test_split을 2번 사용하여 데이터를 3등분하는 것이고

두 번째는 cross-validation을 사용하는 것입니다.


우선 첫 번째 방법부터 살펴보겠습니다. 이 방법은 아래 소스를 통해 그래프로 확인할 수 있습니다.

# library import

import mglearn

import matplotlib

import matplotlib.pyplot as plt


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic'# 한글폰트

plt.rcParams['axes.unicode_minus'] = False # 축 -


mglearn.plots.plot_threefold_split()

plt.show()

training set, validation set, test set의 3개의 폴드로 나눈 데이터



1. train_test_split을 이용한 iris데이터의 grid search

이번에는 iris 데이터로 살펴보겠습니다.

# load library

from sklearn.svm import SVC

from sklearn.model_selection import train_test_split

from sklearn.datasets import load_iris


# data load

iris = load_iris()


# train_test_split 1번

x_trainvalid, x_test, y_trainvalid, y_test=\

  train_test_split(iris.data, iris.target, random_state=0)


# train_test_split 2번

x_train, x_valid, y_train, y_valid =\

  train_test_split(x_trainval, y_trainval, random_state=1)  


print('x_train size:{}\nx_valid size:{}\nx_test size:{}'.format(x_train.shape, x_valid.shape, x_test.shape))

# x_train size:(84, 4)

# x_valid size:(28, 4)

# x_test size:(38, 4)


# grid search

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

best_score = 0

for g in values:

    for c in values:

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

        scores = svc.score(x_valid, y_valid) # 검증세트로 svc를 평가


        if scores > best_score:

            best_score = scores

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

            

svc = SVC(**best_param).fit(x_trainvalid, y_trainvalid) # **kwargs: 딕셔너리 형태로 함수에 인자를 넘김

score_svc = svc.score(x_test, y_test)


print('최적 매개변수 점수 ==> {:.3f}'.format(best_score))

print('최적 매개변수 ==> {}'.format(best_param))

print('최적 매개변수에서 test ==> {:.3f}'.format(score_svc))

# 최적 매개변수 점수 ==> 0.964

# 최적 매개변수 ==> {'C': 10, 'gamma': 0.001}

# 최적 매개변수에서 test ==> 0.921


>> 최적 매개변수에서 최고점수는 96.4%이며 테스트 세트 점수는 92.1%입니다. 

새로운 데이터에 대해 92.1%만 정확하게 분류한다고 볼 수 있습니다.

테스트 세트로 둘 이상의 모델을 평가해서 그 중 더 나은 하나를 선택하는 것은 모델의 정확도를 매우 낙관적으로 추정하거나, 

overfitting이 생길 수 있으므로 주의해야합니다.


2. cross-validaion을 이용한 iris데이터의 grid search


일반화 성능을 더 잘 평가하려면 훈련 세트와 검증 세트를 한 번만 나누지 않고 

cross-validation을 사용해서 각 매개변수 조합의 성능을 평가할 수 있습니다.


cross-validation을 통해 어떤 매개변수가 선택되는지를 살펴보면

# library import

import mglearn

import matplotlib.pyplot as plt


mglearn.plots.plot_cross_val_selection()

plt.show()

cross-validation을 사용한 grid search의 결과


>> [0.001, 0.01, 0.1, 1, 10, 100]를 C와 gamma로 각각 설정한 후, cross-validation 에 한개씩, 모두 5개의 값을 계산합니다.

총 6x6x5 = 180개의 모델을 만들어서 모델 검정을 하기때문에 시간이 오래 걸립니다.


# library import

import numpy as np

from sklearn.svm import SVC

from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split


# 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)


# grid search

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

best_score = 0

for g in values:

    for c in values:

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

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

        scores = cross_val_score(svc, x_train, y_train, cv=kfold)

        score = np.mean(scores)


        if score > best_score:

            best_score = score

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


# 최적 매개변수로 모델을 다시 만듬             

svc = SVC(**best_param).fit(x_train, y_train)

print('최적 매개변수 점수 ==> {:.3f}'.format(best_score))

print('최적 매개변수 ==> {}'.format(best_param))

print('최적 매개변수에서 test ==> {:.3f}'.format(svc.score(x_test, y_test)))

# 최적 매개변수 점수 ==> 0.981

# 최적 매개변수 ==> {'gamma': 0.01, 'C': 100}

# 최적 매개변수에서 test ==> 0.978



cross-validation을 사용한 grid search를 매개변수 조정 방법으로 많이 사용하기 때문에

scikit-learn은 GridSearchCV를 제공합니다.


GridSearchCV는 딕셔너리 형태로 검색 대상 매개변수를 지정하며 필요한 모든 모델을 학습합니다. 아래 소스는 위의 소스와 같은 결과를 냅니다.

# library import

from sklearn.svm import SVC

from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split, GridSearchCV, KFold


# data load

iris = load_iris()


# data parition

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() # SVC모델 생성

kfold = KFold(n_splits=5, shuffle=True, random_state=0) # cross-validation 


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

param_grid = {'gamma':values, 'C':values}  # GridSearchCV의 딕셔너리 생성


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

grid_search.fit(x_train, y_train)


score = grid_search.score(x_test, y_test)

print('GridSearchCV를 이용한 최적 매개변수 점수 ==> {:.3f}'.format(grid_search.best_score_))

print('GridSearchCV를 이용한 최적 매개변수 ==> {}'.format(grid_search.best_params_))

print('GridSearchCV를 이용한 test점수 ==> {:.3f}'.format(score))

print('GridSearchCV를 이용한 최고 성능 모델 ==> \n{}'.format(grid_search.best_estimator_))

# GridSearchCV를 이용한 최적 매개변수 점수 ==> 0.981

# GridSearchCV를 이용한 최적 매개변수 ==> {'C': 10, 'gamma': 0.1}

# GridSearchCV를 이용한 test점수 ==> 0.978

# GridSearchCV를 이용한 최고 성능 모델 ==> 

#SVC(C=10, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma=0.1, kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False)


>> 이 소스는 더 간결해졌지만 많은 내용을 함축하고 있습니다.

다음에는 GridSearchCV를 통해 cross-validation 결과를 시각화 해보겠습니다.



참고 자료: 

[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
simple grid search  (1) 2018.04.03

+ Recent posts