[혼공머]교차 검증과 그리드 서치

ai_lim·2022년 1월 21일
0

혼공머신

목록 보기
7/14
  • 검증 세트
    하이퍼파라미터 튜닝을 위해 모델을 평가할 때, 테스트 세트를 사용하지 않기 위해 훈련 세트에서 다시 떼어 낸 데이터 세트

  • 교차 검증
    훈련세트를 여러 폴드로 나눈 다음 한 폴드가 검증세트의 역할을 하고 나머지 폴드에서는 모델 훈련을 한다. 모든 폴드에 대해서 검증 점수를 얻어 평균하는 방법이다.

  • 그리드 서치
    하이퍼파라미터 탐색을 자동화해주는 도구이다. 탐색할 매개변수를 나열하면 교차검증을 수행하여 가장 좋은 검증 점수의 매개변수의 조합을 선택한다. 마지막으로 이 매개변수의 조합으로 최종모델을 훈련한다.

  • 랜덤 서치
    연속된 매개변수의 값을 탐색할 때 유용하다. 탐색할 값을 직접 나열하는 것이 아닌 샘플링할 수 있는 확률 분포 객체를 전달한다. 지정된 횟수만큼 샘플링하여 교차검증을 수행하기때문에 탐색량을 조절할 수 있다.

  • cross_validate()
    교차검증을 수행하는 함수이다.

  • GridSearchCV
    교차검증으로 하이퍼파라미터 탐색을 수행한다. 최상의 모델을 찾은 후 훈련세트 전체를 사용해 최종모델을 훈련한다.

  • RandomizedSearchCV
    교차검증으로 랜덤한 하이퍼파라미터 탐색을 수행한다. 최상의 모델을 찾은 후 훈련세트 전체를 사용해 최종모델을 훈련한다.

검증 세트


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

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)
  • 훈련/ 테스트 데이터 분리
  • 훈련데이터 안에서 검증 데이터를 또 분리

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)

print(dt.score(sub_input, sub_target))
print(dt.score(val_input, val_target))
  • 과대적합
  • 검증세트를 만드느라 훈련세트가 줄었음
  • 해결법: 교차검증

교차검증

from sklearn.model_selection import cross_validate
scores=cross_validate(dt,train_input,train_target)
print(scores)
  • cross_validate를 사용하면 직접 검증세트를 지정안해줘도됨
  • 기본값은 5번 교차검증
  • fit_time : 훈련시간
  • score_time : 검증시간
  • test_score : 검증 폴드의 점수(테스트 점수 아님!!)

import numpy as np
print(np.mean(scores['test_score']))

from sklearn.model_selection import StratifiedKFold
scores=cross_validate(dt,train_input,train_target,cv=StratifiedKFold())
print(np.mean(scores['test_score']))
  • 앞서 전체 데이터를 섞은 후 나눠줬기때문에 섞을 필요가 없긴함
  • 근데 교차검증을 할때 훈련세트를 섞으려면 분할기를 지정해줘야함
  • 회귀모델의 경우 KFold, 분류모델의 경우 StratifiedKFold를 사용
splitter=StratifiedKFold(n_splits=10,shuffle=True,random_state=42)
scores=cross_validate(dt,train_input,train_target,cv=splitter)
print(np.mean(scores['test_score']))
  • 만약 10-폴드 교차검증을 하고싶다면 splitter에 저장한 후 넣어준다.

그리드서치(1)


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)
  • 그리드서치 클래스에 탐색대상모델과 params의 변수를 전달하여 그리드서치 객체를 만든다.
  • n_jobs에 -1을 지정하면 시스템의 모든 코어를 사용한다.

gs.fit(train_input,train_target)

dt=gs.best_estimator_

print(dt.score(train_input,train_target))
print(gs.best_params_)
  • gs 객체에 fit 메서드를 호출하면 min_impurity_decrease (5) * 교차검증(5) =25개의 모델을 훈련하게 된다.
  • 검증 점수가 가장 높은 하이퍼파라미터로 훈련한 모델은 bestestimator에 저장되어있고 따로 훈련을 하지않아도 바로 score를 확인할 수 있음
  • 최적의 매개변수는 bestparams에 저장되어있음



print(gs.cv_results_['mean_test_score'])
  • 5번의 교차 검증으로 얻은 점수
  • 최적의 하이퍼파라미터인 0.0001 에 있는 위치의 점수가 역시 가장 높음
best_index=np.argmax(gs.cv_results_['mean_test_score'])
print(gs.cv_results_['params'][best_index])
  • argmax를 사용하면 가장 큰 값의 인덱스를 추출할 수있음
  • argmin를 사용하면 가장 작은 값의 인덱스를 추출할 수있음

그리드서치(2)


params = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001),
          'max_depth': range(5, 20, 1),
          'min_samples_split': range(2, 100, 10)
          }
  • arange 함수는 첫번째 매개변수값을 시작으로 두번째 매개변수에 도달할때까지 세번째 매개변수만큼 계속 더한 배열을 만든다.
  • range 함수는 정수만 사용할 수있고, arange 처럼 마찬가지로 보면 된다.
  • 교차검증횟수는 9 15 10 = 1350 번이고 , 5-폴드 검증을 수행하므로 만들어지는 모델은 1350 * 5 =6750 개이다.

gs=GridSearchCV(DecisionTreeClassifier(random_state=42),params,n_jobs=-1)
gs.fit(train_input,train_target)
print(gs.best_params_)
print(np.max(gs.cv_results_['mean_test_score']))

랜덤 서치

from scipy.stats import uniform,randint

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),
          }
  • randint 정수로 숫자를 뽑음
  • uniform 실수로 숫자를 뽑음

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_)
  • n_iter로 샘플링 횟수를 지정할 수 있다. 샘플링 횟수는 시스템 자원이 허락하는 범위내에서 최대한 클 수록 좋다.

print(np.max(gs.cv_results_['mean_test_score']))

dt=gs.best_estimator_
print(dt.score(test_input,test_target))
  • 최적의 파라미터로 훈련한 모델로 테스트를 함
참고문헌: 혼공머신

0개의 댓글