"How to Train a GAN" at NIPS2016 workshopのメモ

NIPS2016でのWorkshop on Adversarial Training「How to train a GAN」での,
GANを学習させるTipsのまとめ。

Workshopの動画 (30分程度で軽めなので観てみると良いと思います) www.youtube.com

以下は登壇者による↓のメモ
https://github.com/soumith/ganhacks

前置き

GANは現状House of cardsのようなもの.

  • Generator,Discriminatorが上手く学習しているのかわからない
  • 上手く言ってると思ったら突然崩壊する
  • モデルの評価が難しい

まだまだ発展途上で,今後新たなアルゴリズムや理論が登場する見込み.
だが現状,以下のようなテクニックは重要と思われる.
(以下のテクニックはZero scienceで単なるHackだと述べている)

1. 入力を正規化する

  • Discriminatorへ入力する訓練データ画像を-1から1の範囲に正規化する
  • Generatorの出力が-1から1の範囲となるよう,Generatorの出力層でtanhを使う

2. 誤差関数を修正する

JS divergenceから誤差関数を導くと,Generatorの学習の際には、{min (log 1-D)}を目的関数とすることとなるが、 実用的には {max log D}を使ったほうがよい。

  • 前者は勾配消失しやすい
  • Goodfellow et. al,(2014)参照

3. 球形のZを使う

Generatorに入力するノイズを一様分布からサンプリングするのではなく、
f:id:yusuke_ujitoko:20170528190404p:plain

ガウス分布からサンプリングする方がよい。
f:id:yusuke_ujitoko:20170528191319p:plain

  • ガウス分布上の点同士の内分点をもとに画像生成する場合には、 単純に点と点を結ぶ線分上の内分点を使うのではなく、 大きな球上の点同士とみて内分点を決定するとよい。 (DCGAN paperでこのミスがあったらしい)
  • 詳しくはTom Whiteの Sampling Generative Networksコード参照

4. BatchNormalization

  • 訓練データと生成データでそれぞれミニバッチ群をつくる。
    (一つのミニバッチに訓練データと生成データが混ざらないようにする)

  • BatchNormalizationを使わないときには、個々のデータに対して正規化処理を行う

f:id:yusuke_ujitoko:20170528191855p:plain

5. スパースな勾配にならないようにする(ReLUやMaxPoolを避ける)

  • スパースな勾配を使うと、GANのmini max gameが不安定になる
  • GeneratorとDiscriminatorの両方でLeakyReLUは有効
  • Downsamplingには、Average PoolingやConv2d+strideを使う
  • Upsamplingには、 PixelShuffleやConvTranspose2d + strideを使う

6. SoftでNoisyなラベルを使う

  • Labelをsoftにする
    訓練データ=1、生成データ=0というラベルであれば、例えば以下のようにする
    • 訓練データのラベルを0.7〜1.2の間のランダム値にする
    • 生成データのラベルを0.0〜0.3の間のランダム値にする
    • Salimans et. al. 2016 参照
  • Discriminatorのラベルをnoisyにする
    • Discriminator学習時に時々ラベルを反転させるなど

7. DCGAN/Hybrid Modelを使う

  • 使えるならDCGANを使う
  • DCGANを使えず、他のモデルでも安定しないときには、hybrid modelを使う
    • KL + GAN
    • VAE + GAN

8. 強化学習の安定学習のためのトリックを取り入れる

  • 強化学習でも学習が不安定になる深刻な問題がある

    • David house?のpaperを読むべき
  • Experience Replayを使う

    • 過去の生成画像をバッファしておき、ときどきそれらを用いる
    • 過去のGeneratorとDiscriminatorを覚えておき、ときどき現世代のGeneratorとDiscriminatorと入れ替える
  • Deep Deterministic Policy Gradientsに対して成功した安定学習のためのトリックを使う
  • Pfau & Vinyals (2016)を参照

9. Adam Optimizerを使う

  • Adamを使う(Radford et. al., 2015参照)
    • 良い結果が出てるlearning rateはだいたい同じ
  • もしくはDiscriminatorに対してはSGDを使い、Generatorに対してはAdamを用いるとよい。

10. 失敗を早めに発見する

  • Discriminatorの誤差が0になったら失敗
  • 勾配の大きさをチェックする。100を超えていれば失敗
  • うまく行っているときには、Discriminatorの誤差の分散は小さく、徐々に小さくなっていく。 一方、分散が大きくスパイクがあるときは失敗
  • Generatorの誤差が安定的に小さくなっているときには、ゴミのような無関係な画像でDiscriminatorを騙している可能性がある。

11. 理論なしで,GeneratorとDiscriminatorのlossがバランスするように制御しない

  • Generatorの学習回数とDiscriminatorの学習会数の比をスケジューリングするのは難しい。
  • もし試みるのであれば、直観的に行うのではなく、理論に基づいて行うほうがよい。

12. ラベルが手元にあるなら使う

  • 何らかの意味を持つラベルが手元にあれば、Discriminatorがサンプルを分類するよう学習させるとよい
    • Auxillary GANs

13. ノイズを入力に混ぜる

14. Discriminatorを多く学習する

  • noiseがあるときには特にDiscriminatorを多く学習する
  • (実際には)GとDの学習回数比を見つけるのは難しい

15. Batch Discrimination

  • 1つのデータを分類するのではなく,バッチごとに分類する手法
  • うまくいく場合とうまくいかない場合がある

16. Conditional GANsの離散変数を使う

  • Embedding layerを使う
  • 画像に追加のチャネルとして付与する
  • embedding dimensionalityを低く保ち、画像チャネルサイズにupsamplingする

17. Generatorの学習時とテスト時両方でDropoutを使う

質疑

登壇者によるhackは有意義だが,これらhackを越えたtheoretical prospectを得るにはどうすればいいの?

hackを越えたところに到達するには, GANがどのように学習するかにfocusする必要がある. そのためには個々のデータに着目するのではなく, lossとデータの関連を見つけるのが重要