[ Python ] Optuna Sampler 비교 (TPESampler VS SkoptSampler)

2020. 1. 24. 14:26분석 Python/구현 및 자료

하이퍼파라미터를 튜닝하는 방법에는 여러 가지가 있다.
일단 기본적으로 GridSearch 나 RandomSearch 같은 방법이 있다.
하지만 이 방법론은 각 파라미터를 돌릴 뿐이지, 최적의 파라미터를 찾아주지는 못한다.

이런 것을 활용하기 위해서 Bayesian Optimization 방법론을 사용하여야 한다.
아래 그림 중에서 밑에 실제 결과라는 부분은 learning rate에 따른 일반화 성능 함수를 나타낸다.
그러나 우리는 저기에서 어떤 learning rate가 최적의 값인지를 알지 못한다. 

그렇지만 실제로 딥러닝을 할 때는 저것을 순차적으로 한다면, 원하는 성능을 얻을 수 있다는 확신도 없이 계속 돌려야 한다. 그래서 많은 연구자들이 이러한 문제점을 해결하기 위해 병렬로 돌리는 것을 연구하였고 그중에 몇 가지 알고리즘이 개발되었다. 
그중에서 19년도 7월에 나온 optuna가 좀 더 편리한 것 같아서 써보기로 했다.
아래 그림에서 각 알고리즘 별로 기능별로 비교한 표가 있다.
저자가 주장하는 것은 optuna가 기존에 할 수 없었던 것을 다 할 수 있다고 한다.
보통 hyperopt와 비교를 하는 것 같지만 기능적 차이로 봤을 때 시각화하는 dashboard와 pruning 하는 것이 있다고 하는데, 추후에 pruning을 tensorflow 어떻게 쓸 수 있는지 알아봐야겠다.


 

Hyperparameter Optimization Framework  : Optuna

optuna를 그냥 쓰면 여러 모델을 병렬적으로 쓰는 기능밖에 제시를 안 한다. 
아래 코드에서는 x를 찾는 것을 하는데 TPESampler를 사용했다.
방법론에 대해서는 아래 문서를 참고하길 바란다.
많이 돌리면 결과는 비슷하게 나올 수 있겠지만 적은 시도로 최적의 값을 찾는 것이 중요하니 테스트를 해봤다.


TPESampler

https://optuna.readthedocs.io/en/stable/reference/samplers.html

 

Samplers — Optuna 1.0.0 documentation

A dictionary containing the parameter names and parameter’s distributions.

optuna.readthedocs.io

import optuna
from optuna.samplers import TPESampler
optuna.logging.disable_default_handler()

def objective(trial):
    x = trial.suggest_uniform('x', -10, 10)
    return (x-1)**2
if __name__ == '__main__':
    sampler = TPESampler(**TPESampler.hyperopt_parameters())
    study = optuna.create_study(direction='minimize',sampler=sampler)
    study.optimize(objective, n_trials=10)
    print('Number of finished trials: ', len(study.trials))

    print('Best trial:')
    trial = study.best_trial

    print('  Value: ', trial.value)

    print('  Params: ')
    for key, value in trial.params.items():
        print('    {}: {}'.format(key, value))

위에 결과물은 10번 시도했을 때, 1을 찾는 것이다. 해당 시도에서는 x : 0.6이라는 값을 찾았다

 


SkoptSampler

아래 integration에서 여러 가지 프레임워크와 호환돼서 사용할 수 있는 Pruner와 Skopt Sampler를 제공하고 있다.
bayesian optimization 방법론 중에서 목적함수의 대략적은 형태에 대한 확률추정 모델로써 Gaussian Process 확률 모델을 사용한다.
skopt는 Gaussian Process 확률 모델을 활용한다고 알고 있다.

https://optuna.readthedocs.io/en/stable/reference/integration.html

 

Integration — Optuna 1.0.0 documentation

Parameters: estimator – Object to use to fit the data. This is assumed to implement the scikit-learn estimator interface. Either this needs to provide score, or scoring must be passed. param_distributions – Dictionary where keys are parameters and values a

optuna.readthedocs.io

from optuna.integration import SkoptSampler
optuna.logging.disable_default_handler()
sampler = SkoptSampler(
    skopt_kwargs={'n_random_starts':5,
                  'acq_func':'EI',
                  'acq_func_kwargs': {'xi':0.02}})
if __name__ == '__main__':
    study = optuna.create_study(direction='minimize',sampler=sampler)
    study.optimize(objective, n_trials=10)
    print('Number of finished trials: ', len(study.trials))

    print('Best trial:')
    trial = study.best_trial

    print('  Value: ', trial.value)

    print('  Params: ')
    for key, value in trial.params.items():
        print('    {}: {}'.format(key, value))

같은 trial에 대해서 x : 0.97이라는 가까운 값을 얻을 수 있게 되었다!!

위에서는 Gaussian Process에서 다음 파라미터를 추천하는 함수를 Acquisition Function이라고 하는데,
여기선  Expected Improvement(EI)를 사용했다. EI는  exploration 전략 및 exploitation 전략 모두를 내재적으로 일정 수준 포함하도록 설계된 것으로, Acquisition Function으로 가장 많이 사용된다.

 

물론 두 개의 sampler는 trial를 좀 높이면 비슷한 값을 얻는 것을 확인했다.

많은 연구자들이 좀 더 효율적으로 하이퍼파라미터를 찾기 위해 다양한 알고리즘을 만들고 있다.
요즘엔 NASNet 과 같이 Network Arhictecture까지 알아서 만드는 연구도 이미 많이 진행되고 있다. 
AutoML이라는 영역이 점점 연구가 많이 되고 있는 것 같아서 개인적으로는 편하지만 불안하기도 하다.


추가적으로 tensorflow에서 해본 것인데,
기존에 skopt가 제공하던 같은 하이퍼파리미터에서 이미 있던 결과값을 gaussian process의 초기값에 넣어줄 수가 있을 것이 optuna에도 가능할 것 같아서 해보니 되는 것을 확인했다.

x0 = [[13, 3, 2, 4, 3, 4, 36, 32, 49, 40, 35, 'he_uniform', 3, 0.00015671897437797408], [10, 3, 4, 2, 2, 3, 34, 64, 45, 54, 40, 'he_normal', 3, 1.4147691642608397e-05], [12, 4, 3, 3, 4, 2, 46, 65, 62, 42, 57, 'xavier_uniform', 0, 0.0001151939657356718], [10, 3, 4, 2, 4, 4, 60, 34, 54, 63, 40, 'he_uniform', 3, 0.00023751936361984937], [11, 2, 4, 3, 4, 3, 38, 58, 39, 31, 63, 'caffe_uniform', 4, 1.185261441167407e-05], [12, 2, 2, 2, 2, 3, 43, 54, 42, 56, 30, 'caffe_uniform', 3, 2.8053303983617267e-05], [13, 3, 4, 3, 4, 2, 53, 31, 57, 31, 40, 'he_uniform', 1, 0.004342367249195597], [10, 3, 2, 2, 2, 2, 52, 56, 50, 40, 45, 'caffe_uniform', 2, 0.0002353657442834687], [12, 2, 3, 2, 2, 4, 37, 43, 38, 48, 56, 'xavier_normal', 2, 1.1695403014796976e-05], [10, 4, 3, 2, 4, 4, 62, 55, 56, 30, 44, 'xavier_uniform', 2, 0.00132122127636011], [12, 2, 4, 4, 3, 3, 64, 47, 60, 39, 64, 'xavier_normal', 3, 0.002818043271032938], [11, 2, 4, 3, 3, 4, 54, 34, 35, 49, 63, 'xavier_uniform', 1, 0.00011653454036311457], [12, 4, 2, 3, 4, 3, 51, 45, 36, 41, 40, 'caffe_uniform', 1, 0.0013094508034332806], [9, 3, 2, 4, 4, 3, 62, 51, 64, 36, 42, 'xavier_normal', 3, 0.006172462319995353], [8, 2, 3, 4, 2, 2, 65, 38, 38, 53, 65, 'xavier_uniform', 1, 0.004848434779819864], [8, 3, 2, 3, 2, 4, 65, 65, 60, 30, 30, 'caffe_uniform', 2, 0.09999999999999999], [10, 4, 4, 4, 3, 3, 65, 34, 65, 30, 46, 'xavier_normal', 3, 0.09999999999999999], [8, 2, 4, 3, 3, 4, 61, 53, 43, 52, 46, 'caffe_uniform', 3, 0.09999999999999999], [8, 4, 3, 4, 3, 2, 63, 57, 44, 55, 48, 'he_uniform', 1, 0.09999999999999999], [8, 2, 3, 4, 2, 3, 36, 30, 30, 63, 32, 'he_normal', 2, 0.09999999999999999], [8, 2, 3, 4, 2, 2, 60, 39, 41, 65, 33, 'xavier_uniform', 4, 0.0002012076028834959], [11, 3, 3, 4, 3, 4, 35, 63, 63, 62, 64, 'xavier_uniform', 1, 0.00866714545089891], [8, 2, 3, 3, 4, 4, 55, 56, 63, 60, 34, 'he_normal', 2, 0.00010933878687689759], [8, 2, 4, 3, 4, 4, 48, 40, 52, 60, 32, 'he_normal', 2, 0.09999999999999999], [8, 4, 4, 3, 3, 4, 60, 54, 65, 41, 32, 'he_normal', 3, 1.0054555508216113e-05], [8, 3, 3, 3, 3, 2, 31, 57, 60, 51, 30, 'he_normal', 1, 0.0026168135968490723], [8, 4, 4, 4, 3, 3, 37, 64, 62, 33, 52, 'he_normal', 0, 0.01685645874697779], [11, 4, 3, 3, 3, 4, 61, 47, 54, 55, 47, 'he_normal', 1, 0.0003765011074475807], [10, 2, 3, 3, 3, 3, 63, 52, 56, 58, 34, 'caffe_uniform', 3, 0.09999999999999999], [8, 2, 2, 4, 2, 2, 30, 30, 30, 65, 30, 'he_normal', 2, 0.09999999999999999], [8, 2, 2, 3, 2, 3, 30, 30, 30, 53, 32, 'he_normal', 0, 0.09999999999999999], [8, 4, 3, 3, 4, 3, 48, 63, 47, 34, 61, 'caffe_uniform', 0, 0.0006988342189973038], [8, 2, 2, 4, 2, 3, 48, 50, 38, 60, 44, 'he_normal', 3, 0.0010630558921353032], [8, 4, 3, 3, 3, 3, 55, 63, 37, 31, 51, 'xavier_uniform', 0, 0.040182145025863716], [8, 4, 3, 2, 4, 3, 52, 36, 65, 36, 54, 'caffe_uniform', 2, 1.799227078888316e-05], [8, 2, 2, 3, 3, 3, 30, 42, 46, 53, 53, 'he_normal', 3, 0.0017274481636200155], [8, 4, 2, 2, 4, 3, 39, 42, 58, 58, 34, 'caffe_uniform', 0, 0.02538727255814498], [8, 3, 2, 3, 2, 3, 34, 64, 54, 32, 44, 'caffe_uniform', 0, 0.05841467788043324], [8, 3, 2, 2, 4, 3, 30, 40, 36, 40, 35, 'caffe_uniform', 0, 2.6425141972924894e-05], [8, 4, 2, 3, 4, 3, 53, 50, 65, 54, 65, 'xavier_uniform', 2, 0.00035018555480494817], [8, 4, 2, 2, 4, 3, 60, 61, 64, 38, 56, 'xavier_uniform', 4, 0.00030709124496748716], [8, 2, 2, 3, 2, 3, 30, 53, 53, 56, 64, 'he_normal', 3, 0.056749864882203925], [8, 2, 2, 4, 2, 3, 30, 65, 59, 30, 65, 'xavier_uniform', 0, 0.09999999999999999], [9, 2, 2, 4, 3, 3, 57, 60, 56, 50, 63, 'xavier_uniform', 1, 2.1659583232534686e-05], [13, 2, 2, 4, 2, 3, 30, 65, 65, 30, 62, 'he_normal', 0, 0.007582478981301236], [8, 2, 2, 4, 2, 3, 30, 65, 65, 30, 65, 'he_normal', 0, 0.09999999999999999], [9, 3, 2, 4, 2, 3, 45, 65, 65, 30, 30, 'he_normal', 2, 0.09999999999999999], [8, 2, 2, 4, 2, 3, 41, 65, 30, 30, 65, 'he_normal', 2, 0.011195733193718348], [8, 2, 2, 4, 2, 3, 65, 65, 43, 30, 37, 'he_normal', 2, 0.015092488426198855], [8, 4, 2, 3, 2, 3, 63, 65, 47, 34, 43, 'he_normal', 2, 1e-05], [8, 4, 2, 2, 3, 3, 57, 55, 65, 42, 65, 'he_normal', 2, 1e-05], [8, 2, 3, 3, 4, 3, 34, 62, 47, 38, 64, 'he_normal', 0, 1.0017455593748346e-05], [10, 3, 2, 4, 2, 3, 54, 65, 39, 46, 50, 'he_normal', 0, 0.0010848883882730042], [13, 2, 3, 2, 2, 3, 57, 65, 36, 56, 55, 'he_normal', 0, 1e-05], [12, 3, 2, 2, 2, 3, 65, 53, 65, 35, 30, 'he_normal', 0, 1e-05], [13, 4, 3, 2, 4, 3, 47, 43, 53, 37, 61, 'he_normal', 4, 2.3448490928467227e-05], [8, 4, 3, 2, 2, 3, 43, 42, 31, 51, 48, 'caffe_uniform', 0, 8.923072180908639e-05], [13, 2, 2, 2, 3, 3, 36, 65, 30, 33, 64, 'he_normal', 0, 2.5008788649091418e-05], [13, 2, 3, 4, 2, 3, 55, 34, 41, 41, 33, 'he_normal', 0, 6.300417507628337e-05], [13, 3, 3, 4, 2, 3, 46, 49, 36, 36, 59, 'he_normal', 0, 1.4168106849205638e-05], [13, 3, 3, 4, 2, 3, 44, 57, 51, 57, 44, 'he_normal', 0, 0.047648161089890124], [10, 3, 3, 4, 2, 3, 53, 58, 48, 63, 52, 'he_normal', 0, 0.0006616156670531221], [11, 3, 3, 2, 2, 3, 49, 56, 61, 50, 35, 'he_normal', 0, 0.003874206631357768], [11, 4, 3, 2, 4, 3, 30, 35, 49, 30, 48, 'he_normal', 0, 0.09999999999999999], [13, 2, 3, 2, 4, 3, 45, 65, 30, 40, 39, 'caffe_uniform', 0, 1.3124990909659663e-05], [11, 4, 3, 2, 2, 3, 59, 60, 36, 51, 65, 'xavier_uniform', 0, 0.016798014117541147], [13, 4, 3, 2, 2, 3, 59, 51, 37, 48, 65, 'xavier_uniform', 0, 0.00010245200147978441], [13, 4, 4, 2, 2, 3, 56, 65, 30, 30, 65, 'he_normal', 0, 1e-05], [8, 4, 4, 2, 2, 3, 32, 58, 60, 39, 51, 'he_normal', 0, 1.138181205622081e-05], [8, 4, 2, 2, 2, 3, 41, 54, 30, 30, 65, 'he_normal', 0, 1e-05], [8, 4, 2, 2, 2, 3, 32, 55, 30, 30, 65, 'he_normal', 0, 1e-05], [13, 3, 3, 2, 2, 3, 38, 48, 56, 36, 65, 'caffe_uniform', 2, 7.267730586124988e-05], [13, 3, 3, 2, 2, 3, 55, 58, 42, 34, 65, 'he_normal', 2, 1.960429089732139e-05], [8, 4, 4, 3, 2, 3, 46, 61, 48, 36, 38, 'he_normal', 2, 0.03533183513155234], [8, 4, 4, 3, 2, 3, 45, 40, 64, 60, 41, 'he_normal', 1, 0.0017356418135645042], [8, 3, 4, 3, 2, 3, 58, 43, 47, 38, 40, 'he_normal', 0, 0.0009185683862714557], [8, 3, 4, 3, 2, 3, 62, 51, 57, 40, 42, 'he_normal', 0, 0.0003828493855941364]]
y0 = [0.5, 0.37312627079078414, 0.5, 0.5, 0.40127449514370905, 0.5, 0.5, 0.5, 0.3953523854056861, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.33482347489277114, 0.5194659099702321, 0.1966741884180666, 0.42179660969198135, 0.5488758740195663, 0.5, 0.5, 0.5, 0.4357786121775885, 0.32259930095007106, 0.5, 0.5, 0.5, 0.31408737435719747, 0.3165046787537358, 0.5782271547251162, 0.5, 0.5, 0.5000287786347415, 0.5, 0.5, 0.5, 0.5033644497408181, 0.5, 0.5, 0.5, 0.4474929984736806, 0.45493217463262253, 0.5, 0.5, 0.5785984352326466, 0.31545481099947675, 0.5, 0.5, 0.5561970460903911, 0.3749490185795035, 0.439759109548035, 0.5, 0.6167678019492814, 0.28535717674560535, 0.5, 0.5, 0.5, 0.5, 0.5611044938310887, 0.5258427040774896, 0.5, 0.5, 0.24205781919861497, 0.5, 0.5000913182518414, 0.5, 0.38260363612366477, 0.700793203550933, 0.507285148316521, 0.4964040570034959, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]

sampler = SkoptSampler(
    skopt_kwargs={'n_random_starts':10,
                  'acq_func':'EI',
                  'acq_func_kwargs': {'xi':0.02, 
                                      "x0" : x0, 
                                      "y0" : y0}})
                                      
if __name__ == '__main__':
    logging.getLogger().info("Start optimization.")
    study = optuna.create_study(direction='maximize',
                               sampler = sampler)
    study.optimize(objective, 
                   n_trials=100,
                   n_jobs = 30
                  )
    print('Number of finished trials: ', len(study.trials))

    print('Best trial:')
    trial = study.best_trial

    print('  Value: ', trial.value)

    print('  Params: ')
    for key, value in trial.params.items():
        print('    {}: {}'.format(key, value))
        
study.trials_dataframe().sort_values(["value"],ascending = False)

x0 = []
y0 = []
for i in range(len(study.get_trials())) :
    check = study.get_trials()[i].value
    if check is None :
        continue
    x0.append(list(study.get_trials()[i].params.values()))
    y0.append(study.get_trials()[i].value)

 


Reference

http://research.sualab.com/review/2018/09/28/nasnet-review.html

 

AutoML을 이용한 Architecture Search 소개 및 NASNet 논문 리뷰

안녕하세요, 오늘은 최근 주목받고 있는 AutoML 관련 논문을 리뷰하려고 합니다. 논문 제목은 “Learning Transferable Architectures for Scalable Image Recognition” 이며 올해, 2018년 CVPR에 발표된 논문입니다. 이 논문을 소개하기에 앞서 AutoML에 대해 간략하게 설명을 드리고 그 중 오늘 소개드릴 논문을 집중적으로 설명 드리고, 그 후속 연구들에 대해 간단하게 설명 드리겠습니다. 이전 포스

research.sualab.com

https://optuna.readthedocs.io/en/stable/

 

Welcome to Optuna’s documentation! — Optuna 1.0.0 documentation

© Copyright 2018, Optuna Contributors. Revision 08db2651.

optuna.readthedocs.io

https://towardsdatascience.com/optuna-vs-hyperopt-which-hyperparameter-optimization-library-should-you-choose-ed8564618151

 

Optuna vs Hyperopt

Which hyperparameter optimization library should you choose?

towardsdatascience.com

http://research.sualab.com/introduction/practice/2019/02/19/bayesian-optimization-overview-1.html

 

Bayesian Optimization 개요: 딥러닝 모델의 효과적인 hyperparameter 탐색 방법론 (1)

지난 글의 서두에서 ‘AutoML’이라는 주제에 대해 간단히 소개해 드린 적이 있습니다. AutoML을 한 문장으로 표현하자면 ‘Machine Learning으로 설계하는 Machine Learning’이라고 하였으며, 현재 3가지 방향으로 연구가 진행된다고 하였습니다.

research.sualab.com

 

728x90