GAN(Generative Adversarial Networks)を学習させる際の14のテクニック

※この記事は<b>"How to Train a GAN?" at NIPS2016</b>を、<a href="https://github.com/soumith/ganhacks">ここ</a>を参考にして、私なりに解釈して、重要そうな部分を引用して翻訳したものです。役に立つことが多かったので共有致します。
※GANの説明は省略します。G=Generator、D=Discriminatorとして説明します。
※それぞれのテクニックに根拠はあまり書いてないですが、ほとんどが論文に書いてあった「こうすればうまくいった」というものです。GANの学習がうまくいかないときに試してみると良いと思います。

<ol>
  <h2>1. 入力を正規化 (Normalize the inputs)</h2>
・DのInput(=Gの出力)となる画像を[-1,1]の範囲に正規化する。<br>
・Gの出力が[-1,1]となるように、OutputのところをTanhにする。<br>
  <h2>2. GのLoss関数を修正する (A modified loss function)</h2>
・Gの最適化では、min(log 1-D)がLossとなるが、実際にはmax(logD)をLossにした方が良い。
→ 前者のLossでは勾配消失が生じやすい。Goodfellow et. al (2014)
  <h2>3. Zはガウス分布から (Use a spherical Z)</h2>
・GのInputとなるベクトルZは、一様分布ではなく、正規分布からサンプルする<br>
・Interpolationする時は、点AからBの直線上の点ではなく、大きな円(Great Circle)上の点を用いて行う<br>
<img src="https://qiita-image-store.s3.amazonaws.com/0/170131/c56eddc9-5bf0-c63c-cacb-abab070fa8e5.png"><br>
・<a href="https://github.com/dribnet/plat">こちらのコード</a>が参考になる
<h2>4. BatchNormalization (Batch Norm)</h2>
・Real画像とFake画像（=Generated）で、別々のミニバッチを作る。＝　一つのミニバッチに、RealとFakeが混ざらないようにする。<br>
<img width="662" alt="batchmix.png" src="https://qiita-image-store.s3.amazonaws.com/0/170131/2058ac01-4744-8c3d-672d-442a7f400010.png">
<br>
・Batchnormを使わないときは、Instance Normalizationを使う。(全てのサンプルから、平均を引いて、標準偏差で割る)
<h2>5. ReLUやMaｘPoolingのように、勾配がスパースになるものは避ける(Avoid Sparse Gradients: ReLU, MaxPool)</h2>
・スパースな勾配があると、GANの学習が安定しにくくなる。<br>
・GとDの両方において、LeakyReLUが有効。<br>
・ダウンサンプリングするときは、Average PoolingやStrideありのConv2dを使う。<br>
・アップサンプリングするときは、<a href="https://arxiv.org/abs/1609.05158">PixelShuffle</a>やStrideありのConvTranspose2dを使う。
<h2>6. DのOutputの正解ラベル(Real/Fake)には、ノイジーなラベルを使う (Use Soft and Noisy Labels)</h2>
・普通はReal=1、Fake=0とするが、Real=0.7~1.2、Fake=0.0〜0.3からランダムにサンプルする。(Label Smoothing) Salimans et. al. 2016<br>
・学習の際、たまにRealとFakeのラベルを入れかえる<br>
<h2>7. DCGANやハイブリッドモデル(DCGAN / Hybrid Models)</h2>
・DCGANが使える状況であれば使う。<br>
・DCGANが使えないのであれば、VAE+GANやKL+GANのような、ハイブリッドモデルを使う。
<h2>8. 強化学習における安定性のテクニックを使う (Use stability tricks from RL)</h2>
・過去のFake画像を保存しておいて、それを時々、DiscriminatorのInputとして用いたり、過去のGとDのモデルを保存しておき、数Iterationだけ、そのモデルを使って学習を行う。（Experience Replay)<br>
・Deep Deterministic Policy Gradientsにおけるテクニックを使う。(詳細省略します)<br>
・Pfau & Vinyals (2016)が参考になる。
<h2>9. 最適化手法はAdamを使う (Use the ADAM Optimizer)</h2>
・現状だとAdamを使うのが一番良い。Radford et. al. 2015<br>
・DiscriminatorにはSGD、GeneratorにはAdamを使うというのも良い。
<h2>10. 学習がうまく進んでいるのかを確認する (Track failures early)</h2>
・DのLossが0になっていたら、うまくいっていない。<br>
・勾配のノームが100を超えるくらい大きければ、うまくいっていない。<br>
・うまくいっているときは、DのLossが小さな分散で、IterationごとにLossが小さくなっていく。大きい分散だとあまりうまくいっていない。<br>
・GのLossが安定して小さくなっていっている場合、あまり意味のない画像を生成している可能性がある。
<h2>11. DとGの学習を統計的に制御しない (Dont balance loss via statistics (unless you have a good reason to))</h2>
・Gの学習回数:Dの学習回数 の比率を見つけるのは、これまでに多くの人がやってきたけど、難しい。<br>
・どうしても制御したいのであれば、例えば、「DのLossがAより大きければ、Dを学習」、「GのLossがBより大きければ、Gを学習」のように行う。
<h2>12. 画像データにラベルがついているのであれば、使う (If you have labels, use them)</h2>
・例えば、顔画像であれば、性別や年齢のように、追加的なラベルある場合、Auxillary GANのように、Discriminatorがラベルの分類も行うようにする。
<h2>13. InputやLayerにノイズを入れる (Add noise to inputs, decay over time)</h2>
・DのInputに、ノイズを入れる(ガウシアンノイズなど) 。 Arjovsky et. al., Huszar, 2016<br>
・Gの全てのLayerにガウシアンノイズを入れる。Zhao et. al. EBGAN<br>
・Iterationごとにノイズの大きさを減衰させる。
<h2>14. Gに学習、テストの両段階において、Dropoutを入れる。(Use Dropouts in G in both train and test phase)</h2>
・50%のDropoutを、Gの一部のレイヤーに適用する。<br>
・テストの段階でもDropoutを適用したままにする。<br>Phillip et. al. pix2pix

</ol> 
<br>
<br>
Thank you so much for authors of https://github.com/soumith/ganhacks