[혼자 공부하는 머신러닝+딥러닝] 12강. 교차 검증과 그리드 서치 -
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 :
'데이터분석-머신러닝-AI > 강의 정리' 카테고리의 다른 글
[혼자 공부하는 머신러닝+딥러닝] 14강. 흑백 이미지 분류 방법과 비지도 학습, 군집 알고리즘 이해하기 - 지도 학습 샘플로 군집 알고리즘 학습 (1) | 2023.11.15 |
---|---|
[혼자 공부하는 머신러닝+딥러닝] 13강. 트리의 앙상블 - 다양한 앙상블 알고리즘 (1) | 2023.11.14 |
[혼자 공부하는 머신러닝+딥러닝] 11강. 로지스틱 회귀로 와인 분류하기 & 결정 트리 - 와인 분류하기 (1) | 2023.11.12 |
[혼자 공부하는 머신러닝+딥러닝] 10강. 확률적 경사 하강법 알아보기 - 점진적 학습, 온라인 학습 (0) | 2023.11.11 |
[혼자 공부하는 머신러닝+딥러닝] 9강. 로지스틱 회귀 알아보기 - 분류모델 (2) | 2023.11.09 |
댓글