만약 min_impurity_decrease 외에도 더 다양한 매개변수를 탐색해보고 싶다면 얼마나 촘촘히 매개변수 값들의 간격을 설정하느냐에 따라 교차검증을 해야하는 모델의 개수가 크게 늘어날 수 있다.
다음과 같은 params dictionary 를 예로 들어보자면, 9개의 min_impurity_decrease 와 15개의 max_depth 와 10개의 min_samples_split 을 5-fold 로 교차검증할 시, 총 6750개의 모델의 훈련이 요구된다.
params = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001),
'max_depth': range(5,20,1),
'min_samples_split': range(2,100,10)}
따라서 다양한 parameters 를 촘촘한 간격으로 테스트하고 싶을 때 이전과 같은 grid search 를 이용하면 꽤 많은 메모리와 시간 등이 필요하다.
Grid search 의 약점을 보완하기 위해 우리는 random search 를 이용할 수 있다.
Random search selects a value for each hyperparameter independently using a probability distribution.
이는 특히 random sampling 을 통해 보다 넓은 범위 또는 분포를 효율적으로 탐색할 수 있다는 장점을 가진다. Scipy 의 stats 가 제공하는 uniform 과 randint 는 각각 실수와 정수에 대한 균등 분포 샘플링을 담당하므로 다음과 같이 parameters 의 탐색 범위를 지정하는데 사용하도록 하자.
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)}
이후 sklearn 의 RandomizedSearchCV class 생성 시 우리의 모델과 params 를 feed 해준다. 참고로 n_iter 은 해당 params 범위들 내에서 random sampling 실행 횟수인 동시에 만들어야 할 모델의 개수를 의미하며, n_jobs 는 필요한 tasks 를 몇 개의 parallel 한 작업으로 진행할지를 specify 한다. 특히 이 값이 -1 이라면 가능한 모든 processors 를 이용하도록 한다.
from sklearn.model_selection import RandomizedSearchCV
gs = RandomizedSearchCV(DecisionTreeClassifier, params, n_iter=100, n_jobs=-1)
gs.fit(train_input, train_target)
그렇다면 훈련과 검증을 반복하며 얻은 최적의 매개변수 조합 및 평균 점수를 알아보자.
print(gs.best_params_)
# {'max_depth': 21, 'min_impurity_decrease': 0.00026332784129117875, 'min_samples_leaf': 3, 'min_samples_split': 3}
print(np.max(gs.cv_results_['mean_test_score']))
# 0.8685775893980899
이와 같이 각각의 항목에 대한 최적해를 이용해 얻은 평균 검증 점수는 약 86.9% 이다. 또한, 최적해에 대한 정보를 RandomizedSearchCV class 에게 알려준 후 훈련세트와 검증세트를 합쳐 학습한 모델로 테스트세트를 평가한다면 약 86.6% 를 얻게 된다.
dt = gs.best_estimator_
print(dt.score(test_input, test_target)) # 0.8661538461538462
일반적으로 test score 는 validation score 보다 조금 낮으므로 이상적인 결과라고 할 수 있겠다.