前回の記事では、Conditional VAEを実装しましたが、本記事ではそれと対を成す、Conditional GANをTensorflowで実装してみます。
#概要
Conditional GANに関する詳細な説明は、あらゆるところですでに行われていますので、ここでは割愛させていただきます。ただ個人的には、Discriminatorが比較的単純で学びやすいタスク(fake/real画像を識別する)に集中して高速に学習が進む一方で、Generatorがその傾き情報を使うことでやはりより高速な学習を行うという意味で、カリキュラムラーニングと蒸留のテクニックを合わせたような美しさを感じるところです。
通常のランダムに生成を行うようなモデルであるGANに対し、labelの情報を与えてやることで、labelに対応するカテゴリ内での出力を行うようにしたものが、Conditional GANということになります。
基本的に、Generator, Discriminatorの双方に、labelを入力してあげることだけが、通常のGANとの違いです。
- Discriminatorでは、カラー画像3channelに加えて、labelのone-hot vectorに対応するfeatureを追加してあげます。結果として、入力画像の時点でfeatureは、N+3となります
- Generatorでは、Noise input zにconcateneteする形で、labelのone-hot vectorを追加してあげます
学習の初期では、Generatorはlabel vectorを無視したような出力を出すこともできます。例えば、label=犬のときに、実際には猫の画像をGenerateすることが可能です。ただ、それがDiscriminatorに入ったときには、label=犬にも関わらず猫の画像が入ってきたということで、明らかに(本物の写真ではなく)生成された画像という判定ができてしまいます。そのようなわけで、間接的にではありますが、このlabelがDiscriminatorのfake/realの判定に使われることを通して、双方ともlabelに対応した画像を出力することを学びます。
#実装上の留意点
実装自体は、githubにアップロードしております:
https://github.com/ysasaki6023/conditionalGAN/tree/v1.0
以下に、いくつか実装上の留意点を示します。
##入力画像の規格化
対称にすべく、-0.5~+0.5の範囲内に規格化しました。
なので、画像の再構成時には、x*255+128を行う必要があります。
##Generator最終層をtanh(x)にて正規化
上記のために、Generatorの最終層にtanh(x)を掛けました。そうすると、普通は-1~+1までの出力になってしまいますが、学習の中でNNは-0.5~+0.5の範囲に収め、fake/realを同一のダイナミックレンジにしていくことを学んでいきます。
##学習係数・Adamのパラメータ・学習回数の設定
GANは非常に不安定なシステムです。実際、GCGANの論文は、安定に学習を進めるためのパラメータを見つけたということが一つの大きな貢献となっているそうです。ですので、パラメータもそれら準拠で設定します。
- learnRate = 2e-4
- Adamの$\beta_1$=0.5
学習の回数にも工夫があります。GANでは、GeneratorとDiscriminatorの学習を交互に行う必要があるのですが、下記実装では、経験則に基づき、Generatorの学習を2回、Discriminatorの学習を1回の頻度で行っています。そうでないと、学習の発散などが生じるようです。
#結果
MNISTの手書き文字を学習させました。0-9の数字をlabelとしています。
2000回 ✕ 64枚/バッチ = 3 epoch程度の学習です。大体15分程度だったと思います。
##labelを指定し、noize vector zは一様乱数
VAEと比べて、比較的「読める」文字になっていると思います。さすがDiscriminatorが、最低限「読める」ものになることを要求しており、可読性の低いものは少ないです。
##labelを指定し、noize vector zは定数
こちらもきれいに見えているのではないかと思います。
#付録
ConditionalなGANを実装するまえに、普通のGANの実装もしてみました。その際、セレブの顔画像を使った生成も行っていますので、付録として展示します。
githubは、下記です:
https://github.com/ysasaki6023/faceGAN/tree/v1.0