모델의 과소/과대 적합을 판단하기 위해 훈련세트를 또 나눈것을 의미한다
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개까지도 되는 파라미터값을 직접 조정하여야 한다
이를 위해 우리는 그리드 서차
를 사용 할 수 있다
위 클래스는 교차검증
및 하이퍼 파라미터
탐색을 함께 진행해준다
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...
교차검증을 통해 최적의 값을 찾을때, 파라미터의 범위를 정하기 모호하거나, 매개변수가 너무 많아 수행시간이 너무 오래 걸릴 수 있다
이럴때 우리는 랜덤서치
를 통하여 값을 찾을 수 있다
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