- Tensor2Tensor: TensorFlowのいろんなモデル(resnetとかseq2seqとか、transformerとか)が実装された便利ライブラリ
- Optuna: ハイパーパラメータ最適化フレームワーク。grid searchよりも良い探索
誰でも最新Deepモデル x 誰でもハイパーパラメータ探索
これらが合わさると最強な気がしませんか?合わせてみました。
TensorFlowよく知らなかったので、TensorFlowでOptunaを既に動かしている方の実装をかなり参考にしました。
使い方
tensor2tensor自体の使い方とかは例えば以下のブログが参考になります:
独自データを定義したpythonファイルに、range objectを例えば以下のように定義します。
@registry.register_ranged_hparams
def myhparamsrange(rhp):
rhp.set_float("learning_rate", 0.01, 0.2, scale=rhp.LOG_SCALE)
rhp.set_discrete("filter_size", [1024, 2048])
rhp.set_int("num_hidden_layers", 3, 5)
rhp.set_discrete("hidden_size", [128, 256, 512])
rhp.set_float("attention_dropout", 0.4, 0.7)
rhp.set_float("relu_dropout", 0.4, 0.7)
そしたらtrain時にこれを optuna_params_range として指定します。
t2t-trainer \
--data_dir=data \
--problem= \
--model=transformer \
--hparams_set=myhparams \
--optuna_params_range=myhparamsrange \
--optuna_objective=metrics-/targets/accuracy \
--optuna_n_trials=10 \
--optuna_is_higher_better \
--output_dir= \
--t2t_usr_dir= \
--train_steps=10000
パラメータの説明は以下の感じ:
パラメータ | 説明 | 例 |
optuna_objective | 最小(大)化したいメトリック | metrics-<problem_name>/targets/accuracy |
optuna_n_trials | 試行の回数(試行ごとにハイパーパラメータが変わる) | 10 |
optuna_n_startup_trials | ここで指定した回数の試行が終わるまでは枝刈りをしない | 3 |
optuna_n_warmup_steps | 枝刈りの判断を開始するステップ数 | 100 |
optuna_params_range | 定義したrange object | myhparamsrange |
optuna_is_higher_better | Optunaはobjectiveを最小化しようとするので、最大化したい場合にはこのオプションをつける | – |
実行すると、こんな感じで枝刈りをやってくれます。
途中で終わっている試行があるのがわかりますか?あるんです。
なお、Optunaのstudy.optimize()はt2t_trainerの内部で呼ばれているので、Optunaを使わないことはできません。
パラメータがもう決まった場合など、Optunaによる最適化が必要ない場合には、optuna_n_trialsを1にして、optuna_params_range オプションを付けないでt2t-trainerを実行してください。
余談1
実はtensor2tensorによるハイパーパラメータチューニングは既に可能でした。ML Engineならね。
金がいくらあっても足りゃあしないので、Optunaを使えるようにしてみたというわけです。パラメータの範囲を読み込むrange objectは、ML engineでの利用のために実装されているrange objectを利用したのでした。
余談2
実装の話。
- Optunaは、study.optimize()内でObjectiveオブジェクトを繰り返しcallする。Objective.__call__()内では、パラメータの更新、trainの実行などが行われる。
- t2tは、tensor2tensor/bin/t2t_trainer.main()からtensor2tensor/utils/trainer_li.create_experiment_fn()を呼び出してネットワークを定義して、実行する。
つまり、
- t2t_trainer.main()-study.optimize()
- Objective.__call__()-create_experiment_fn()
という対応づけが可能だったので、すんなり実装ができました。コードを読んでいくと、tensor2tensorはgoogleで練られてきた?きれいなディレクトリ構造になっており、たくさんのコントリビュータが並列で実装を進めるような感じ、Optunaは問題の構造自体がまず理論化されている & 実装が素直でわかりやすい & ドキュメントもきれい という感じでした。Optunaすごいと思いました。
ChainerもそうなんですけどPFNの理論化力 & Python力はすげえなと思いました。
コメント