LoginSignup
21
25

More than 3 years have passed since last update.

【Optuna】ハイパーパラメータの自動最適化ライブラリの使い方例

Last updated at Posted at 2021-02-24

Optuna概要

使い方

基本形

  • 公式チュートリアルから転載
import optuna

def objective(trial):
    x = trial.suggest_float("x", -10, 10)
    return (x - 2) ** 2

study = optuna.create_study()
study.optimize(objective, n_trials=100)

best_params = study.best_params
found_x = best_params["x"]
print("Found x: {}, (x - 2)^2: {}".format(found_x, (found_x - 2) ** 2))

hist_df = study.trials_dataframe(multi_index=True)
hist_df.to_csv("result.csv")
  1. objectiveを作成
    • objective内で、値を探索したいところに、trial.suggest_xxxと記述。
      • trial.suggest_xxxの種類はいろいろあり後述。
    • objectiveの返り値はスコアとし、optunaはデフォルトではこのスコアを最小する。
  2. optuna.create_studyでタスク(study)を作成。
    • 引数にはSamplerを与えることができる。デフォルトはTPESampler。
  3. study.optimizeでobjectiveを引数として、n_trialsで試行回数を設定すると最適化が始まる。
  4. 結果は、studyの中にbest_paramsとして入っている。
  5. study.trials_dataframeで各試行の結果をデータフレームで取得できる。
    • multi_indexはFalseでもよい。データフレームのカラムの見え方が変わるだけ。

trial.suggest_xxxの種類

名前 説明
suggest_categorical カテゴリ変数。アルゴリズム名やkernel名など各モデルで文字列で表現されるものはこれ。
suggest_int 整数パラメータ。log=trueで対数的に分布させられる。stepで刻み幅を指定できる
suggest_float 後ろ3つのラッパー。logやstepの設定によりそれぞれが呼ばれる。
suggest_uniform 連続一様分布。suggest_floatでlogやstepを指定しない場合。
suggest_loguniform 連続対数分布。suggest_floatでlog=trueとした場合。
suggest_discreteuniform 離散一様分布。suggest_floatでstepを指定した場合。

trial.suggest_xxxの使い方例

  • sklearn.svm.SVCの場合
def objective(trial):
  # ...(略)...

  params = {
    # 10のべき乗で表すことが多いので、対数一様分布
    "C": trial.suggest_loguniform("C", 0.0001, 1000.0),

    # kernelはカテゴリ変数
    "kernel": trial.suggest_categorical("kernel", ["linear", "poly", "rbf", "sigmoid"]),

    # 整数
    "degree": trial.suggest_int("degree", 1, 10), 

    # gammaはカテゴリと数字双方使える。その場合はとりあえず"numeric"を余分に準備して…
    "gamma": trial.suggest_categorical("gamma", ["scale", "auto", "numeric"]), 
  }

  # gammaが"numeric"の場合、ここで"gamma_val"という新しい名前でパラメータを振り、
  # params["gamma"]にはgamma_valにしておく。
  if params["gamma"] == "numeric":
      params["gamma"] = trial.suggest_loguniform("gamma_val", 0.1, 1.0)

  # モデル作成
  model = sklearn.svm.SVC(*params)

  # ...(略)...
  • カテゴリと数字が混在する、"gamma"の振り方はポイント。(振る意味があるかは置いておいて)
  • その他、機械学習のモデルによっては、あるモードでしか使えない引数などもこの方法で回避できる。

objectiveに引数を与えたい場合

import optuna

# Objective function that takes three arguments.
def objective(trial, min_x, max_x):
    x = trial.suggest_uniform("x", min_x, max_x)
    return (x - 2) ** 2


# Extra arguments.
min_x = -100
max_x = 100

# Execute an optimization by using the above objective function wrapped by `lambda`.
study = optuna.create_study()
study.optimize(lambda trial: objective(trial, min_x, max_x), n_trials=100)

objective内の途中計算結果も取得したい場合

  • set_users_attrsを使えば、データフレームに格納することが可能。
def objective(trial):
  # ...(略)...

  # user_attrsに設定
  trial.set_user_attr('hoge', hoge)
  trial.set_user_attr('hogehoge', hoge)

  # ...(略)...

study = optuna.create_study()
study.optimize(objective, n_trials=100)

best_params = study.best_params
found_x = best_params["x"]
print("Found x: {}, (x - 2)^2: {}".format(found_x, (found_x - 2) ** 2))

hist_df = study.trials_dataframe(multi_index=True) # user_attrsに設定したものもDFで取得できる。
hist_df.to_csv("result.csv")

Optunaのログをファイルに出力したい場合

  • optunaのロガーを"optuna"で取得できるので、そこにFileHandlerを設定すればよい。
import logging
optuna.logging.get_logger("optuna").addHandler(logging.FileHandler('./optuna.log'))

Optunaのロガーに任意の情報を出力したい場合

  • 前項と同様、objective内でロガーを取得すれば可能。
def objective(trial):
    # ロガー取得
    logger = optuna.logging.get_logger("optuna")

    # 出力される
    logger.info("test")

なんか再現性がない場合

  • n_jobsを1以外に設定すると、再現性がなくなるように見えている。
  • おなじn_jobs(例えば20)を設定していても実行する度に変わるため、再現性がとりたい場合は1にした方が良さそう。

多目的化最適化(Multi-objective)

その他の参考ページ

21
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
25