본문 바로가기
인공지능 개발하기/Machine Learning

하이퍼파라미터 최적화 (Hyperparameter Optimization)

by 선의공 2024. 2. 18.

 
 

 
이번 포스팅에서는 하이퍼파라미터 최적화 방법론에 대해서
학습해보겠습니다.
해당 포스팅을 참조했습니다.
 
https://velog.io/@emseoyk/%ED%95%98%EC%9D%B4%ED%8D%BC%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%ED%8A%9C%EB%8B%9D

 

하이퍼파라미터 튜닝

캐글 노트북으로 하이퍼파라미터 튜닝 공부

velog.io


 
 

1. 하이퍼 파라미터 최적화(HyperParameter Optimization)란?

 
모델의 최적의 가중치를 구하기 위한
최적의 하이퍼 파라미터 조합을 찾는 것 입니다.
 
예를들어 tensorflow 측면에서 보자면
model의 epochs, batch_size,
layer의 활성함수 선택, 노드 수 조절, 레이어 층 수 조절
split의 random_state를 변경하는 등이
하이퍼파라미터 조합을 찾는 과정이죠.
 
머신러닝 측면에서 보자면 이전 포스팅에서 작성한
SVC 같은 경우도 kernel, C, 감마 등이 하이퍼파라미터에 포함됩니다.
 
머신러닝에서는 이 개념의 하이퍼 파라미터의 최적화 방식을 
더 효율적으로 만들어주는 자동화 방법론들이 있습니다.
(tensorflow keras에도 동일하게
하이퍼파라미터 최적화 자동화 방법론을 적용한 tuner라는
자동 파라미터 최적화 개념이 있습니다!
나중에 포스팅해보겠습니다)
 
 
 


 

2. 하이퍼 파라미터 최적화의 종류

 
하이퍼 파라미터 최적화의 종류에는 아래의 방법 등등..이 있다고 합니다!
 
Manual Search,
Grid Search,
Random Search,
Bayesian Optimization
Non-Probabilistic
Evolutionary Optimiaztion,
Gradient-based Optimization
 
 
이번 포스팅에서는 자주 사용하는 개념인
Manual Search,
Grid Search,
Random Search,
Bayesian Optimization
가 뭔지 알아보도록 하겠습니다.
 
 


 

2-1 Manual Search

 
 
수동 하이퍼 파라미터 최적화 방법입니다.
경험적으로 혹은 감으로 직접 일일히 하이퍼 파라미터를 변경해 가면서 
최적의 모델을 비교하며 찾아가는 방식이에요.
대부분 성능이 잘 나오는 값들이 있기에
그대로 따라가는 경우가 있으나,
조합 별 성능을 비교하기 어렵다는 단점이 있습니다.
 
 
직접 파라미터 튜닝을 해보겠습니다.
 
기존 코드입니다.
SVC 모델의 하이터 파라미터는 default 값으로 설정된 상태입니다.
accuracy score는 0.69 나오고 있습니다.

import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

#데이터
X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

#모델구성
model = SVC() #parameters = kernel , C, gamma, degree, max_iter

#훈련
model.fit(X_train, y_train)

#평가 예측

predict = np.round(model.predict(X_test))
acc_score = accuracy_score(y_test, predict)
print(f'''
    {type(model).__name__} predict is [{predict}]
    accuracy score is [{ acc_score}]"
    ''')

'''
    SVC predict is [[0 1 0 1 1 0 0 1 1 1 1 1 0 1 0 1 1 2 1 0 1 1 0 0 1 1 0 1 1 1 0 0 1 1 1 1]]
    accuracy score is [0.6944444444444444]"
'''

 
 
SVC의 파라미터를 임의로 변경해서 accuracy score를 0.75로 올렸습니다.
이런식으로 하이퍼파라미터를 직접 설정하는 방식이 Manual Search 방식입니다!

#모델구성
model = SVC(kernel='rbf', C=10, gamma=0.00001, degree=10, max_iter=10) 

'''
    SVC predict is [[0 2 1 1 2 0 0 1 2 2 1 2 0 2 0 1 1 2 2 0 1 2 0 0 2 1 0 2 2 2 0 1 1 2 2 2]]
    accuracy score is [0.75]"
'''

 
 


 

 

2-2 Grid Search

 
파라미터 범위 내의 모든 조합을 이용해서
하이퍼파라미터 최적화를 진행하는 방법입니다.
 
탐색 범위 정의가 필요합니다.
모든 조합을 살펴봄으로서 하이퍼파라미터나 데이터가 많은 경우
시간이 많이 걸리게 됩니다.
 
  Scikit learn의 GridSearchCV를 사용해줬습니다.
GridSearchCV는 이름에서 CV가 보이듯
데이터셋 교차 검증과 하이퍼파라미터 최적화를 같이 해줄 수 있습니다!

# GridSearch
import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score

#데이터
X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

#모델구성
model = SVC() #parameters = kernel , C, gamma, degree, max_iter

parameters = {'kernel' : ['linear','rbf','poly','sigmoid'],
              'C' : [1,3,5,10],
              'degree' : [5, 10, 15, 20],
              'max_iter' : [1, 5, 10 ,15, 20]}
gscv = GridSearchCV(estimator=model, param_grid= parameters, cv= 5, n_jobs= -1)

#훈련
gscv.fit(X_train, y_train)

#평가 예측
best_model = gscv.best_estimator_
best_param = gscv.best_params_
predict = np.round(best_model.predict(X_test))
acc_score = accuracy_score(y_test, predict)
print(f'''
    best parameters : {best_param}
    {type(model).__name__} predict is [{predict}]
    accuracy score is [{ acc_score}]"
    ''')
'''
    best parameters : {'C': 10, 'degree': 5, 'kernel': 'rbf', 'max_iter': 15}
    SVC predict is [[0 2 0 1 2 0 0 1 2 2 1 2 0 2 0 1 1 2 2 0 1 2 0 0 2 1 0 2 2 2 0 0 1 2 2 2]]
    accuracy score is [0.7777777777777778]"
'''

 
훈련이 끝나면 탐색된 best 점수의
parameters 와
모델을 반환 받을 수 있습니다.
GridSearchCV를 사용해줌으로서 
accyracy_score가 0.27정도 상승했네요.
 
 


 

2-3. Random Search

 
임의의 조합을 추출해서 최적의 하이퍼파라미터 조합을 찾는 방법입니다.
Grid Search 보다 빠르며, 시간 대비 성능이 좋다고합니다.
마찬가지로 Scikitlearn에서 제공하는 클래스는 RandomSearchCV로
CV가 들어가며, 교차검증도 같이 해줄 수 있습니다.

# RandomSearch
import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from sklearn.metrics import accuracy_score

#데이터
X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

#모델구성
model = SVC() #parameters = kernel , C, gamma, degree, max_iter

parameters = {'kernel' : ['linear','rbf','poly','sigmoid'],
              'C' : [1,3,5,10],
              'degree' : [5, 10, 15, 20],
              'max_iter' : [1, 5, 10 ,15, 20]}
gscv = RandomizedSearchCV(estimator=model, param_distributions= parameters, cv= 5, n_jobs= -1)

#훈련
gscv.fit(X_train, y_train)

#평가 예측
best_model = gscv.best_estimator_
best_param = gscv.best_params_
predict = np.round(best_model.predict(X_test))
acc_score = accuracy_score(y_test, predict)
print(f'''
    best parameters : {best_param}
    {type(model).__name__} predict is [{predict}]
    accuracy score is [{ acc_score}]"
    ''')
'''
    best parameters : {'max_iter': 1, 'kernel': 'linear', 'degree': 15, 'C': 5}
    SVC predict is [[0 2 2 1 2 0 0 1 2 2 1 1 0 2 0 1 1 2 2 0 1 2 0 0 2 1 0 1 2 2 0 2 1 1 2 2]]
    accuracy score is [0.6944444444444444]"
'''

 
결과적으로 accuracy_score 가 GridSearch보다는 낮게 나왔습니다..
RandomSearchCV를 사용하므로서 
탐색 시간은 빨라졌습니다.
 
RandomSearchCV가 좋은 결과를 뽑아낼 수 있는 경우도 있다고 하니,
여러가지 조합을 사용해보는게 좋을 것 같습니다.
 
 


 

2-4 Bayesian Optimization

 
베이지안 최적화는 베이지안 이론을 적용한 최적화 방법인듯 해요.
베이지안 이론은 확률의 개념인데,
일어나지 않은 일을 예측하는 방식이라고 합니다. 
 
두가지 중요 개념이 있다고 합니다
1. Surrogate model: 설정한  목적함수에 대한 확률적인 추정을 하는 모델
 
2. Acquisition function : Surrogate model이 확률적으로 추정한 결과를 바탕으로
다음 하이퍼파라미터 조합을 추천하는 함수
 
 
결국 베이지안 최적화는 베이지안 이론을 적용해
설정한 목적함수와 하이퍼파라미터의 조합으로
Surrogate model 모델을 만들어서 평가하고 
이 평가 기준으로 Acquisition function을 이용하고 
추천 조합을 받아가며 최적의 하이퍼 파라미터 최적화를 
예측하고 진행하는 방식인 듯 합니다! 

 
위 그림을 보면 가장 best 파라미터가 나온 시점을
빨간 세모 지점으로 표시해주고,
다음 과정에서 이 지점에서의
관찰을 해주고 있습니다.
이 과정을 반복하는 것을 알 수 있습니다.
 
 
이 방법이 적용된  API 가 Hyperopt, Optuna 튜너입니다.
 
Hyperopt, Optuna 
두 방식을 모두 사용해볼게요.!
 
(두 방식 모두 라이브러리 설치가 필요합니다
'pip install hyperopt'
'pip install optuna')
 
 

2-4-1 Hyperopt

 

최적의 하이퍼 파라미터를 뽑아주고
이 하이퍼 파라미터로 재훈련을 실시해줬습니다. 
위 개념에서 나온 목적함수는 def objective() 로서 구현해주네요.

import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from hyperopt import hp, fmin, tpe, STATUS_OK, Trials

# hp.choice : 리스트 내의 값을 무작위로 추출
# hp.uniform : 정의된 범위 내의 임의 숫자 추출
# hp.quniform : 정의된 범위에서 간격을 참고하여 숫자 추출
space = {
    'C': hp.uniform('C', 0.1, 10.0),
    "degree": hp.quniform("degree", 1, 10, 1),
    "max_iter": hp.quniform("max_iter", 1, 100, 10),
}
def objective(space):
    hopt = SVC(
               C = space['C'],
               degree= space['degree'],
               max_iter= space['max_iter']
               )
    return {'loss': -1, 'status' : STATUS_OK }

trials = Trials()
best_param = fmin(fn=objective,
                  space=space,
                  algo=tpe.suggest,
                  max_evals=10,
                  trials= trials)
# 재훈련
print(best_param)
model = SVC(**best_param)
model.fit(X_train, y_train)

# #평가 예측
predict = np.round(model.predict(X_test))
acc_score = accuracy_score(y_test, predict)
print(f'''
    best parameters : {best_param}
    {type(model).__name__} predict is [{predict}]
    accuracy score is [{ acc_score}]"
    ''')

'''
    best parameters : {'C': 8.863929212636368, 'degree': 5, 'max_iter': 21}
    SVC predict is [[0 2 0 1 2 0 0 1 2 2 1 2 0 2 0 1 1 2 2 0 1 2 0 0 2 1 0 2 2 2 0 0 1 2 2 2]]
    accuracy score is [0.7777777777777778]"
'''

 
 
 
 
 

2-4-2 Optuna

 

최적의 파라미터를 뽑아서 hyperopt와 동일하게
재 훈련을 해줘야합니다!
Optuna도 hyperopt와 동일한 방법론을 사용하므로 
목적함수를 objective() 함수를 정의해서
사용해주나 보네요.

# Optuna
import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from sklearn.metrics import accuracy_score
import optuna

def objective(trial: optuna.Trial):
    params = {
    'C': trial.suggest_uniform('C', 0.1, 10.0),
    "degree":  trial.suggest_int("degree", 1, 10, 1),
    "max_iter":  trial.suggest_int("max_iter", 1, 100, 10),
    }

    svc = SVC(**params)
    svc.fit(X_train, y_train)
    predictions = svc.predict(X_test)
    return accuracy_score(y_test, predictions)

study = optuna.create_study(study_name="obesity-accuracy", direction="maximize")
study.optimize(objective, n_trials=10)
best_study = study.best_trial
best_param = best_study.params

# 재훈련
model = SVC(**best_param)
model.fit(X_train, y_train)
# #평가 예측
predict = np.round(model.predict(X_test))
acc_score = accuracy_score(y_test, predict)
print(f'''
    best parameters : {best_param}
    {type(model).__name__} predict is [{predict}]
    accuracy score is [{ acc_score}]"
    ''')
'''
    best parameters : {'C': 7.544583675807302, 'degree': 5, 'max_iter': 21}
    SVC predict is [[0 2 0 1 2 0 0 1 2 2 1 2 0 2 0 1 1 2 2 0 1 2 0 0 2 1 0 2 2 2 0 0 1 2 2 2]]
    accuracy score is [0.7777777777777778]"
'''

 
 
 
저는 적은 하이퍼파라미터로 테스트를 해줘서
같은 결과가 나왔지만
두 방식을 비교한 글이 있습니다.
해당 글을 참고해서 두 방식 중 
더 나은 방식을 사용하면 될 듯 합니다!
https://neptune.ai/blog/optuna-vs-hyperopt#12

 

Optuna vs Hyperopt: Which Hyperparameter Optimization Library Should You Choose?

Comparision of Optuna vs Hyperopt, evaluating ease of use, hyperparameters, documentation, visualizations, speed, and experimental outcomes.

neptune.ai

 
 
 
 


 
 
이번 포스팅에서 하이퍼파라미터 최적화에 대해서
학습해봤습니다.
 
결과적으로 저는 테스트 범위가 적어
GridSearch, Optuna, hyperopt의 accuracy_score가 가장
좋게 나왔고
탐색 범위가 늘어난다면 편의성은 Optuna, hyperopt의 압승이 될 것 같습니다.
속도는 optuna가 가장 빨랐던 것 같습니다.
 
 
 
틀린점이 있다면 지적 부탁드립니다!
 
 

'인공지능 개발하기 > Machine Learning' 카테고리의 다른 글

Latent Space에 대해서  (0) 2024.11.12
결정트리(Decision Tree)  (0) 2024.03.28
교차검증(Cross-Validation)  (1) 2024.02.18
퍼셉트론과 XOR 문제  (0) 2024.02.18
SVM(Support Vector Mchine)  (1) 2024.02.13