TL; DR
OptunaのAsk-and-Tellでデータセットから複数の目的値を設定して Multivariate Optimization していたと思ったら、TellするときのTrialの目的値をvalues
でなくvalue
に入れていたので、全く学習(Tell)できていなかった。
複数目的値を設定した時は、 optuna.trial.create_trial
のvalue
ではなく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回のままなのでしっかり確認しよう(仕様変更したらちゃんとテストしよう)。