import pandas as pd
df = pd.read_csv('https://archive.ics.uci.edu/ml/'
'machine-learning-databases'
'/breast-cancer-wisconsin/wdbc.data', header=None)
from sklearn.preprocessing import LabelEncoder
X = df.loc[:, 2:].values
y = df.loc[:, 1].values
le = LabelEncoder()
y = le.fit_transform(y)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = \
train_test_split(X, y,
test_size=0.20,
stratify=y,
random_state=1)
비교를 위해 GridSearchCV
실행 결과를 출력합니다.
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline
import numpy as np
pipe_svc = make_pipeline(StandardScaler(),
SVC(random_state=1))
param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]
param_grid = [{'svc__C': param_range,
'svc__kernel': ['linear']},
{'svc__C': param_range,
'svc__gamma': param_range,
'svc__kernel': ['rbf']}]
gs = GridSearchCV(estimator=pipe_svc,
param_grid=param_grid,
cv=10,
n_jobs=-1)
gs = gs.fit(X_train, y_train)
print(gs.best_score_)
print(gs.best_params_)
print(np.sum(gs.cv_results_['mean_fit_time']))
0.9846859903381642 {'svc__C': 100.0, 'svc__gamma': 0.001, 'svc__kernel': 'rbf'} 2.9397503376007084
사이킷런 0.24 버전에서 추가된 HalvingGridsearchCV
는 모든 파라미터 조합에 대해 제한된 자원으로 실행한 다음 가장 좋은 후보를 골라서 더 많은 자원을 투여하는 식으로 반복적으로 탐색을 수행합니다. 이런 방식을 SH(Successive Halving)이라고 부릅니다. HalvingGridsearchCV
의 resource
매개변수는 반복마다 늘려갈 자원을 정의합니다. 기본값은 'n_samples'
로 샘플 개수입니다. 이 외에도 탐색 대상 모델에서 양의 정수 값을 가진 매개변수를 지정할 수 있습니다. 예를 들면 랜덤 포레스트의 n_estimators
가 가능합니다.
factor
매개변수는 반복마다 선택할 후보의 비율을 지정합니다. 기본값은 3으로 후보 중에서 성능이 높은 1/3만 다음 반복으로 전달합니다. max_resources
매개변수는 각 후보가 사용할 최대 자원을 지정합니다. 기본값은 'auto'
로 resources='n_samples'
일 때 샘플 개수가 됩니다.
min_resources
는 첫 번째 반복에서 각 후보가 사용할 최소 자원을 지정합니다. resources='n_samples'
이고 min_resources='smallest'
이면 회귀일 때 cv
$\times$ 2가 되고 분류일 때는 cv
$\times$ 클래스개수 $\times$ 2가 됩니다. 그외에는 1입니다. min_resources='exhaust'
이면 앞에서 계산한 값과 max_resources
를 factor
**n_required_iterations
으로 나눈 몫 중 큰 값입니다. 기본값은 'exhaust'
입니다(n_required_iterations
는 $ \text{log}_{factor}(전체 후보 갯수) + 1$ 입니다).
마지막으로 aggressive_elimination
매개변수를 True
로 지정하면 마지막 반복에서 factor
만큼 후보가 남을 수 있도록 자원을 늘리지 않고 초기에 반복을 여러 번 진행합니다. 기본값은 False
입니다.
HalvingGridsearchCV
아직 실험적이기 때문에 sklearn.experimental
패키지 아래에 있는 enable_halving_search_cv
을 임포트해야 사용할 수 있습니다. verbose=1
로 지정하면 각 반복 과정을 자세히 살펴 볼 수 있습니다.
from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingGridSearchCV
hgs = HalvingGridSearchCV(estimator=pipe_svc,
param_grid=param_grid,
cv=10,
n_jobs=-1, verbose=1)
hgs = hgs.fit(X_train, y_train)
print(hgs.best_score_)
print(hgs.best_params_)
n_iterations: 3 n_required_iterations: 4 n_possible_iterations: 3 min_resources_: 40 max_resources_: 455 aggressive_elimination: False factor: 3 ---------- iter: 0 n_candidates: 72 n_resources: 40 Fitting 10 folds for each of 72 candidates, totalling 720 fits ---------- iter: 1 n_candidates: 24 n_resources: 120 Fitting 10 folds for each of 24 candidates, totalling 240 fits ---------- iter: 2 n_candidates: 8 n_resources: 360 Fitting 10 folds for each of 8 candidates, totalling 80 fits 0.9803968253968254 {'svc__C': 100.0, 'svc__gamma': 0.001, 'svc__kernel': 'rbf'}
출력 결과를 보면 첫 번째 반복(iter: 0)에서 72개의 후보를 40개의 샘플로 교차 검증을 수행합니다. 여기에서 72/3 = 24개의 후보를 뽑아 두 번째 반복(iter: 1)을 수행합니다. 두 번째 반복에서는 40 * 3 = 120개의 샘플을 사용합니다. 같은 방식으로 세 번째 반복(iter: 2)에서는 8개의 후보가 360개의 샘플로 평가됩니다. 최종 결과는 98.3%로 GridSearchCV
보다 조금 낮습니다. 찾은 매개변수 조합도 달라진 것을 볼 수 있습니다.
3번의 반복 동안 HalvingGridSearchCV
가 수행한 교차 검증 횟수는 모두 104번입니다. 각 교차 검증에 걸린 시간은 cv_results_
속성의 mean_fit_time
에 저장되어 있습니다. 이를 GridSearchCV
와 비교해 보면 5배 이상 빠른 것을 볼 수 있습니다.
print(np.sum(hgs.cv_results_['mean_fit_time']))
0.38695635795593264
각 반복 단계에서 사용한 샘플 개수와 후보 개수는 각각 n_resources_
속성과 n_candidates_
속성에 저장되어 있습니다.
print('자원 리스트:', hgs.n_resources_)
print('후보 리스트:', hgs.n_candidates_)
자원 리스트: [40, 120, 360] 후보 리스트: [72, 24, 8]