핵심 키워드
- #검증 세트 #교차 검증 #그리드 서치 #랜덤 서치
- 검증 세트가 필요한 이유를 이해하고 교차 검증에 대해 배우자
그리고 그리드 서치와 랜덤 서치를 이용해 최적의 성능을 내는 하이퍼파라미터를 찾자
검증 세트
- 검증 세트
지금까지는 훈련 세트에서 모델을 훈련하고 테스트 세트에서 모델을 평가했으므로 점점 테스트 세트에 맞추게 되는 셈이 됨
그러므로 모델을 만들고 나서 마지막에 딱 한 번만 테스트 세트를 사용하는 것이 좋음
이를 위해 훈련 세트를 또 나누어 검증 세트(개발 세트)를 만들어서 사용해야 함
전체 데이터 중 20%를 테스트 세트로 만들고 나머지 80%를 훈련 세트로 만든 후, 훈련 세트 중 다시 20%를 검증 세트로 만듦
이 후 훈련 세트에서 모델을 훈련하고 검증 세트로 모델을 평가하며
테스트하고 싶은 매개변수를 바꿔가며 하이퍼파라미터 튜닝을 하면 가장 좋은 모델을 만든 후,
최적의 매개변수를 사용해 훈련 세트와 검증 세트를 합쳐 전체 훈련 데이터에서 모델을 다시 훈련함
그리고 마지막으로 테스트 세트에서 최종 점수를 평가하면 실전에 투입했을 때 테스트 세트 점수와 비슷한 성능을 기대할 수 있음
데이터를 불러와 검증 세트를 만들기 위해 훈련 세트의 입력 데이터와 타깃 데이터를 tain_input, train_target 배열에 저장
이후 train_input과 train_target을 다시 train_test_split() 함수에 넣어
모델 훈련을 위한 훈련 세트 sub_input, sub_target과 하이퍼파라미터 튜닝을 위한 검증 세트 val_input, val_target을 만듦
그런 후 sub_input, sub_target과 val_input, val_target을 사용해 모델을 만들고 평가
교차 검증
- 교차 검증
검증 세트를 너무 조금 떼어 놓으면 검증 점수가 들쭉날쭉하고 불안정할 것이므로 교차 검증을 이용해 안정적인 검증 점수를 얻음
교차 검증은 검증 세트를 떼어 내어 평가하는 과정을 여러 번 반복한 후 이 점수를 평균하여 최종 검증 점수를 얻음
훈련 세트를 세 부분으로 나눠서 교차 검증을 수행할 경우 3-폴드 교차 검증이라고 함
사이킷런에는 cross_validate()라는 교차 검증 함수가 존재하므로 직접 검증 세트를 떼어 내지 않고 훈련 세트 전체를 전달
이 함수는 fit_time, score_time, test_score 키를 가진 딕셔너리를 반환하며
처음 2개의 키는 각각 모델을 훈련하는 시간과 검증하는 시간을 의미함
cross_validate() 함수는 기본적으로 5-폴드 교차 검증을 수행(25개의 모델 생성)하므로
교차 검증의 최종 점수는 test_score 키에 담긴 5개의 점수를 평균하여 얻을 수 있음
+) 딥러닝과 머신러닝
딥러닝의 경우 데이터가 풍부하므로 검증 세트를 충분히 확보할 수 있어 검증세트, 훈련 세트 사용
머신러닝의 경우 교차 검증 사용
- 분할기를 사용한 교차 검증
만약 교차 검증을 할 때 훈련 세트를 섞으려면 분할기를 지정해야 함
사이킷런의 분할기는 교차 검증에서 폴드를 어떻게 나눌지 결정해줌
회귀 모델일 경우 KFold 분할기를 사용하고 분류 모델일 경우 타깃 클래스를 골고루 나누기 위해 StratifiedKFold 사용
만약 훈련 세트를 섞은 후 10-폴드 교차 검증을 수행하려면 n_splits 매개변수를 10으로 바꿔줌
하이퍼파라미터 튜닝
- 그리드 서치
하이퍼파라미터를 튜닝하는 작업은 매개변수를 바꿔가면서 모델을 훈련하고 교차 검증을 수행하는 것을 뜻함
만약 결정 트리 모델에서 최적의 max_depth 값을 찾았다고 이를 고정해둔 후 min_samples_split을 바꿔가면서
최적의 값을 찾는다면 max_depth의 최적값은 min_samples_split 매개변수의 값이 바뀌면 함께 달라지므로
이 두 매개변수를 동시에 바꿔가며 최적의 값을 찾아야 함
이러한 과정을 위해 사이킷런에서 제공하는 그리드 서치를 사용
사이킷런의 GridSearchCV 클래스는 하이퍼파라미터 탐색과 교차 검증을 한 번에 수행하므로 cross_validate() 호출 필요 없음
먼저 GridSearchCV 클래스를 임포트하고 탐색할 매개변수와 탐색할 값의 리스트를 딕셔너리로 만듦
그 후 GridSearchCV 클래스에 탐색 대상 모델과 params 변수를 전달하여 그리드 서치 객체를 만들고
결정 트리 클래스의 객체를 생성해서 바로 전달한 후 fit() 메소드를 호출
fit() 메소드를 호출하면 그리드 서치 객체는 결정 트리 모델 min_impurity_decrease 값을 바꿔가면서 총 5번을 실행함
GridSearchCV의 cv 매개변수 기본값은 5이므로 따라서 min_impurity_decrease 값마다 5-폴드 교차 검증을 수행하므로
결국 5 X 5 = 25개의 모델을 훈련하기 때문에 n_jobs 매개변수에서 병렬 실행에 사용할 CPU 코어 수를 지정
n_jobs 매개변수의 기본값은 1이며 -1로 지정하면 시스템에 있는 모든 코어를 사용하게 됨
사이킷런의 그리드 서치는 훈련이 끝나면 25개의 모델 중에서 검증 점수가 가장 높은 모델의 매개변수 조합으로
전체 훈련 세트에서 자동으로 다시 모델을 훈련한 후 gs 객체의 best_estimator_ 속성에 저장함
그리고 그리드 서치로 찾은 최적의 매개변수를 best_params_ 속성에 저장함
마지막으로 각 매개변수에서 수행한 교차 검증의 평균 점수는 cv_results_속성의 mean_test_score 키에 저장함
조금 더 복잡한 매개변수 조합을 탐색하기 위해서는 넘파이 arange() 함수와 range() 함수를 이용
arange() 함수는 첫 번째 매개변수 값에서 시작해 두 번째 매개변수에 도달할 때까지 세 번째 매개변수를 계속 더한 배열을 만듦
range() 함수는 정수만 사용할 수 있으며 arange() 함수와 비슷함
- 확률 분포 선택
매개변수의 값이 수치일 때 값의 범위나 간격을 미리 정하기 어려울 수 있으며
또 너무 많은 매개변수 조건이 있어 그리드 서치 수행 시간이 오래걸릴 수 있어 이럴 때 랜덤 서치를 사용
싸이파이의 stats 서브 패키지에 있는 uniform과 randint 클래스는 모두 주어진 범위에서 고르게 값을 뽑음
이를 균등 분포에서 샘플링한다고 말하며 randint는 정숫값을 뽑고, uniform은 실숫값을 뽑음
이를 사용해 랜덤 서치에 randint과 uniform 클래스 객체를 넘겨주고 총 몇 번을 샘플링해서 최적의 매개변수를 찾으라고 함
- 랜덤 서치
매개변수의 딕셔너리를 만들어
min_imputiry_decrease는 0.0001에서 0.001 사이의 실숫값을 샘플링하고 max_depth는 20에서 50 사이의 정수,
min_sample_split은 2에서 25 사이의 정수, min_samples_leaf는 1에서 25 사이의 정수를 샘플링
샘플링 횟수는 사이킷런의 랜덤 서치 클래스인 RandomizedSearchCV의 n_iter 매개변수에 지정
그러면 params에 정의된 매개변수 범위에서 총 100번(n_iter 매개변수)을 샘플링하여 교차 검증을 수행하고
최적의 매개변수 조합을 찾아 best_params_ 속성에 저장함
그리고 최적의 매개변수로 찾은 검증 세트의 점수인 최고 교차 검증 점수를 cv_results_속성의 mean_test_score 키에 저장함
마지막으로 최적의 모델은 이미 전체 훈련 세트로 훈련되어 best_estimator_ 속에 저장되어 있으므로
이 모델을 최종 모델로 결정하고 테스트 세트의 성능을 확인하면
테스트 세트 점수는 검증 세트에 대한 점수보다 조금 작게 나오는데 이것이 일반적
이처럼 랜덤 서치는 그리드 서치보다 훨씬 교차 검증 수를 줄이면서 넓은 영역을 효과적으로 탐색할 수 있음
+) 확인 문제
- RamdomizedSearchCV 예제에서 DecisionTreeClassifier 클래스에 splitter='random' 매개변수를 추가하고 다시 훈련
- splitter 매개변수의 기본값은 'best'로 각 노드에서 최선의 분할을 찾지만
'ramdom'이면 무작위로 분할한 다음 가장 좋은 것을 고름 - 결정 트리의 노드를 랜덤하게 분할하기 때문에 100번의 반복에서 최적의 매개변수를 조합을 찾지 못함
그러므로 평균 검증 점수와 테스트 세트의 점수가 모두 조금 낮게 됨
'ML > 혼자 공부하는 머신러닝 + 딥러닝' 카테고리의 다른 글
[혼공머신] 06. 비지도 학습 - 군집 알고리즘 (0) | 2022.06.28 |
---|---|
[혼공머신] 05. 트리 알고리즘 - 트리의 앙상블 (0) | 2022.06.01 |
[혼공머신] 05. 트리 알고리즘 - 결정 트리 (0) | 2022.05.30 |
[혼공머신] 04. 다양한 분류 알고리즘 - 확률적 경사 하강법 (0) | 2022.05.24 |
[혼공머신] 04. 다양한 분류 알고리즘 - 로지스틱 회귀 (0) | 2022.05.24 |