AI 머신러닝 딥러닝/파이썬 머신러닝 입문 공부일지

파이썬 머신러닝 입문 공부일지 14. 교차 검증 (3) cross_val_score(), GridSearchCV

Tomitom 2023. 1. 5. 17:48
반응형

 

 

지난 번에 교차 검증의 KFold 에 대해서 예제까지 들며 하나씩 살펴보았습니다. 

이번에는 이 일련의 교차 검증 과정을 보다 간편하게 처리할 수 있는 API 를 소개합니다!

 

cross_val_score() 

 

cross_val_score 의 주요 파라미터는 다음과 같습니다.

 

cross_val_score(estimator, X, y, scoring=평가지표, cv=교차 검증 폴드 수)

  • estimator : 사이킷런의 분류 알고리즘 중 Classfier 또는 회귀 알고리즘 중 Regressor 
  • X : 피처 데이터 세트 
  • y : 레이블 데이터 세트 
  • scoring : 예측 평가 지표
  • cv : 교차 검증 폴드 수

 

cross_val_score() 의 수행 후 반환 값은 scoring 파라미터로 지정된 성능 지표 측정값을 배열 형태로 반환합니다. 

 

성능지표란? 성능에 대한 측정이 가능한 지표 값입니다. 

즉, 성능이 좋은지 나쁜지에 대한 성능 측정 기준을 accuracy (정확도) 로 수치화한 것 입니다. 

 

cross_val_score() 는  classifier 가 입력되면 Stratified K 폴드 방식으로 레이블 값의 분포에 따라 학습/테스트 세트를 분할합니다. 

 

다음 코드를 직접 작성해서 확인합니다. 

 

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, cross_validate
from sklearn.datasets import load_iris
import numpy as np

iris_data = load_iris()
dt_clf = DecisionTreeClassifier(random_state=99)

data = iris_data.data
label = iris_data.target

# 성능 지표(성능에 대한 측정의 지표) 는 정확도(accuarcy) 입니다. 
# 교차 검증 세트는 3개

scores = cross_val_score(dt_clf, data, label, scoring='accuracy', cv=3)

print("교차 검증별 정확도 : ", np.round(scores, 4))
print("평균 검증 정확도 : ", np.round(np.mean(scores),4))

 

 

cross_val_score() API 는 내부에서 Estimator 를 학습(fit), 예측(predict), 평가(evaluation) 하기 때문에 간단하게 교차 검증을 수행할 수 있습니다. 

 

비슷한 API 로 cross_validat() 가 있습니다. 

단 하나의 평가 지표만 사용할 수 있는 cross_val_score()  와 달리 여러 개의 평가 지표를 반환할 수 있으며, 

학습 데이터에 대한 성능 평가 지표와 수행 시간도 같이 제공합니다. 

(그러나 통상적으로 cross_val_score() 만으로 대부분의 경우 쉽게 사용합니다.) 

 

기존에 KFold 예제를 작성하면서 그렇게 복잡했던 코드가 이렇게 간편해졌습니다...^^..

https://blue-dot.tistory.com/201

 

파이썬 머신러닝 입문 공부일지 12. train_test_split(), 교차 검증 (1) KFold 클래스

사이킷런의 Model Selection 모듈은 학습 데이터와 테스트 데이터 세트를 분리하거나 교차 검증 분할 및 평가, 그리고 Estimator 의 하이퍼 파라미터 튜닝을 위한 함수와 클래스 등을 제공합니다. 우선

blue-dot.tistory.com

(이 때는 정말...^^... 네...)

 

 

 

그럼 이번에는 교차 검증과 최적의 하이퍼 파라미터 튜닝을 한 번에 할 수 있는 API 에 대해서 알아볼게요. 

 

 

GridSearchCV

 

하이퍼 파라미터는 머신러닝 알고리즘을 구성하는 주요 구성 요소이며, 이 값을 조정해서 알고리즘 예측 성능을 개선할 수 있습니다. 

 

 

사이킷런은 GridSearchCV  API로 Classifier분류나 Refressor회귀와 같은 알고리즘에 사용되는 하이퍼 파라미터를 순차적으로 입력하며, 편리하게 최적의 파라미터를 찾아낼 수 있게 합니다. 

 

즉, 사용자가 직접 모델의 하이퍼 파라미터 값을 리스트로 입력하면, 값에 대한 경우의 수마다 예측 성능을 측정하고 평가해서 최적의 하이퍼 파라미터 값을 찾을 수 있게 해주는 것이에요. 

 

Grid(격자) Search(찾기) CV(교차 검증을 위한 폴드 수) -> 보다 촘촘하게 파라미터를 격자처럼 입력하며 찾는다!

 

단 시간이 오래 걸린다는 단점이 있습니다. 

 

우리가 최적의 파라미터를 발견하기 위해서는 최대한 많은 파라미터를 변경하고 적용하면서 최고의 성능을 가지는 파라미터를 추출해내야겠죠. 그러기 위해서는 파라미터의 집합을 만들고 이를 순차적으로 적용하면서 최적화를 진행하면 됩니다. 

 

우선 grid_parameters 라고 하는 딕셔너리를 생성합니다. 

 

grid_parameters = {
    'max_depth': [1, 2, 3],
    'min_samples_split' : [4, 5]
}

 

이 경우 모든 하이퍼 파라미터는 교차적으로 적용되며

총 6회에 걸쳐서 파라미터를 순차적으로 바꿔가며 최적의 파라미터의 수행 결과를 도출하는 것이에요. 

 

순번 max_depth min_samples_split
1 1 4
2 1 5
3 2 4
4 2 5
5 3 4
6 3 5

 

분명 최적의 파라미터를 찾을 수 있지만 시간이 무척 오래 걸리겠죠. 

 

GridSearchCV 의 주요 파라미터는 다음과 같습니다. 

 

  • estimator(string) : classifier(분류) , regressor(회귀) , pipeline(파이프라인 : 프로세서에서 성능을 높이기 위해 명령어 처리를 여러 단계로 나우어 단계별로 동시에 수행하는 병렬화) 등이 사용될 수 있다. 
  • param_grid(dict) : key+리스트 의 값을 가지는 딕셔너리가 사용됨. Estimator(모델 학습train/검증evaluate/예측predict)의 튜닝을 위해 파라미터명과 여러 파라미터 값을 지정한다. 
  • scoring(string) : 예측 성능을 측정할 평가 방법 지정. 보통은 문자열 (정확도의 경우 accuarcy)로 지정하나, 별도의 성능 평가 지표 함수도 지정할 수 있다. 
  • cv(int) : 교차 검증을 위하 분할되는 학습/테스트 세트의 개수를 지정한다. 
  • refit(bool) : true인 경우 최적의 하이퍼 파라미터를 찾은 후 입력된 estimator개체를 해당 하이퍼 파라미터로 재학습한다. 

 

GridSearchCV로 붓꽃 데이터를 예측해볼게요. 

 

 

우선 데이터를 로딩하고, 학습데이터와 테스트 데이터를 분리한 뒤에 

결정 트리 학습 방법을 불러옵니다. 

그리고 하이퍼 파라미터의 명칭은 문자열 key 값으로, 하이퍼 파라미터의 값은 리스트 형으로 설정합니다. 

 

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV

iris_data = 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)

dt_clf = DecisionTreeClassifier()

parameters = {'max_depth':[1, 2, 3], 'min_samples_split':[2, 3]}

 

여기에서 max_depth 와 min_samples_split 은 DecisionTreeClassifier 의 파라미터예요. 

 

 

DecisionTreeClassifier의 주요 파라미터(*참고)

 

더보기

 

min_samples_split - 노드를 분할하기 위한 최소한의 샘플 데이터수 → 과적합을 제어하는데 사용

- Default = 2 → 작게 설정할 수록 분할 노드가 많아져 과적합 가능성 증가
min_samples_leaf - 리프노드가 되기 위해 필요한 최소한의 샘플 데이터수

- min_samples_split과 함께 과적합 제어 용도

- 불균형 데이터의 경우 특정 클래스의 데이터가 극도로 작을 수 있으므로 작게 설정 필요
max_features - 최적의 분할을 위해 고려할 최대 feature 개수

- Default = None → 데이터 세트의 모든 피처를 사용

- int형으로 지정 →피처 갯수 / float형으로 지정 →비중

- sqrt 또는 auto : 전체 피처 중 √(피처개수) 만큼 선정

- log : 전체 피처 중 log2(전체 피처 개수) 만큼 선정
max_depth - 트리의 최대 깊이

- default = None
→ 완벽하게 클래스 값이 결정될 때 까지 분할
또는 데이터 개수가 min_samples_split보다 작아질 때까지 분할

- 깊이가 깊어지면 과적합될 수 있으므로 적절히 제어 필요
max_leaf_nodes 리프노드의 최대 개수

출처 :  https://injo.tistory.com/15

 

 

반응형

 

 

 

이제 본격적으로 학습을 시작할 거예요.

 

 

 

결정트리를 이용하고, 딕셔너리에는 파라미터를 삽입한 뒤, 3개의 폴드로 나누어 GridSearchCV로 학습한 객체를 grid_dtree 에 별칭합니다. 

 

이제 학습 데이터 세트를 GridSearchCV 객체의 fit 훈련에 넣어 학습시킵니다. 

GridSearchCV 의 fit 메소드를 실행하면 학습데이터를 cv에 입력한 숫자만큼 폴드 세트를 분할해 

딕셔너리에 기술된 파라미터의 순차적으로 변경하며 학습 평가를 수행합니다. 

그리고 그 결과를 cv_results_ 속성에 기록합니다.

 

cv_result_ 는 GridSearchCV의 결과 세트로 딕셔너리 형태로 key와 리스트 형태의 value 값을 같습니다. 

cv_result 를 pandas의 DataFrame 으로 변환하면 내용을 좀 더 쉽게 볼 수 있습니다. (scores_df 변수가 그것!)

 

 

import pandas as pd
from sklearn.model_selection import GridSearchCV

# 그리드CV 하이퍼 파라미터를 3개의 train, test 폴드 세트로 만들어 테스트 합니다. 
grid_dtree = GridSearchCV(dt_clf, param_grid = parameters, cv=3, refit=True)

#학습 데이터를 grid_dtree 의 하이퍼 파라미터로 순차적 학습/평가 
grid_dtree.fit(X_train, y_train)

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'
]]

 

총 6개의 결과를 확인할 수 있습니다. 

  • 위 결과의 params 에서는 수행할 때마다 적용된 하이퍼 파라미터 값을 가지고 있습니다. 
  • rank_test_score 은 해당 파라미터 조합인 max_depth 3 , min_sample_split : 2 (또는 3) 으로 평가한 결과가 예측 성능 1이라는 뜻입니다.
  • split 1, 2, 3 은 모두 CV가 3이기 때문에 세 개의 폴딩 세트에서 각각 테스트한 성능의 수치가 됩니다. 
  • mean_test_score 은 이 세 개의 성능 수치를 평균한 것입니다. 

 

GridSearchCV 객체의 fit() 을 수행하고 나면 자동으로 속성에 기록되는 것이 있습니다. 

  • best_params_ : 최고 성능 하이퍼 파라미트 값
  • vest_score_ : 최고 성능 하이퍼 파라미터 평가 결과 값

 

print('GridSearchCV 최적 파라미터 : ', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도 : ', round((grid_dtree.best_score_),4))

 

 

GridSearchCV  객체의 생성 파라미터 중 refit 은 True 가 디폴트 입니다. 

refit = True 일 때, GridSearchCV 가 최적 성능을 나타내는 하이퍼 파라미터로 Estimator를 학습해서 

best_estimator_로 자동 속성 기록 합니다. 

 

이미 학습된 best_estimator_ 를 이용해서 train_test_split() 로 분리한 테스트 데이터 세트에 대한 예측을 해보고 성능 평가를 해볼게요. 

 

 

# 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)))

 

별도의 테스트 데이터 세트로 정확도를 측정한 결과가 96% 정도로 도출됩니다. 

일반적으로 학습 데이터를 GridSearchCV를 이용해서 최적 하이퍼 파라미터 튜닝을 수행한 후 

-> 별도의 테스트 세트에서 평가하는 것이 일반적인 머신러닝 모델의 적용 방법입니다. 

 

 

 

여기까지 교차 검증과 모델 평가에 대해서 알아보았어요.,

긴 여정이었네요 ... 

이 다음에는 전처리 방법에 대해서 알아보겠습니다. 

 

 

 

반응형