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の学習の際には、を目的関数とすることとなるが、 実用的には を使ったほうがよい。
- 前者は勾配消失しやすい
- Goodfellow et. al,(2014)参照
3. 球形のZを使う
Generatorに入力するノイズを一様分布からサンプリングするのではなく、
ガウス分布からサンプリングする方がよい。
- ガウス分布上の点同士の内分点をもとに画像生成する場合には、 単純に点と点を結ぶ線分上の内分点を使うのではなく、 大きな球上の点同士とみて内分点を決定するとよい。 (DCGAN paperでこのミスがあったらしい)
- 詳しくはTom Whiteの Sampling Generative Networksの コード参照
4. BatchNormalization
訓練データと生成データでそれぞれミニバッチ群をつくる。
(一つのミニバッチに訓練データと生成データが混ざらないようにする)BatchNormalizationを使わないときには、個々のデータに対して正規化処理を行う
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. ノイズを入力に混ぜる
- 人工的なノイズをDiscriminatorの入力に混ぜる(Arjovsky et al., Huszar, 2016)
- ガウスノイズをGeneratorの各層に混ぜる(Zhao et. al, EBGAN)
- Improved GANs
- OpenAI code
14. Discriminatorを多く学習する
- noiseがあるときには特にDiscriminatorを多く学習する
- (実際には)GとDの学習回数比を見つけるのは難しい
15. Batch Discrimination
- 1つのデータを分類するのではなく,バッチごとに分類する手法
- うまくいく場合とうまくいかない場合がある
16. Conditional GANsの離散変数を使う
- Embedding layerを使う
- 画像に追加のチャネルとして付与する
- embedding dimensionalityを低く保ち、画像チャネルサイズにupsamplingする
17. Generatorの学習時とテスト時両方でDropoutを使う
- dropoutの形でノイズ(50%)を挿入する
- Generatorの学習時とテスト時両方で幾つかの層に適用する
- https://arxiv.org/pdf/1611.07004v1.pdf
質疑
登壇者によるhackは有意義だが,これらhackを越えたtheoretical prospectを得るにはどうすればいいの?
hackを越えたところに到達するには, GANがどのように学習するかにfocusする必要がある. そのためには個々のデータに着目するのではなく, lossとデータの関連を見つけるのが重要