본문 바로가기
Archive/데이터 분석 관련

[Data] GridSearchCV

by 다람이도토리 2021. 6. 14.

GridSearch란?

모델을 결정해서 학습시킬 때, 모델의 하이퍼파라미터가 얼마일때가 가장 최적인지, 알기 어려운 경우가 많다. 
GridSearch를 통해서 최적값이 얼마인지 찾아줄 수 있다. 이의 구조에 대해 알아보고자 한다.

 

K-fold and stratified K-fold

음? 이것부터 하는 이유는 무엇일까?

우리는 data set을 train set - validation set - test set으로 나누어서 훈련, 검증, 평가 한다.

이 과정에서 훈련셋과 검증셋의 경우는 K-fold를 활용하여 여러번 훈련 및 검증한다.
데이터셋을 K등분하여 분할하여 훈련하게 된다.

그런데, 여기서 Train / Test set은 임으로 분할하게 되는데, 만일 특정 label이 train에만 있거나 test에만 있으면 어떻게 될까?  이러한 문제점을 막아주는 것이 Stratified K-fold이다.

Stratified K-fold는 train에서의 label 분포와 test에서의 label 분포를 유사하게 한다.

from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits = 5)
all_acc = []
fold_idx = 0

iris = load_iris()
features = iris.data
labels = iris.target

for train_idx, test_idx in skf.split(features, labels):
  train_x, train_y = features[train_idx], labels[train_idx]
  test_x, test_y = features[test_idx], labels[test_idx]

  model = DecisionTreeClassifier()
  model.fit(train_x, train_y)
  pred_y = model.predict(test_x)
  acc = accuracy_score(test_y, pred_y)

  fold_idx += 1
  all_acc.append(acc)

print(np.mean(all_acc))

 

Cross_val_score

그런데 이렇게 train, test를 직접 수동으로 나누는 대신 cross_val_score를 통해서 한번에 평가까지 가능하다.

# Stratified K-fold 기반이다.
from sklearn.model_selection import cross_val_score, cross_validate

iris_data = load_iris()
features = iris_data.data
labels = iris.target

model = DecisionTreeClassifier()

scores = cross_val_score(model, features, labels,
                        scoring='accuracy', cv=5)
print(scores)

 

Grid Search

그리드 서치에서는 파라미터의 후보값을 사전에 정의해주고 알아서 for문을 돌려준다.

또한, 여기에서는 교차검증까지 바로 실시하게 되므로 한번에 위의 작업과 하이퍼파라미터튜닝을 하게 된다.

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd

iris_data = load_iris()
train_x, test_x, train_y, test_y = train_test_split(iris_data.data, iris_data.target,
                                                    test_size = 0.2)
model = DecisionTreeClassifier()
params = {'max_depth':[3, 4, 5, 6], 'min_samples_split':[2, 3, 4]}

grid_dtree = GridSearchCV(model, param_grid = params,
                          cv = 5, refit = True, return_train_score = True)
grid_dtree.fit(train_x, train_y)

# 결과표 출력
scores_df = pd.DataFrame(grid_dtree.cv_results_)
scores_df[['params', 'mean_test_score', 'rank_test_score', 
           'split0_test_score', 'split1_test_score', 'split2_test_score']]

# best_params_ 할당
print(f"최적의 파라미터 : {grid_dtree.best_params_}")
print(f"최적의 파라미터로 모델의 정확도 : {grid_dtree.best_score_}")

# 최적의 best_params
estimator = grid_dtree.best_estimator_
pred_y = estimator.predict(test_x)
print(accuracy_score(test_y, pred_y))