ジョイジョイジョイ

ジョイジョイジョイジョイジョイ

櫟井唯ちゃんの画像を無限に生成する話りぴーと

joisino.hatenablog.com ▲昔の記事

前回の試みから二年以上経ちましたがまだゆゆ式二期は発表されません。(*1)

二期が発表されないためこの記事のタイトルものんのんびよりさんから拝借することになりました。

やはり今話題のディープラーニングでなんとかするしかなさそうです。

三行で説明して

Progressive Growing GAN (Tero Karras et. al. 2017) を chainer で実装して櫟井唯さん(ゆゆ式)の画像を生成しました。

唯

こんな感じのができました。(下の方にスクロールするともっとたくさんあります。)

github.com

レポジトリです。

Progressive Growing GAN とは

浅いネットワークで小さい画像を生成・識別することからはじめ、段階的にネットワークと画像を大きくしていく手法です。太古に流行った AE の事前学習のような感じです。

こうすることで本来不安定な GAN の学習が安定します。

GAN の枠組みは基本的に WGAN-GP を使っています。

この論文では他にも GAN を安定させたり、多様性をもたせるためのいくつかの技術を提唱しているので紹介します。

バッチごとの統計

GAN の generator は教師データ 1 枚を覚えてそれだけ生成する過学習に陥りがちです。そこで、この論文では、 discriminator の中間層に、バッチ全体の統計量を用いることを提唱しています。

具体的には、

  1. その層の入力 (batch x channel x height x width 次元) について、各位置・チャネルごと (channel x height x width 箇所) に、バッチを通して(各 batch 個ある値についての)標準偏差を求める。
  2. それらの値 (channel x height x width 個ある) の平均 m を求める。
  3. m を height x width 個並べたものを(それぞれのバッチについて)入力に append して、出力とする(batch x (channel + 1) x height x width 次元)

というものです。こうすることで、データ 1 枚だけ覚えるのでは、分散が小さすぎて discriminator に見破られてしまい、結果として generator は多様な画像を生成するようになります。

論文では、この層を最終層付近に一箇所挿入しています。

論文によると、さらにリッチな統計量も試したが、このシンプルな方法が一番良かったとのことです。

論文では 1. で標準偏差を用いていましたが、後述の実験では、安定しなかったので分散を用いました。(chainer の F.sqrt は現状二回微分に対応していなくて、自分で書いたので何か間違えていたのかも)

初期化と動的補正

畳み込みの重みの初期化に He normal (平均 0 標準偏差 sqrt(2/N) の正規分布で初期化)を使うことが多いですが、この論文では標準正規分布で初期化し、畳み込むときに sqrt(2/N) 倍することを提唱しています。

こうすることで、様々な畳み込み層の学習が同じペースで進み安定するそうです。

ピクセルごとの正規化

generator の畳み込み層の出力の際に、毎回ピクセルごとに正規化をかけます。

つまり、出力は batch x channel x height x width 次元 あるわけですが、 batch x height x width 個の場所(各場所には channel 個値がある)について、標準偏差で割ってから出力します。

こうすることで値が発散するのを防ぐ効果があるそうです。

交互に学習

WGAN-GP では discriminator(critic) 5 回学習するごとに generator 1 回学習などとすることが一般的ですが、この論文では交互に学習 (n_critic = 1) させたそうです。

特に理由は書いてませんでした。

(これでもうまくいくから)簡単のため?

discriminator の出力にペナルティ

この論文では WGAN-GP の loss に加えて、 discriminator の出力値の二乗に比例する項を設けています。

これは、この論文では discriminator の最終層の活性化関数に恒等関数を使っていて、discriminator が強い時に出力がどんどん大きくなるのを防ぐためだと思います。

実験

実際に python 3.5.2 + chainer 3.0.0 で実装して実験しました。(レポジトリは上の方に貼ってあります)

データは唯の画像 4077 枚です。(同じ・ほぼ同じ画像も多く含んでいます)

4x4 の画像からはじめて 256x256 の画像を出力するようにしました(論文では 1024x1024 までやっています)

学習にかかった時間は p3.2xlarge (GPU は Tesla V100) を使っておおよそ丸 2 日です。

生成は以下に載せるような gif アニメを一本作るくらいなら c5.large (GPU なし)で 1 分くらいでできます。

結果をどうぞ。

ギャラリー

割といい感じに生成できてるのから、雑に二枚の画像補完しただけやんけみたいなのまで様々です。

唯

唯

唯

唯

唯

唯

唯

唯

唯

唯

唯

唯

唯

唯

考察

体感的に他の GAN の手法に比べてかなり安定しているように思います。

論文のデモビデオほどはうまくいかなかったですが、思ったよりいい感じに生成できました。

論文のデモビデオでは、見たら分かるとおり、目や鼻や口の位置などをかなり丁寧に正規化しています(論文の appendix に正規化する手法も書いてあります)

今回はそこまで丁寧にデータを洗ったわけではないので、この辺をもっと丁寧にやるともっといい感じになりそうです。

データももっと必要そう。

そもそも唯の画像がそれほど大量には無いので、一般のアニメキャラクターの生成モデル作って唯でファインチューニングしたりすると良いかもしれません。

もっといい感じにしてまたどこかで発表できたらいいな。

おまけ

f:id:joisino:20171106173720p:plain

▲データに少しゆずこが混ざってしまったせいでできた合体画像

最後に

何か間違いや質問などがあればお願いします。

最後まで読んでいただきありがとうございました。

*1 OVA は発表されました!めでたい!!

参考文献

[1] Progressive Growing of GANs for Improved Quality, Stability, and Variation | Research

[2] GitHub - dhgrs/chainer-WGAN-GP: A Chainer implementation of WGAN-GP.

[3] GitHub - joisino/chainer-PGGAN: Progressive Growing of GANs implemented with chainer