카테고리 없음

교차검증(cross_val_score ), 하이퍼파라미터 (GridSearchCV, RandomizedSearchCV) 간단하게 이해하기

simplecode 2021. 6. 28. 01:22

ㄱ데이터를 훈련/검증/테스트 세트로 나누어 평가를 하다보면 그 테스트 데이터에만 최적화된 과적합 학습 모델이 만들어집니다.

모의고사를 만점맞았는데 정작 수능은 저조한 평가를 받는다고 보면 쉽습니다.

 

이를 방지하기 위해 수능을 보기 전 여러번 모의고사를 치르는 방법을 생각할 수 있는데, 이를 교차검증이라고 합니다.

검증세트의 크기가 작은 경우에도 사용이 가능합니다.

 

K폴드 교차 검증( k-fold cross-validation(CV))

예를들어, 데이터를 3등분으로 나누고 검증(1/3)과 훈련세트(2/3)를 총 세번 바꾸어가며 검증하는 것은 3-fold CV 입니다.


교차검증 모델의 종류

  • 일반 K 폴드 - 가장 보편적인 교차검증기법입니다.
  • stratifiedKFold - 일반 K 폴드보다 stratifiedKFold가 불균형한 분포를 가진 분류 레이블 데이터에 사용이 가능합니다.                (단, 회귀/시계열데이터는 연속값이므로 지원하지 않습니다.)
  • cross_val_score - 폴드세트 추출, 학습/예측, 평가를 한번에 수행합니다. 교차검증을 보다 편리하게 수행할 수 있습니다. 

교차검증세트 3개를 사용한 cross_val_score() 예시를 보도록 하겠습니다.

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, cross_validate
from sklearn.datasets import load_iris
 
iris_data =load_iris()
dt_clf = DecisionTreeClassifier(random_state = 156)
 
data = iris_data.data
label = iris_data.target
 
# 성능 지표는 정확도(accuracy), 교차 검증세트는3개
scores = cross_val_score(dt_clf, data, label, scoring = 'accuracy', cv =3)
np.round(scores, 4# 검증별 정확도
np.round(np.mean(scores),4# 평균 검증 정확도
 
>>> 0.9804 0.9216 0.9792
    0.9604
cs

 


하이퍼파라미터 튜닝

 

머신러닝 모델을 만들때 중요한 이슈는 최적화(optimization)와 일반화(generalization) 입니다.

  • 최적화는 훈련 데이터로 더 좋은 성능을 얻기 위해 모델을 조정하는 과정이며,
  • 일반화는 학습된 모델이 처음 본 데이터에서 얼마나 좋은 성능을 내는지를 이야기 합니다.

위와 같이 순차로 진행할 파라미터의 세부값을 지정해줍니다.

GridSearchCV: 검증하고 싶은 하이퍼파라미터들의 수치를 정해주고 그 조합을 모두 검증합니다.

                               cv세트가 3이면 * 파라미터 순차적용횟수 6 = 18번

                              2 imputation n cols 3 alphas * 3 cv = 1386 tasks (너무 많습니다. 이런 경우 시간이 상대적으로 오래 걸립니다.)

Randomized Search CV: 검증하려는 하이퍼파라미터들의 값 범위를 지정해주면 무작위로 값을 지정해 그 조합을 모두 검증합니다.

                                              n_iter(=50) * 3 교차검증 = 150 tasks

 


그리드서치 (GridSearchCV )

교차검증을 기반으로 최적 하이퍼파라미터 집합을 만들어 이를 순차적으로 적용하여 최적의 파라미터를 찾을 수 있습니다.

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
 
# 데이터를 로딩하고 학습데이터와 테스트 데이터 분리
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, 
                                                    test_size=0.2, random_state=121)
dtree = DecisionTreeClassifier()
 
### parameter 들을 dictionary 형태로 설정
parameters = {'max_depth':[123], 'min_samples_split':[2,3]}
cs
import pandas as pd
 
# param_grid의 하이퍼 파라미터들을 3개의 train, test set fold 로 나누어서 테스트 수행 설정  
### refit=True 가 default 임. True이면 가장 좋은 파라미터 설정으로 재 학습 시킴
grid_dtree = GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True, return_train_score=True)
 
# 붓꽃 Train 데이터로 param_grid의 하이퍼 파라미터들을 순차적으로 학습/평가 
grid_dtree.fit(X_train, y_train)
 
# GridSearchCV 결과는 cv_results_ 라는 딕셔너리로 저장됨. 이를 DataFrame으로 변환
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']]
cs

 

print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도: {0:.4f}'.format(grid_dtree.best_score_))
 
# refit=True로 설정된 GridSearchCV 객체가 fit()을 수행 시 학습이 완료된 Estimator를 내포하고 있으므로 predict()를 통해 예측도 가능. 
pred = grid_dtree.predict(X_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
cs

>>>

GridSearchCV 최적 파라미터: {'max_depth': 3, 'min_samples_split': 2}

GridSearchCV 최고 정확도: 0.9667

테스트 데이터 세트 정확도: 0.9667


*잠깐!*

Estimator란 : 지도학습의 모든 알고리즘(classifier, Regressor 등)을 구현한 클래스로  fit()과 Predict() 과정이 이미 포함되어 있습니다. cross_val_score(), GridSearchCV.fit()함수 내에서 이미 이 Estimator의 fit()과 Predict()를 호출해서 평가하고있습니다.

 

 
# GridSearchCV의 refit으로 이미 학습이 된 estimator 반환
estimator = grid_dtree.best_estimator_
 
# GridSearchCV의 best_estimator_는 이미 최적 하이퍼 파라미터로 학습이 됨
pred = estimator.predict(X_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test,pred)))
cs

>>>

테스트 데이터 세트 정확도: 0.9667

 


Randomized Search CV

Ridge 회귀모델의 하이퍼파라미터를 튜닝해보겠습니다.

from sklearn.model_selection import RandomizedSearchCV
 
pipe = make_pipeline(
    OneHotEncoder(use_cat_names=True)
    , SimpleImputer()
    , StandardScaler()
    , SelectKBest(f_regression)
    , Ridge()
)
 
# 튜닝할 하이퍼파라미터의 범위를 지정해 주는 부분
dists = {
    'simpleimputer__strategy': ['mean''median'], 
    'selectkbest__k'range(1len(X_train.columns)+1), 
    'ridge__alpha': [0.1110], 
}
 
clf = RandomizedSearchCV(
    pipe, 
    param_distributions=dists, 
    n_iter=50
    cv=3,
    scoring='neg_mean_absolute_error',
    verbose=1,
    n_jobs=-1
)
 
clf.fit(X_train, y_train);
 
cs

 >>>

Fitting 3 folds for each of 50 candidates, totalling 150 fits

 

print('최적 하이퍼파라미터: ', clf.best_params_)
print('MAE: ', -clf.best_score_)
cs

>>>

최적 하이퍼파라미터: {'simpleimputer__strategy': 'median', 'selectkbest__k': 55, 'ridge__alpha': 10} MAE: 18414.633797820472


선형회귀, 랜덤포레스트 모델들의 튜닝 추천 하이퍼파라미터 입니다

Random Forest

class_weight (불균형(imbalanced) 클래스인 경우)

  • max_depth (너무 깊어지면 과적합)
  • n_estimators (적을경우 과소적합, 높을경우 긴 학습시간)
  • min_samples_leaf (과적합일경우 높임)
  • max_features (줄일 수록 다양한 트리생성)

Logistic Regression

  • C (Inverse of regularization strength)
  • class_weight (불균형 클래스인 경우)
  • penalty

Ridge / Lasso Regression

  • alpha