MOB-LOG

モブおじの記録 (Programming, 統計・機械学習)

(やらかし)Optunaで多変量最適化をしてたと思ったらTellのときtrialの目的値をミスってて試行回数n=0のまま最適化してた(valueではなくvalues)

TL; DR

OptunaのAsk-and-Tellでデータセットから複数の目的値を設定して Multivariate Optimization していたと思ったら、TellするときのTrialの目的値をvaluesでなくvalueに入れていたので、全く学習(Tell)できていなかった。

複数目的値を設定した時は、 optuna.trial.create_trialvalueではなくvaluesに設定すること。

いきさつ

コーヒーのハンドドリップパラメータ最適化で、前まではレシピの評価は総合評価のScore 単一で最適化していた(Scoreを最大化)。

23試行くらい運用した結果、Scoreだけだとレシピの良さ・悪さを表現しきれなくて微妙だったので、コーヒーを以下の6つの評価軸で評価し、Ask-and-TellのTellで今までの評価とレシピを学習するようにした(以下のコード)。

  • 総合評価: Score
  • うま味: Umami
  • 苦味: Bitter
  • 酸味: Acidity
  • 香り: Flavor
  • えぐみ: Astringency

はずだった。

if not np.all(is_record_null[target_score]):
  try:
    value = record[target_score]
    value = value.tolist() if isinstance(value, pd.Series) else value
    trial = optuna.trial.create_trial(
      params=params,
      distributions=trial_search_space,
      value=value,
      )
    study.add_trial(trial)
  except ValueError as e:
    logging.info("pass trial:{}".format(trial))
    logging.info(e)

実際には study.add_trial(trial) でエラーが出てて、trialが学習できてなかった。

ValueError: The added trial has 1 values, which is different from the number of objectives 6 in the study (determined by Study.directions).

try-catchでシステムは止まらなかったのと詳細はログファイルに吐き出され続けていたので長いこと気づかなかったが、それまで10試行ほど、学習試行回数0のまま回していて、ランダムなコーヒーのレシピが出力されていたということになる(無駄すぎる)。

学び(戒め)

OptunaのAsk-and-Tellで、StudyとTrial中の単一の目的値の扱いは value だが、複数の場合は values に設定しないといけない。

特に単一の目的値を基に最適化のTrialを回していて、後々複数の目的値へ仕様を変更した時はvalueのままにしている可能性が高く、良ければエラーになるし、最悪不適切にcatchとかしていたらワンチャン学習回数0回のままなのでしっかり確認しよう(仕様変更したらちゃんとテストしよう)。