初心者向けにTensorFlowのseq2seqでどのパラメータを使えば良いか適当に解説する

## はじめに
電車が運転見合わせになって時間ができた（？）ので、暇つぶしがてら初心者向けにTensorFlowのNMT (ニューラル機械翻訳）サンプルで指定できるパラメータについてざっくり解説しようと思う。使う人が増えて「俺が考えた最強のネットワーク」が増えるといいなと思う。[TensorFlow公式のNMTのサンプル](https://github.com/tensorflow/nmt)は良く出来てて、seq2seqをとりあえず使ってみるなら適当な入力データを用意すれば使えてしまう。ちなみに、、、筆者は機械学習バリバリだが深層学習バリバリって訳ではないので、情報が間違っていたら深層学習強者の皆様からあたたかいコメントをいただければ幸甚です。あと、筆者はTensorFlowのNMTの`README`と`nmt.py`のソースコードを読んだだけで、サンプルは動かしてもいない（爆）。

なお、TensorFlowはv2.0が控えているので、本記事の寿命は1ヶ月もたないかもしれない（2018年9月26日著）。

## 初心者向けのパラメータ
seq2seqのソースコードは[こちら](https://github.com/tensorflow/nmt)。初心者向けに抜粋して解説。

### Data
機械学習の学習データに関するパラメータ。

#### src
ニューラル機械翻訳でいう翻訳元のデータのsuffixを指定するパラメータ。例えば`--src=vi`とした場合、`train.vi`というファイルが学習データに使われる。

#### tgt
ニューラル機械翻訳でいう翻訳先のデータのsuffixを指定するパラメータ。例えば`--tgt=en`とした場合、`train.en`というファイルが学習データに使われる。

#### train_prefix
学習データのファイルのprefixを指定するパラメータ。例えば`--train_prefix=/tmp/nmt_data/train`とした場合、`/tmp/nmt_data/train.vi`が学習データに使われる。

#### dev_prefix
評価データ（その１）のprefixを指定するパラメータ。使い勝手は`train_prefix`と同じ。このデータは学習の進捗を評価するために使われる（と思う）。

#### test_prefix
評価データ（その２）のprefixを指定するパラメータ。使い勝手は`train_prefix`と同じ。このデータは最終的なモデルの性能を評価するために使われる（と思う）。`dev_prefix`と`test_prefix`を同じものにすると、とても不幸になる。

#### out_dir
ログや学習モデルの出力先。

### Network
ネットワークのデザイン。自分でオリジナルネットワークを作り出せば、一流の機械学習エンジニアの仲間入り（ただし数学に基づき、かつトップカンファレンスに論文を通した場合に限る）。

#### num_units
ネットワークサイズ。これが大きいほどニューラルネットの表現力が上がるので、複雑な問題を解ける可能性がある。が、初心者は初期値を使っておけば良いと思う。大きくするほど計算が増えるので学習が終わらなくなる。初心者が設定するなら初期値の`32`から高々`200`かなと思う。

#### num_layers
ニューラルネットのレイヤーの数。これが大きいほどニューラルネットの表現力が上がるので、複雑な問題を解ける可能性がある。当然、大きくするほど計算時間が爆増するし、勾配消失なども起こりうる。初心者は初期値の`2`を使えば良い、なんなら`1`でも良い。なお、よほど時間があって試行錯誤をしたい人は`num_encoder_layers`と`num_decoder_layers`を色々と変えてみても良いと思う（が、encoderとdecoderの数を変えることは学術的に意味を説明できそうにないので、あくまで試行錯誤向け）。

### その他の学習系パラメータ
ほんとは細かい設定ができるけど初心者は一部だけイジれば良いと思うので、そういうものをまとめた。

#### attention
アテンション。あの有名なアテンション。初期値は`なし`。アテンションを使うと性能が改善することが知られている。結構重い処理なので、計算資源と時間に余裕があれば使う。`luong`がシンプルで良いと思う。

#### optimizer
オプティマイザ。初期値は`sgd`。`sgd`と`adam`で学習の進め方は大いに違うが、どちらが良いとはひとえに言えない。`adam`の方が若干早く学習が終わり、安定したパフォーマンスが出るイメージ。`sgd`はめっちゃ細かくチューニングすれば`adam`以上のパフォーマンスが出るイメージ。故に初心者は`adam`の方が良い（かも）。

#### learning_rate
学習率。神のみぞ知るパラメータ。学習率を大きくすれば早く学習が収束するが、パフォーマンスはイマイチなことが多い（local minimum）。初心者は初期値を使っておくのが無難。なお、`decay_scheme`とあわせて使えるようになると、機械学習エンジニアとして次のステップにいける（かもしれない）。

#### unit_type
ネットワーク構造のパラメータ。初期値は`lstm`。とりあえず`lstm`使っておけば良い。Layer normalizationのタイプもあるので、時間があれば試しても良いと思う。

#### dropout
ドロップアウト。特定のニューロンだけが頑張る状況（過学習やlocal minimum）を回避するため、学習時にランダムで一定のニューロンをマスクして残りのニューロンに学習をふる方法。初期値は`0.2`で20%をマスクするという意味。個人的にはdropoutの価値は疑問視してて、さらにbatch normalizationやlayer normalizationと組み合わせることはナンセンスだと思ってる（※個人の意見です）。

#### batch_size
バッチサイズ。初期値は`128`。128個の学習データごとに内部パラメータを更新する。（近年の計算機の最適化により）大きくすれば学習は早く終わるが、細かい調整がきかなくなる(local minimumに落ちる)イメージ。個人的には最初の学習モデルはバッチサイズ大きめ、その後にオンラインラーニングで学習モデルを更新するときはバッチサイズ小さめ、にすると良い感じになる気がする（がこれは初心者向けではないかも）。個人的には、バッチサイズと学習率は反比例するように調整（e.g. バッチサイズを大きくして、学習率を下げる）するのが良い感じ。

#### num_train_steps
学習ステップ。バッチ１回を１ステップとする。`epoch`はTensorFlowのseq2seqでは`[epoch]=([num train steps] x [batch size])/[num data]`となる（よね？）。`epoch`の代わりに`num_train_steps`を設定するのは、昔Deepをやってた私からするとちょっと分かりづらかった。

#### steps_per_stats
途中経過を表示するステップの間隔。初期値は`100`なので`100`ステップごとに経過を表示する。

#### metrics
評価指標。初期値は`bleu`。`bleu`や`rouge`は評価指標として不十分だとよく言われているが、他に良い方法もないのでどちらかを選ぶこと。

#### num_gpus
GPUを使うなら指定する。workerに対するGPUの数。初心者向けではない（そもそもGPU使えるようにするためにはいくつもの儀式が必要）。

## おわりに
初心者向けに超適当にパラメータを解説した。公式ではもっと多くのパラメータがあり、色々と試行錯誤できるようになっている。また中上級者は公式サンプルをfolkしてオリジナルのネットワークを作ることもできる。実際、実課題に機械学習を適用しようとすると数学の知識やデータに対する知識が必要不可欠だが、そんなもんなくても適当にやって成果出して世界が良くなるなら良いんじゃない？ってことで、誰かの参考になれば幸いです。

## 筆者
服部圭悟（[keigohtr](https://twitter.com/keigohtr?lang=ja)）
趣味でアルゴリズムのマーケットプレイス[Apitore](https://apitore.com)を提供している。自然言語処理系のWebAPIを無料で提供しているので、ハッカソンとかで使ってくれると嬉しい。