11. 교차검증 & 그리드서치

akanana·2023년 1월 16일
0

개인공부

목록 보기
23/30
post-thumbnail

검증세트

모델의 과소/과대 적합을 판단하기 위해 훈련세트를 또 나눈것을 의미한다

import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')

data = wine[['alcohol','sugar','pH']].to_numpy()
target = wine['class'].to_numpy()

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = \
    train_test_split(data,target,test_size=0.2,random_state=42)

먼저 데이터를 받아 훈련세트테스트세트로 분류한다

sub_input, val_input, sub_target, val_target = \
    train_test_split(train_input,train_target,test_size=0.2,random_state=42)

그리고 훈련세트를 다시 train_test_split()을 통하여 훈련세트검증세트로 분류한다

from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)
print_score(dt,"dt")
# 0.997...
# 0.864...

교차검증

하지만, 위 과정을 통해 훈련세트의 수가 줄어들었다
그렇다고 검증세트를 너무 적게 할당시, 검증 점수가 불안정할것이다
이를 해결하기위해 교차검증을 사용 할 수 있다

위 그림처럼 여러 검증을 통한 검증 점수의 평균을 통하여 검증을 실시한다.

위 그림은 3개의 검증을 했으므로 3-폴드 교차 검증이라고 부른다
보통 5-폴드10-폴드교차검증을 이용한다

import numpy as np
from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
print(scores)
# {
# 	'fit_time': array([0., 0.015..., 0., 0.0156..., 0.]), 
#	'score_time': array([0., 0., 0., 0., 0.]), 
#	'test_score': array([0.869..., 0.846..., 0.876..., 0.848..., 0.835...])
# }
print(np.mean(scores['test_score']))
# 0.855...

fit_time : 훈련하는 시간
score_time : 검증하는 시간
test_score : 검증 점수
각 키마다 5개의 숫자가 있으므로, 기본적으로 5-폴드 교차 검증임을 알 수 있다
이때, 회귀모델은 KFold 분할기를, 분류모델은 StrtifiedKFold를 통해 데이터를 분류한다

from sklearn.model_selection import StratifiedKFold
splitter = StratifiedKFold()
scores = cross_validate(dt, train_input, train_target, cv=)
print(scores)
print(np.mean(scores['test_score']))

aksdir 10-폴드 교차 검증을 이용할때에는 다음과 같은 코드를 이용할 수 있다

splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
print(scores)
print(np.mean(scores['test_score']))

하이퍼 파라미터 튜닝

머신러닝에서 모델이 학습하는 파라미터를 모델 파라미터라고 한다
반면, 사용자가 직접 지정해야 하는 파라미터를 하이퍼 파라미터라고 한다
모델별 적게는 1개에서 많게는 5~6개까지도 되는 파라미터값을 직접 조정하여야 한다
이를 위해 우리는 그리드 서차를 사용 할 수 있다

GridSearchCV

위 클래스는 교차검증하이퍼 파라미터 탐색을 함께 진행해준다

from sklearn.model_selection import GridSearchCV
params = {'min_impurity_decrease':[0.0001,0.0002,0.0003,0.0004,0.0005]}
gs = GridSearchCV(DecisionTreeClassifier(random_state=42),params,n_jobs=-1)
gs.fit(train_input, train_target)
dt = gs.best_estimator_
# 최고 점수 출력
print(dt.score(train_input, train_target)) # 0.961...
# 최고 점수일때 파라미터 값 출력
print(gs.best_params_) # 0.0001
# 교차검증의 모든 점수 출력 
print(gs.cv_results_['mean_test_score']) 
# [0.868.. 0.864.. 0.864.. 0.867.. 0.867..]

더 복잡한 파라미터를 통해 값을 출력해보자

params = {'min_impurity_decrease':[0.0001,0.0002,0.0003,0.0004,0.0005],
          'max_depth': range(5,20,1),
          'min_samples_split': range(2,100,10)}
gs = GridSearchCV(DecisionTreeClassifier(random_state=42),params,n_jobs=-1)
gs.fit(train_input, train_target)

print(gs.best_params_)
# {'max_depth': 14, 'min_impurity_decrease': 0.0004, 'min_samples_split': 12}
print(np.max(gs.cv_results_['mean_test_score']))
# 0.868...

랜덤서치

교차검증을 통해 최적의 값을 찾을때, 파라미터의 범위를 정하기 모호하거나, 매개변수가 너무 많아 수행시간이 너무 오래 걸릴 수 있다
이럴때 우리는 랜덤서치를 통하여 값을 찾을 수 있다

uniform, randint 사용법

from scipy.stats import uniform, randint
import numpy as np
# 0~10 사이의 정수
rgen = randint(0,10)
# 10개 추출
print(rgen.rvs(10)) # [2 1 9 7 1 6 9 8 4 2]

# 1000개 추출 후, 개수
np.unique(rgen.rvs(1000),return_counts=True)
print(np.unique(rgen.rvs(1000),return_counts=True))
# (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64), 
# array([103, 114, 109, 102,  95,  76, 102,  92, 102, 105], dtype=int64))

# 0~1 사이의 실수
ugen = uniform(0,1)
# 10개 출력
print(ugen.rvs(10))
# [0.159.. 0.242.. 0.238.. 0.804.. 0.313.. 0.992.. 0.393.. 0.864.. 0.678.. 0.380..]

위 내용을 바탕으로 파라미터의 범위를 랜덤하게 설정하였다

params = {'min_impurity_decrease':uniform(0.0001,0.001),
          'max_depth': randint(20,50),
          'min_samples_split': randint(2,25),
          'min_samples_leaf': randint(1,25),}

그 후, 100번의 샘플링을 교차검증 후, 최적의 매개변수를 도출하였다

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import RandomizedSearchCV
gs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42), params,
                        n_iter=100,n_jobs=-1,random_state=42)
gs.fit(train_input, train_target)
print(gs.best_params_)
# {
#	'max_depth': 39, 
#	'min_impurity_decrease': 0.00034102546602601173, 
#	'min_samples_leaf': 7, 
#	'min_samples_split': 13
# }
print(np.max(gs.cv_results_['mean_test_score']))
# 0.869...

이제 테스트세트를 통해 테스트점수를 출력해보았다

dt = gs.best_estimator_
print(dt.score(test_input, test_target)) # 0.86

0개의 댓글