ブロックチェーン・AI・システム開発の株式会社INDETAIL

GANsによるウマが徐々に変化するgifアニメ生成とmode collapse

2018.12.23
eiyuu

※本記事は、INDETAIL Advent Calendar 2018の一環として投稿しています。

馬の画像

この記事の主旨

  • ウマが徐々に変化するgifアニメをGANsを使って生成します
  • mode collapseが発生したので、CycleGANのCycle Consistency Lossっぽく損失関数を変更することで回避しました

はじめに

こんにちは、eiyuuです。でも僕がeiyuuであることは大して重要じゃなくて、まずはこの動画を見て欲しいんです。1分あるけども、最初の数秒だけで充分です。

これはCrypkoという、二次元美少女を題材としたcrypto collectible game※1の紹介動画のようなものです。「ようなもの」っていうのは、これはCrypkoの技術的な補足のための動画であって、実際利用する際には特に関係のないものだからです。

※1 複製不可能な猫とか美少女とかの画像(題材はゲームによって異なる)を競り落としたり、他人に売ったり買ったり、交配させて両親の特徴を受け継いだ画像を生成したりして遊ぶゲームのことです。

別バージョンを作りたい

さて、あなたはこの動画自体を見たことがあるかもしれません。あるいはこれのアイドルの顔版を見たことがあるかもしれません。そうでなくとも、20年以上前のJリーグカレーのCMでも思い出しているかもしれません。何が言いたいかと言うと、顔が徐々に変化する動画なんて、特別珍しくも新しくもないと言うことです。

それでも僕はこの動画を見てすごいと思ったし、興味を持ちました。きっと同じように感じた方は少なくないとも思っています。ただ、何がすごいのかを説明するには別の専用記事が必要で、興味を持った理由についてはただの自分語りになってしまうので、どちらも省略します。ここまでの文章はただの導入なのです。

本題に近づいていきます。興味を持った理由について本当にざっくり話すと、この動画(ひいてはCrypkoの根幹となる部分)はGANs(Generative Adversarial Networks)という技術を応用して作られていて、僕が丁度そのGANsを仕事で取り扱っていたからです。

Crypkoの動画とは別種のGANsの応用だったのですが、習作としてこのCrypkoの動画っぽいものを作ってみようと思い立ったのです。で、同じく興味を持った同僚と何を題材にするかちょっと話して、サラブレッドの画像でやってみようって話になりました。僕はダビスタっぽくて面白そうと思ったのですが、同僚はウイニングポストっぽくて面白そうって思ったらしいです。

訓練データ

さて、手始めにまず学習用のデータ、つまり大量のサラブレッドの画像を用意しなければいけません。同僚がここなどから約5000枚用意してくれました。画像をここに載せるのはアレな気がするので載せませんが、この記事のTOPにある画像みたいな感じです。また、各画像は正方形になるよう上下に白埋めをします。

モデル概要

DiscriminatorとGeneratorは、Crypkoの前身となったサービスMakeGirlsMoeの技術部分の論文で紹介されているものを使用(Discriminatorの最後のタグ推定のための全結合層は除く)しました。また、損失関数としてDRAGANのものを使いました。コードはGitHubのソースを参考にしました。

実験1

学習データも用意した、モデルも用意したということで、喜び勇んで学習開始!退勤前にプログラムを走らせておくことで、翌日の朝のやる気をほんの少しだけ改善する手法を用います。翌朝出力されていた画像はこちら。

GANsが出力した馬の画像1

ウマだ。

僕も同僚も同じ気持ちでした。ただ、よく見ると毛の色は色々種類があるものの、馬のポーズや体型はほとんど似通ったものになってしまっています。そして、もう少し学習を進めると、全部同じ画像が出力されるようになってしまいました。いわゆるmode collapse※2です。

※2 学習が進むにつれて、Generatorの出力が入力に関わらず(ほぼ)一定になってしまう現象のことです。損失関数の設計が原因だったり、学習データ数の不足が原因だったりします。これを回避するための工夫を凝らした損失関数がいくつか提案されています(DRAGANなど)。

実験2

このままだと馬が次々変わっていく動画なんて夢のまた夢です(毛色は変わるけど)。ということで、mode collapseを回避する方法を模索しました。そもそもDRAGANの損失関数はmode collapseしにくいような工夫がされているので、そのパラメータを変えてみたのですが、いまいち変化が実感できませんでした。少し考えて、Discriminatorに画像の真贋だけではなく、元となったノイズ空間の値も同時に推定させればいいのではという考えに至ります。mode collapseしている場合Generatorの出力は入力に関わらず一定になるので、Generatorの出力から元のノイズ空間の値を推定できなくなるはずです。

要するに、Discriminatorに真贋の判定とは別で元のノイズの推定(Dres)をさせ、元のノイズとその推定値との距離Lresを計算し、DiscriminatorとGenerator両方の損失関数に加えます。Discriminatorへの入力が本物の時はLres = 0とします。Lresのことを個人的にRestorability Lossと呼んでいます。

数式

zはノイズベクトルで、λresはノイズ推定の重みです。これはCycleGANのCycle Consistency Lossから発想したのですが、Cycle Consistency LossはLノルムでした。単なる覚え間違いです。

その結果以下の画像が出力されました。画像上下の白埋め幅、背景、影のつき方などにバリエーションが出るようになりました(改めて見るとポーズはみんな一緒に見える)。

GANsが出力した馬の画像2

実験3

この後もうちょっと精度を向上させるために、パラメータのチューニングを行います。λresを小さくすると精度が少し上がるものの小さくしすぎるとやはりmode collapseしてしまうため、少し耐性を上げるために同僚に頼んでフランスのセリサイトからデータを約5000枚追加、合計約10000枚のサラブレッド画像で学習に臨んだところ、最終的に以下の画像が出力されました。だいぶ馬らしくなったし、バリエーションにも富んでいるように見えます。

GANsが出力した馬の画像3

データ追加で解決するなら結局λres = 0でも良かったのではとも思ったのですが、それだと上手くいきませんでした。学習初期にλresがある程度大きいことが必要なようです。

gifアニメ

ということで、この学習したモデルを使って馬が徐々に変化するgifアニメを作りました。

パラメータ

パラメータ名
max epoch 2000
batch size 128
ノイズ次元 256
データ数 11728
learning rate 初期値0.0001、100epoch毎に0.9倍
Adam β1 0.9
Adam β2 0.99
λres 初期値 30、30epoch毎に0.9倍
λDRAGAN 0.5

余談

実験3では、より良くGANsを学習させるためのノウハウ集(古め)から

  • 3. Use a spherical Z
  • 6. Use Soft and Noisy Labels
  • 13. Add noise to inputs, decay over time

を新たに試しました。体感で申し訳ないですが、割と効果があったように思っています。

まとめ

ということでCrypkoに影響されてウマの画像が徐々に変化する動画を作ろうとしたらmode collapseしたため、CycleGANのCycle Consistency Lossっぽく損失関数を変更することで回避しました。という話でした。

なんとなくACGANっぽい雰囲気も感じるし、きっとこのやり方にはすでに名前がついていて僕が知らないだけだと思っています。もしこいつの真名をご存知の方がいらっしゃいましたらご教示いただければと思います。

参考資料(辞書順)

ARQANA(フランスの競走馬セリサイト): https://www.arqana.com/
Crypko: https://crypko.ai/#/
CycleGAN: https://arxiv.org/pdf/1703.10593.pdf
DRAGAN: https://arxiv.org/pdf/1705.07215.pdf
DRAGANのコード参考: https://github.com/hwalsuklee/tensorflow-generative-model-collections
How to Train a GAN?: https://github.com/soumith/ganhacks
MakeGirlsMoeの論文: https://arxiv.org/pdf/1708.05509.pdf
日本競走馬協会: http://www.jrha.or.jp/

eiyuu

ロン毛

「いいね」ボタンを押すと、最新情報をすぐに確認できます。