본문 바로가기
AI 공부/머신러닝

(머신러닝) 모델튜닝

by AI Sonny 2022. 9. 13.
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

댓글