Hyperparameter와 Parameter를 구분하는 기준은 사용자가 직접 설정하느냐 아니냐이다.
Hyperparameter Tuning 정의
Hyperparameter Tuning 필요성
위의 그래프를 보면, 모델은 Random Forest로 동일하지만, 모델의 Hyperparameter인 max_features 변수를 다르게 설정함에 따라 OOB error값이 달라진다. (
OOB error에 대해서는 다른 포스팅에서 설명하겠다. 지금은, 모델의 성능을 나타내는 값이라 이해하면 된다.) 따라서, 우리가 어떠한 Hyperparameter를 설정, 즉 Hyperparameter Tuning을 어떻게 하냐에 따라 모델의 성능이 좌지우지 될 수 있다.
주의사항
📌 Hyperparameter Tuning 시, test 데이터를 사용해서는 안 된다. Test 데이터는 모델의 최종 성능 평가에만 사용된다. (Test 데이터를 우리가 아예 모르는 미래의 어떠한 데이터라 생각하면 이해하기 쉽다.)
📌 주의사항 : Hyperparameter Tuning 의 종류에 따라 시간이 너무 오래 걸릴 수 있다. 따라서, 예를 들어 하나의 변수를 고정하고, 다른 변수를 변화시키면서 하나하나 일일이 대입해보면서 성능의 변화를 통해 대략적인 감으로 튜닝을 진행해야 할 수도 있다. (실제로 필자가 대용량 데이터를 다루면서 겪어본 바이다.)
Grid Search를 한 문장으로 표현하자면 다음과 같다.
제시한 Hyperparameter 들을 모두 조합하여 모델에게 가장 적합한 Hyperparameter 를 찾는 방법
정의
Grid Search 는 간단하고 광범위하게 사용되는 Hyperparameter 탐색 알고리즘이다. 사용자가 지정한 grid에 속한 모든 Hyperparameter를 조합하여 최고의 조합을 비교해가며 찾는 과정을 뜻한다. 실험할 Hyperparameter를 명시적으로 정해줘야 한다.
장점
단점
코드
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
### 파라미터를 딕셔너리 형태로 설정
params = {'max_depth' : [1,2,3], 'min_samples_split' : [2,3]}
iris = load_iris()
data = iris.data
label = iris.target
x_train, x_test, y_train, y_test = train_test_split(data, label,
test_size = 0.2,
random_state=121)
dtree = DecisionTreeClassifier(random_state=156)
# param_grid의 하이퍼 파라미터를 3개의 train, test set fold로 나누어 테스트
### refit = True가 default. True이면 가장 좋은 파라미터 설정으로 재학습시킴
grid_dtree = GridSearchCV(dtree, param_grid = params, cv=3, scoring = 'accuracy', refit=True)
# 붓꽃 학습 데이터로 param_grid의 하이퍼 파라미터를 순차적으로 학습/평가
grid_dtree.fit(x_train, y_train)
print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
print('GridSearchCV 최고 정획도: {:.4f}'.format(grid_dtree.best_score_))
GridSearchCV 최적 파라미터: {'max_depth': 3, 'min_samples_split': 2}
GridSearchCV 최고 정획도: 0.9750
from sklearn.metrics import accuracy_score
pred = grid_dtree.predict(x_test)
print('테스트 데이터 세트 정확도: {0:.4f}'.format(accuracy_score(y_test, pred)))
테스트 데이터 세트 정확도: 0.9667
Random Search를 한 문장으로 표현하자면 다음과 같다.
주어진 구간 안에서 랜덤으로 숫자를 뽑은 후 이를 조합하여 가장 적합한 Hyperparameter 를 찾는 방법
정의
Random Search 는 사용자가 정한 범위 내에서 임의의 조합을 추출하여 최적의 Hyperparameter 조합을 찾는 방법이다. Grid Search 와는 다르게 실험할 Hyperparameter를 구간으로 주거나 직접적인 값을 넣어주기도 한다. 랜덤으로 총 몇 개의 조합을 뽑을지 명시해줄 수 있다.
장점
단점
Hyperparameter의 범위가 너무 넓으면, 일반화된 결과가 나오지 않음 (할 때마다 달라짐)
Grid Search 와 마찬가지로 최종 성능이 최고점이 아닐 가능성이 높음
코드
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.model_selection import RandomizedSearchCV
iris = load_iris()
data = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(random_state=156)
x_train, x_test, y_train, y_test = train_test_split(data, label,
test_size = 0.2,
random_state=100)
# 구간으로 주거나 직접적인 값을 넣기도 함. 랜덤으로 뽑아서 사용
params = {'max_depth' : range(1,11),
'max_leaf_nodes' : range(3,31,3),
'criterion' : ['gini', 'entropy']}
# k-fold 방식으로 최적의 하이퍼 파라미터 값을 찾아내는 과정
rs = RandomizedSearchCV(dt_clf, param_distributions = params,
n_iter = 6, cv = 4, refit = True,
scoring = 'accuracy',
random_state = 101, n_jobs = -1)
# param_distributions : 하이퍼 파라미터 목록 전달
# n_iter : 파라미터 검색 횟수 (총 랜덤으로 뽑은 조합 개수)
# cv : 교차검증 시 fold 개수
rs.fit(x_train, y_train)
print('RandomSearchCV 최적 파라미터:', rs.best_params_)
print('RandomSearchCV 최고 정획도: {:.4f}'.format(rs.best_score_))
RandomSearchCV 최적 파라미터: {'max_leaf_nodes': 6, 'max_depth': 4, 'criterion': 'gini'}
RandomSearchCV 최고 정획도: 0.9667
만약 여러분이 충분히 원하는 예측 결과가 나오지 않은 상태에서 Hyperparameter Tuning 을 통해 성능 개선을 원한다면, Hyperparameter Tuning 보다는 데이터에 대한 접근 및 모델링 방식을 다시 한 번 생각해 보는것을 추천한다. Hyperparameter Tuning 으로 개선할 수 있는 부분은 어느 정도 한계가 존재한다.
추후에, Bayesian Optimization에 대해 다루고, 이를 이용한 HyperOpt에 대해 소개하겠다. (가능하면 Optuna도)