728x90
Model Tuning (Hyperparameter Optimization)
- 학습을 수행하기 전에 설정해야하는 값인 하이퍼파리마터의 최적값을 탐색
Grid Search
- 하이퍼파라미터별로 다양한 값들을 지정해서 모든 조합에 대해 성능 결과를 측정한 후 가장 높은 성능을 발휘했던 하이퍼파라미터 조합을 선정하는 방법
- 오래걸려서 잘 안쓰게 될 것 같다...
from sklearn.model_selection import KFold
cv = KFold(n_splits=5,shuffle=True,random_state=SEED) # cv =cross valid
적용
from sklearn.model_selection import GridSearchCV
from lightgbm import LGBMClassifier
hp = {
"max_depth" : range(2,5), # 깊이
"min_samples_split" : range(2,5), # 내부노드를 분할하는데 필요한 최소 샘플 수
"criterion" : ["gini","entropy"], # 순수도 척도
"max_leaf_nodes" : range(5,10), # 최대 리프 노드수
"n_estimators": range(50,100,10) # 부스팅 단계 수
}
model = LGBMClassifier(random_state=SEED)
grid = GridSearchCV(
model,
hp,
cv=cv,
scoring = "roc_auc",
n_jobs = -1
)
grid.fit(x_train,y_train)
=>
GridSearchCV(cv=KFold(n_splits=5, random_state=42, shuffle=True),
estimator=LGBMClassifier(random_state=42), n_jobs=-1,
param_grid={'criterion': ['gini', 'entropy'],
'max_depth': range(2, 5),
'max_leaf_nodes': range(5, 10),
'min_samples_split': range(2, 5),
'n_estimators': range(50, 100, 10)},
scoring='roc_auc')
최적의 파라미터 값 조회
grid.best_params_
=>
{'criterion': 'gini',
'max_depth': 2,
'max_leaf_nodes': 5,
'min_samples_split': 2,
'n_estimators': 50}
최적의 스코어 값 조회
grid.best_score_
=> 0.8578552243327711
Grid score 조회
grid.score(x_valid,y_valid)
-----------------------------------------
pred = grid.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8893822393822393
Random Search
- 하이퍼파라미터 별로 다양한 값들을 지정하여 랜덤 조합을 통해 반복수행하여 가장 높은 성능을 발휘했던 하이퍼파라미터 조합을 선정
- grid보다 조금 좋다.
from sklearn.model_selection import RandomizedSearchCV
hp = {
"max_depth" : range(2,15), # 깊이
"min_samples_split" : range(2,10), # 내부노드를 분할하는데 필요한 최소 샘플 수
"criterion" : ["gini","entropy"], # 순수도 척도
"max_leaf_nodes" : range(5,10), # 최대 리프 노드수
"n_estimators": range(50,201,10) # 부스팅 단계 수
}
model = LGBMClassifier(random_state=SEED)
rand = RandomizedSearchCV(
model,
hp,
cv=cv,
scoring = "roc_auc",
n_jobs = -1,
random_state=SEED,
n_iter = 15
)
rand.fit(x_train,y_train)
Random Search는 Grid보다 속도가 약간 빨랐다.
값도 다양하게 지정하기 때문에 성능도 높아졌다.
최적의 파라미터 값 조회
rand.best_params_
=>
{'n_estimators': 70,
'min_samples_split': 2,
'max_leaf_nodes': 5,
'max_depth': 2,
'criterion': 'entropy'}
Random score 조회
model = LGBMClassifier(random_state = SEED, **rand.best_params_) # (**rand.best_params_) 파일형태로 저장하였다가 필요할 때 사용하는 예시
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.890990990990991
Grid Search vs Random Search
Random Search는 Grid Search에 비해 불필요한 반복 수행 횟수를 대폭 줄이면서
동시에 정해진 간격(Grid) 사이에 위치한 값들에 대해서도 확률적으로 탐색이 가능해서
최적의 하이퍼파라미터를 더 빨리 찾을 수 있다.
베이지안 최적화(Bayesian Optimization)
- 매회 새로운 하이퍼파라미터 값에 대한 조사를 수행할 시 사전지식을 충분히 반영하면서 동시에 전체적인 탐색과정을 체계적으로 수행할 수 있는 방법
- 대체모델이라는 걸 이용해서 이전 하이퍼파라미터조합의 적용결과를 기반으로 더 높은 성능점수를 얻는 하이퍼파라미터 조합을 예측하는 방식
- 직관적이라 많이 사용한다.
optuna 설치
!pip install optuna
목적함수 만들기
import optuna
from sklearn.model_selection import cross_val_score
def objective(trial): # 시도객체가 들어간다
hp = {
"max_depth" : trial.suggest_int("max_depth",2,15), # 찾을 범위의 최소값과 최대값
"min_samples_split" : trial.suggest_int("min_samples_split",2,10),
"criterion" : trial.suggest_categrical("criterion",["gini","entropy"]),
"max_leaf_nodes" : trial.suggest_int("max_leaf_nodes",5,10),
"n_estimators" : trial.suggest_int("n_estimators",10,500),
"learning_rate" : trial.suggest_float("learning_rate",0.01,0.1)
}
cv = KFold(n_splits=5,shuffle=True,random_state=SEED) # SEED 함수내부에서 전역변수 사용 (이렇게하면 안됨!)
model = LGBMClassifier(random_state=SEED,**hp)
scores = cross_val_score(model, x_train, y_train, cv = cv, scoring="roc_auc") # 리스트가 넣어옴
return np.mean(scores)
위처럼 함수로 구현할 수 가 있다.
코드를 살펴보면 하나하나 다 직관적이라 보기에는 편해보이나 혼자 코드를 짜려면 매우 어려울 것 같다...
sampler = optuna.samplers.TPESampler(seed = SEED) # 대체모델 부분
# 스터디 객체
study = optuna.create_study(
direction= "maximize", # 높은게 좋은지 낮은게 좋은지 설정 (maximize or minimize)
sampler = sampler
)
study.optimize(objective,n_trials=50)
=>
[I 2022-09-13 10:40:45,679] A new study created in memory with name: no-name-e8ae915b-df98-4391-aacb-5f09432ce5ba
[I 2022-09-13 10:40:45,853] Trial 0 finished with value: 0.8522732281153486 and parameters: {'max_depth': 7, 'min_samples_split': 10, 'criterion': 'gini', 'max_leaf_nodes': 5, 'n_estimators': 86, 'learning_rate': 0.015227525095137952}. Best is trial 0 with value: 0.8522732281153486.
[I 2022-09-13 10:40:46,678] Trial 1 finished with value: 0.842336280687235 and parameters: {'max_depth': 14, 'min_samples_split': 7, 'criterion': 'gini', 'max_leaf_nodes': 10, 'n_estimators': 418, 'learning_rate': 0.029110519961044856}. Best is trial 0 with value: 0.8522732281153486.
[I 2022-09-13 10:40:46,865] Trial 2 finished with value: 0.847517887036954 and parameters: {'max_depth': 4, 'min_samples_split': 3, 'criterion': 'entropy', 'max_leaf_nodes': 7, 'n_estimators': 152, 'learning_rate': 0.06506676052501416}. Best is trial 0 with value: 0.8522732281153486.
[I 2022-09-13 10:40:46,995] Trial 3 finished with value: 0.8527045845122097 and parameters: {'max_depth': 3, 'min_samples_split': 4, 'criterion': 'entropy', 'max_leaf_nodes': 9, 'n_estimators': 108, 'learning_rate': 0.05628109945722505}. Best is trial 3 with value: 0.8527045845122097.
...
베인지안 최적화를 보면 높은 값과 낮은 값을 설정해주어야 한다.
print("Best Score:",study.best_value) # 최고점수
print("Best hp", study.best_params) # 최고점수의 하이퍼파라미터조합
=>
Best Score: 0.8612226995693584
Best hp {'max_depth': 2, 'min_samples_split': 2, 'criterion': 'entropy', 'max_leaf_nodes': 10, 'n_estimators': 81, 'learning_rate': 0.04761586218744837}
검증셋 점수 확인
model = LGBMClassifier(random_state=SEED, **study.best_params)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8868725868725869
하이퍼파라미터 중요도 시각화
optuna.visualization.plot_param_importances(study)
하이퍼파라미터 최적화 과정 history
optuna.visualization.plot_optimization_history(study)
강사님이 마지막에 __call__함수를 이용하여 클래스로 만드는 것을 보여주셨는데 이해가 안된다.
클래스에 대해 다시 봐야할 것 같다...
728x90
'AI 공부 > 머신러닝' 카테고리의 다른 글
(머신러닝) data leakage (0) | 2022.09.15 |
---|---|
(머신러닝) 비지도 학습 - 차원축소 (1) | 2022.09.14 |
(머신러닝) 앙상블 (0) | 2022.09.13 |
(머신러닝) 머신러닝 모델 (2) | 2022.09.13 |
(머신러닝) sklearn (0) | 2022.09.11 |
댓글