데이터분석-머신러닝-AI/강의 정리

[혼자 공부하는 머신러닝+딥러닝] 12강. 교차 검증과 그리드 서치 -

bluebamus 2023. 11. 13.

https://www.youtube.com/watch?v=ZaIKUvHquEQ&list=PLJN246lAkhQjoU0C4v8FgtbjOIXxSs_4Q&index=14

 

 - 검증세트 만드는 방법

   - 샘플 데이터를 먼저 train_test_split를 이용해 테스트 세트와 분리하고 이후 training 데이터들을 다시 train_test_split를 이용해 검증 세트와 분리한다.

      - train_test_split를 이용해 두 번 샘플을 분리하는 과정을 거치면 된다. 

      - 하이퍼파라미터, 매개변수튜닝을 통해 훈련, 검증, 테스트 세트들의 범위를 정의할 수 있다.

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.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

 

 - cross_validate는 기본적으로 5폴드를 사용한다.

 - score의 결과늰 fit_time(모델 훈련 시간), score_time(검증 점수 예측/만들어 내는 시간), test_score(검증 점수) 세개 의 변수로 제공된다. 

 - 최종적으로 test_score를 np.mean을 사용해 평균을 낸다.

 - RandomForestClassifier, ExtraTreesClassifier 등 다양한 모델에는 파라미터가 존재하며 이 값을 조정하여 교차 검증을 수행함으로 높은 score 점수를 이끌어 낼 수 있다.

 

 - 교차검증은 딥러닝에서는 사용하지 않으며 머신러닝에서 사용된다. 

   - 머신러닝에서는 교차 검증 혹은 그리드 서치를 꼭 사용하는 것을 요구한다.

   - 머신러닝은 데이터가 충분하기 때문에 검증세트를 효율적으로 확보할 수 있다.

   - 비용 문제로 여러번 돌리는 것은 비효율적이다.

 

 - 분할기(spliter)를 사용한 교차 검증

   - cross_validate의 cv는 폴드를 설정하는 변수로 기본 5이다. 만약 10개 폴드로 나누면 10%를 사용한다는 의미가 된다. 

   - cv에 스플리터 객체를 지정해서 나누는 동작을 상세하게 정의할 수 있다.

   - KFold(회귀)

   - stratifiedKFold(분류)

   - cross_validate 첫번째 인자의 객체가 회귀 모델이면 자동으로 KFold이 설정되고 분류면 stratifiedKFold가 할당된다.

scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())

 

   - 10개의 폴드, 랜덤하게 섞어서 학습을 하고자 한다면 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']))

 

 - 하이퍼 파라미터 튜닝

   - 사용자가 수동으로 일일이 매개변수를 바꿔가며 cross_validate를 해야하나?

   - 사실, 매개변수들의 최적값은 순차적으로 찾을 수 없다. 각각의 매개변수 값들은 상호 영향을 주기 때문에...

   - 이러한 많은 가능성의 '수'에 대한 작업을 자동으로 해주는 작업이 튜닝 작업이다.

   - 사이킷런은 하이퍼파라미터 탐색(최적의 매개변수 탐색)과 교차검증을 한번에 수행해주는 클래스를 제공해준다.

      - gridsearchCV()

         - params : 딕셔너리 형태로 탐색할 매개변수 후보 값들을 dict으로 정의

         -  n_jobs : 작업에 사용할 CPU 코어 수 (-1로 설정하면 사용 가능한 모든 core 선택)

         -  .best_params_ : 찾아낸 최적의 매개변수가 저장됨

         -  .best_estimator_ : 최적의 매개변수 조합으로 훈련시킨 최적의 모델이 저장됨

         -   각 매개변수 후보들에서 수행한 교차검증의 평균 점수는 .cv_results_ 딕셔너리의 'mean_test_score' 키에 저장됨
            - 그 중 제일 큰 값의 인덱스를 .argmax()로 꺼내 'params' 키를 거쳐서, 최적의 매개변수를 뽑아볼 수도 있음

 

 - 그리드 서치

   - min_impurity_decrease에 정의되는 값은 부모노드와 자식 노드간의 불순도의 차이, 정보이득이다.

      - 정보 이득이 클수록 분할이 더 잘 된다.

      - 최소 값을 정의한다. 이 값보다 밑의 값이 되면 노드를 분할하지 말라는 의미가 된다.

      - DecisionTreeClassifier는 기본적으로 5개 모델로 분할된다. 그리고 정의된 params도 5개 이므로 총 25개 모델이 존재하게 된다.

      - n_jobs는 병렬 수행을 하는 것으로 core의 수에 따라 증가시키면 된다. -1은 가능한 모든 core를 사용한다는 뜻이다.

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

print(gs.best_params_)

print(gs.cv_results_['mean_test_score'])

best_index = np.argmax(gs.cv_results_['mean_test_score'])
print(gs.cv_results_['params'][best_index])

 

   - 가장 좋은 파라미터 값이 best_estimator_ 변수에 저장 된다.

   - 교차 검증 점수는 cv_results_ 변수의 'mean_test_score'에 저장된다.

      - 위 코드의 결과로 총 5개의 점수가 저장되어 있는 것을 확인할 수 있다.

 

   - 더 많은 매개변수를 탐색하고 싶다면?

      - 넘파이의 np.arrange() 함수와 파이썬의 range() 함수를 사용할 수 있다.

      - min_samples_split는 특정 노드의 샘플 수가 정의된 수만큼 되지 않으면 분할 하지 않겠다는 정의를 할 수 있다.

params = {'minaparams = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001),
          'max_depth': range(5, 20, 1),
          'min_samples_split': range(2, 100, 10)
          }

 

 - 랜덤 서치

   - 확률 분포 선택

      - uniform(실수), randint(정수)

from scipy.stats import uniform, randint

rgen = randint(0, 10)
rgen.rvs(10)

np.unique(rgen.rvs(1000), return_counts=True)

ugen = uniform(0, 1)
ugen.rvs(10)

 

 

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),
          }
          
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.8695428296438884

dt = gs.best_estimator_

print(dt.score(test_input, test_target))
0.86

 

 

-  reference :

https://velog.io/@simon919/%ED%98%BC%EA%B3%B5%EB%A8%B8%EC%8B%A0-5-2.-%EA%B5%90%EC%B0%A8-%EA%B2%80%EC%A6%9D%EA%B3%BC-%EA%B7%B8%EB%A6%AC%EB%93%9C-%EC%84%9C%EC%B9%98-v07z0r3b

 

[혼공머신] 5-2. 교차 검증과 그리드 서치

이사님🗣️ "최적의 모델을 찾는 건 좋은데, 그 과정에서 자꾸 테스트 세트로 평가를 하면 테스트 세트에만 잘 맞는 모델이 되어버리는 거 아닌가요?"

velog.io

https://velog.io/@ohxhxs/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EA%B5%90%EC%B0%A8%EA%B2%80%EC%A6%9D-KFold-StratifiedKFold-crossvalscoreGridSearchCV

 

파이썬 머신러닝 교차검증 - KFold, StratifiedKFold, cross_val_score, GridSearchCV

* 과적합 * 과적합 : 모델이 학습 데이터에만 과도하게 최적화되어, 실제 예측을 다른 데이터로 수행할 경우에는 예측 성능이 과도하게 떨어지는것을 말한다. 과적합을 방지할 수 있는 교차검증

velog.io

https://continuous-development.tistory.com/entry/MLDL-python-%EC%9D%84-%ED%86%B5%ED%95%9C-%EA%B5%90%EC%B0%A8%EA%B2%80%EC%A6%9D-k-Fold-stratifiedkFold

 

[ML/DL] python 을 통한 교차검증 ( k -Fold , stratifiedkFold)

교차검증이란? 머신러닝을 돌리기 전에 train test로 나눠 머신을 훈련한다. 하지만 이 훈련 때 학습 데이터에 과도하게 초점을 맞춰 머신이 훈련될 수가 있다. 이 같은 경우에는 훈련시에는 점수

continuous-development.tistory.com

 

댓글