GANの安定化の非常に大きなブレイクスルーである「Spectral Normalization」を使ったGAN(SNGAN)を実装してみました。
公式
論文
Takeru Miyato, Toshiki Kataoka, Masanori Koyama, Yuichi Yoshida. Spectral Normalization for Generative Adversarial Networks. ICLR2018. OpenReview
Arxiv version
書いたのは日本人でうち2人はPFNの方です。あまり知られていませんが、GANの安定化の研究に大きく貢献したのは実は日本人なのです。
デモ
https://www.youtube.com/watch?v=q3yy5Fxs7Lc
https://www.youtube.com/watch?v=83D_3WXpPjQ
Chainerによる実装
https://github.com/pfnet-research/sngan_projection
自分の実装・ポスト
PyTorchによる実装
https://github.com/koshian2/SNGAN
より詳しい内容(日本語で自分が書いたもの)
https://blog.shikoan.com/sngan/
※とにかく長いので時間あるときに読んでください。この投稿は相当端折ったものです。
Spectral Normalizationのやっていること
前提(WGANの背景)
Spectral Normのやっていることを知るには、WGANの理論的な背景を知っていたほうがわかりやすいです。WGANでは「GANの安定性/出力画像の質の向上には、Dの損失関数の連続性が重要。$\theta\to P_\theta$のマッピングが滑らかであるほどよい」というのが大きな背景にあります。
その上で、WGANではDのスペクトルにリプシッツ連続という強い制約を置きます。このリプシッツ連続がGANの安定性を語る上でのキーワードとなっています。
WGANではリプシッツ連続を実践する手法の1つとして、損失関数にWasserstein距離を使っています(ここは今回大事ではないので省略)。
Spectral Normの考え方
「結局大事なのってリプシッツ連続であって、何らかの別の方法で制約をおければ、別にWasserstein距離でなくてもいいよね」というのがSpectral Normの根幹の考え方です。実際WGAN-GP(WGANの改良版)はBackpropを2回走らせないといけないので計算が遅かったりします。
その上で、Spectral NormではDのBatch NormをSpectral Normという特別なNormalizationレイヤーに置き換えるということで、この制約を実現しています。論文のGAN(SNGAN)では、損失関数にHinge Lossを使っていたりと、WGANの研究をかなり踏襲してはいるものの、Wasserstein距離からは既に離れているのが特徴です。SA(Self attention)GANや、BigGANといったモダンなGANではSpectral Normを使いつつHinge Lossを損失関数として使っています。Wasserstein距離にこだわらないのが最近のトレンドです。
Spectral Normって具体的にどういうNormalizationかというと、係数行列の特異値分解を使ったNormalizationです。
この$u_l^TW^lv_l$というのが特異値分解です。ただし、そのままSVDなどの関数をかませると遅いので、Power Iterationというアルゴリズムでニューラルネットの中で高速に計算できるようにしています。具体的になにやっているか気になる場合は、コードを見るのが速いと思います。
PyTorch公式でも実装があるので、これを使うのもありです。
アニメ顔を生成してみる
AnimeFace Character DatasetをSNGANで生成してみます。
SNGANはACGANのようにラベルを加味して生成できるのでそれで生成してみました(Unconditionalなケースも見たい場合は巻末のリンクから別記事を見てください)
大方の輪郭はできています。
顔っぽくなってきました。
細かい輪郭ができてきましたが、まだ線がぐにょぐにょですね
とてもいい感じになってきました。背景がぼやけるのは仕方ないです。
1100エポック回したのはGを約5万回アップデートするためです。SNGANではアップデート回数をG:D=1:5にしたほうがうまくいきやすい(Spectral NormのぶんDの学習が進みづらい)ので、どうしても訓練時間は長めになってしまいます。訓練時間はRTX 2080Tiを1枚で丸一日程度でした。
潜在空間の補間
ACGANの場合は、クラス単位でモード崩壊が置きてしまいましたがどう変わっているでしょうか?
ACGANの場合
クラス単位で1つの画像しか出力できない=モード崩壊が起こっています
(左:サンプリング、右:補間です)。まずクォリティが全然違いますし、補間をすると潜在空間の乱数を動かすにつれて表情や顔の向きが変化しているのがわかります。
Anime Face Datasetはキャラ別に176枚のクラス、14490枚の画像からなります。つまり1クラス平均82枚しかありません。これでもそこそこGANとして形になってしまうのがSNGANのすごいところです。
花の生成をしてみる
同様にOxford Flower Datasetという花のデータセットをSNGANしてみます。
これは8189枚の画像、花の種類別に102のクラスからなります。1クラスあたりの枚数はAnime Faceとほぼ同じです。
花の生成で使ったモデルはAnimeFaceのものとほぼ同じですが(そしてAnimeFaceのモデルは論文のImageNetのモデルを出力解像度だけいじったもの)、Dの計算量を減らすためにDの最初にstride=2のConvを入れました。花では5万回Gをアップデートさせるために1900 epoch回しますが、Dの計算量削減のおかげで、GPU1枚で18時間程度で計算できます。
500 epoch
花びらの輪郭はそれっぽい感じになってきました
1000 epoch
だいぶそれっぽい形にはなってきましたが、一部難しい花があるようです
1900 epoch(完成)
ちょっと花の構成がおかしいもの(花びらがバラバラになっているもの)がありますが、おそらくデータ数が足りなかったのでしょう。
潜在空間の補間
クラス単位でモード崩壊していないので、GAN自体はうまく行っています。出力のクォリティを上げるには、データ数を増やすかより最新のGANを使う必要がありそうです。
まとめ
Spectral Normalizationすごい。DのBatch Normを置き換えればいいだければわかりやすい。しかも、データ数が少なくてクラス数が多いケースでもモード崩壊しないので、相当有力な手法でしょう。SNGANで相当綺麗になるのが確認できたので、最新形を使えばどれだけいくのか夢がありますね。
次はこの発展型のSAGAN(Self attention GAN)いってみよう。
SNGANのより詳しい内容
もっと泥臭い内容が見たければこちら。論文の再実装や追加の実験結果などを掲載しています。
https://blog.shikoan.com/sngan/