이 글은 기존 Tistory 블로그에서 옮겨온 글입니다. 원문: https://jms3084.tistory.com/26
검증세트
테스트세트를 사용하지 않고 모델이 과소적합인지 과대적합인지 판단하기 위해 훈련세트를 또 나눠서 검증세트를 만든다.

훈련세트에서 모델을 훈련하고 검증 세트로 모델을 평가한다.
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)
#훈련세트를 훈련세트와 검증세트로 분할(sub: 훈련세트, val: 검증세트)
sub_input, val_input, sub_target, val_target = train_test_split(train_input,
train_target, test_size = 0.2)
위 코드에서 분할한 sub_input, sub_target(훈련세트)로 모델을 훈련한다.
테스트세트 대신 val_input, val_target(검증세트)로 모델을 평가한다.
교차 검증
검증세트를 너무 조금 떼어 놓을 경우 검증 점수가 불안정하다. → 교차 검증을 이용해 안정적인 점수를 얻고 훈련에 더 많은 데이터를 사용한다.
교차 검증은 검증 세트를 떼어 평가하는 과정을 여러번 반복하고 이 점수를 평균내서 최종 검증 점수를 얻는다.

훈련세트를 k부분으로 나눠서 교차 검증을 수행하는 것을 k-겹 교차 검증이라고 한다.
폴드는 훈련세트를 몇부분으로 나누냐에 따라 달라진다.
보통 5, 10-폴드 교차 검증을 많이 사용한다. → 데이터의 80~90%를 훈련에 사용 가능
사이킷런에는 cross_validate()라는 교차검증 함수가 존재한다.
평가할 모델 객체를 첫번째 매개변수로 전달하고 훈련세트를 두번째 매개변수로 전달한다.
from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
→ fit_time(훈련시간), score_time(검증시간), test_score(최종점수) 키를 가진 딕셔너리를 반환한다.
교차검증을 수행하면 입력한 모델에서 얻을 수 있는 최상의 검증 점수를 가능 가능
train_test_split에서 훈련세트를 섞지 않고 cross_validate에서 훈련세트를 섞으려면 분할기를 지정해야 한다.
→ 사이킷런의 분할기는 교차 검증에서 폴드를 어떻게 나눌지 결정해준다.
cross_validate 함수는 기본적으로 분류 모델일 경우 StratifiedKFold 분할기를 사용한다.
회귀 모델일 경우 KFold 분할기를 사용한다.
StratifiedKFold 분할기의 매개변수중 n_splits는 교차검증의 폴드수를 정합니다.
shuffle 매개변수를 True로 지정시 훈련세트를 섞는다.
하이퍼파라미터 튜닝
머신러닝 모델이 학습하는 파라미터를 모델 파라미터라고 부른다.
모델이 학습 불가하여 사용자가 직접 지정하는 파라미터를 하이퍼파라미터라고 부른다.
→ 머신러닝 라이브러리 사용시 클래스나 메서드의 매개변수로 표현된다.
튜닝하는 작업
- 라이브러리가 제공하는 기본값을 사용하여 모델 훈련
- 검증세트나 교차검증을 통해서 매개변수를 조금씩 변경
- 여러개의 매개변수의 최적값을 동시에 바꿔가며 찾아야 한다 → 한개 찾고 다음꺼 찾으면 안됨
매개변수가 많아지면 문제는 더욱 복잡해진다.
→ 사이킷런에서 제공하는 그리드 서치를 사용한다.
GridSearchCV 클래스는 하이퍼파라미터 탐색과 교차 검증을 한번에 수행한다.
별도로 교차검증을 할 필요가 없다. (cross_validate 함수 필요없음)
탐색할 매개변수와 탐색할 값의 리스트를 params 딕셔너리로 만든다.
→ params = {’min_impurity_decrease’: [0.0001, 0.0002, 0.0003, 0.0005]}
결정트리 클래스의 객체를 생성하자마자 그리드서치 매개변수로 바로 전달하는것이 가능하다.
→ gs = GridSearchCV(DecisionTreeClassifier(random=42), params, n_jobs=-1)
이 메서드 호출시 그리드 서치 객체는 결정트리모델 min_impurity_decrease 값을 바꿔가며 총 5번 실행한다. (GridSearchCV의 cv 매개변수 기본값은 5)
훈련이 끝나면 25개의 모델중에서 검증 점수가 가장 높은 모델의 매개변수 조합으로 전체 훈련 세트에서 자동으로 다시 모델을 훈련한다. → 훈련한 모델은 best_estimator_ 속성에 저장되어 있다.
이 모델을 일반 결정트리처럼 사용이 가능하다.
그리드 서치로 찾은 최적의 매개변수는 best_params_속성에 저장
각 매개변수에서 수행한 교차 검증의 평균 점수는 cv_result 속성의 ‘mean_test_score’키에 저장
→ gs.cv_result[‘mean_test_score’]
params에 더욱 복잡한 매개변수 조합을 넣을 수도 있다.
params = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001), #불순도 감소 최소량: 9개
'max_depth': range(5, 20, 1), #트리의 깊이: 15개
'min_samples_split': range(2, 100, 10) #노드를 나누기 위한 최소 샘플 수: 10개 }</code></pre>
np.arange와 range 차이는 range 함수는 정수만 가능하나 np.arange 함수는 실수도 가능하다
이 params 매개변수로 수행할 교차 검증 횟수는 9 x 15 x 10 = 1,350개이다.
기본 5-폴드 교차 검증을 수행하므로 만들어지는 모델의 수는 1350 x 5 = 6750개가 됩니다.
그리드 서치 객체로 매개변수 n_jobs = -1로 지정시 가능한 모든 코어를 사용해서 계산
랜덤서치
매개변수의 값이 수치일 경우 범위나 간격을 미리 정하기 어려울 때는 랜덤 서치를 사용한다.
매개변수 값의 목록을 전달하는 것이 아니라 매개변수를 샘플링 할 수 있는 확률 분포 객체를 전달한다.
사이파이에서 2개의 확률 클래스를 임포트
→ from scipy.stats import uniform, randint
균등분포에서 샘플링한다. randint에서는 정수, uniform에서는 실수를 뽑는다.
rgen = randint(0, 10) → 0에서 9까지의 랜덤한 정수
rgen.rvs(10) → 10개의 랜덤한 변수를 샘플링
uniform도 똑같이 수행하면 된다.
min_samples_leaf 매개변수는 노드가 분할하여 만들어질 자식 노드의 샘플수가 이 값보다 작을 경우 분할하지 않는다.
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
#n_iter는 샘플링 횟수 지정(prarms에 있는 랜덤분포에서의 샘플링 횟수)
gs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42), params, n_iter=100,
n_jobs=-1, random_state=42)
gs.fit(train_input, train_target)
Copyright 2021. 박해선 All rights reserved.