[GAN] ポケモンの最終進化をさらに進化させようとして闇を見た

# ポケモン生成モデル
[過去の記事](https://qiita.com/Takuya-Shuto-engineer/items/1e2750905f22a0b07287)にまとめたStyleGAN2を用いたポケモン生成モデルを使って，ポケモンの最終進化系をさらに進化させてしまおうという悪いことを考えています．最近実装したものがうまくいくことが多くて，神になったつもりになっていたところで思いついたネタです．

今回は利用する技術を少し詳細に解説しつつ，応用例としてポケモンの進化に挑戦した話を紹介したいと思います．

具体的な手法としては，以下の流れです．今回は直線上に進化するポケモンが並んでいると仮説を立てました．ピカチュウ→ライチュウ→？という最終進化の更新を想定して説明します．

- 学習済StyleGAN2のモデルを読み込む
- ピカチュウとライチュウを生成するような潜在変数を推定する
- ピカチュウとライチュウの二点を通るような次元方向のベクトルを計算する
- そのベクトル方向に移動させていけばピカチュウ派生のポケモンが出てくる（はず）

![evolution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/0ad4738a-ec36-f3bb-c537-c564bc1d8e12.png)

# 関連研究の紹介

### [Image2StylyGAN](https://arxiv.org/abs/1904.03189)
PGGAN・StyleGANなど，十分に学習された表現力の高い生成モデルはデータセットには存在しない新しい顔を生み出すことが知られています．その性質を利用して，広い潜在変数空間上で任意の画像を生み出すような潜在変数を推定してやろうというのがImage2StyleGANのコンセプトです．

![ss01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/408d4319-ae1f-5a02-1c53-184518430407.png)
※Image2StyleGANの論文より引用

与えられた画像に対応する潜在変数を推定する方法は以下の二つが考えられます．

- 生成モデル（Decoder）に対応するEncoderを学習させる
- 生成画像と所望の画像の類似度を損失関数として，それを最小化するように潜在変数空間上を探索する

前者は経験的にうまくいかないことが知られているらしく，Image2StyleGANでは後者の最適化手法を採用しています．

損失関数には知覚損失(Perceptual Loss)を用いていて，ImageNetで学習済みのVGG16モデルに画像を入力して得られる特徴量を比較することで画像間の類似度を損失として計算しています．知覚損失をAdamで最適化することでVGG16が見ている知覚的な特徴が一致した生成画像を探し出すことができるわけです．Perceptual Modelとしては[zhang, 2018](https://github.com/richzhang/PerceptualSimilarity)が有名なようで，今回もこれを使うことにします．

画像間の類似度を計算するだけだったら，その目的で学習されている[FaceNet](https://arxiv.org/abs/1503.03832)なんかを再学習させて独自のモデルを作ってもいいかもしれないですね．

再現実験として，モデルをStyleGAN2(config-f)の学習済モデルに入れ替えて安倍首相を再構成してみたらこうなりました．

![shinzo.pngcompare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/64f15a53-a236-f8a1-6bd2-97ca5a0ab243.png)


### [InterFaceGAN](https://github.com/genforce/interfacegan)
こちらの研究も十分に学習された生成モデルにおける潜在変数空間上の画像のふるまいについての研究です．ある属性に関して，潜在変数空間上に分離超平面が存在することを示唆した研究です．分離超平面が推定できればその法線ベクトル方向に潜在変数を移動させればその属性を変化させられるわけです．

![ss02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/a8ad3887-7863-9bc2-0f93-10051c4356fb.png)
※InterFaceGANの論文から引用

分離超平面の推定手法はシンプルで結構泥臭い感じになっています．以下のステップを踏みます．例として眼鏡の超平面を推定することを考えます．

- 眼鏡の有無を0-1のスコアで推定するモデルを学習
- 生成モデルからランダムに数万件サンプル画像を生成
- 全サンプル画像に対して眼鏡のスコアを計算して，潜在変数座標とスコアの対応をつける
- SVMで眼鏡あり画像と眼鏡なし画像を最も分離するような超平面を計算する
- 推定された分離超平面の法線ベクトル方向に潜在変数を移動させることで属性値を変化させる

ちなみにこれも再現実験でStyleGAN2のモデルに差し替えて属性を変化させてみたらこんな感じになりました．

性別
![gender.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/7f6e19e6-a8ce-2ea9-caa8-32d737a337ad.png)

年齢
![age.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/45aec523-c72c-0ab8-795f-d092fd55de29.png)

長くなりましたが，この研究のおかげで潜在変数空間上では属性の分離超平面が学習の中で形成されていることがわかります．つまり，ポケモンの進化もある次元方向で表現されているのではないかと考えられます．ただし，さすがに人間の顔の属性とは違ってポケモンは多種多様すぎるので一つの種族の進化系統に限ってそれが成り立つと今回は考えます．

## やってみる
今回使うモデルはStyleGAN2(config-f)を[MosnterGAN](https://medium.com/@yvanscher/using-gans-to-create-monsters-for-your-game-c1a3ece2f0a0)のデータセットで学習したモデルです．画像サイズは64x64で，約15000枚の画像を1120kimg分学習しています．

生成画像はこんな感じ
![fakes001200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/34b6f015-72d7-ed34-b595-356cd787de8c.png)

正直品質はよくないんですが，データセットに含まれる画像を扱う分にはこんなもんでも行けるかなと思って使っています．（FIDスコア50くらいで停滞しているのでここで止めてます）

### Image2StyleGANでImage Embedding
ピカチュウとライチュウを再現できるような潜在変数が存在するかどうかまずは確かめます．

ピカチュウ
![pikachu_compare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/dd459cbd-1837-4fac-4376-9a06d0204b2e.png)

ライチュウ
![raichu_compare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/a08bcacf-fba7-ff66-6760-a3e3c5e42863.png)

完全にパチモンですね...この時点でモデルの表現力の低さに絶望してますが，最後までやってみます．

### 進化前後の二点間を通る次元方向へ移動させる
ピカチュウから進化方向へ少しずつ線形補完してみました．

![pikachu_interp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/c3418e93-aaa0-c828-5a9b-7be038d1b699.png)

悪・電気タイプあたりに進化しそうな結果が得られました．だんだん形が崩れていってしまうので，潜在変数空間の表現できる範囲を超えてしまっているんだと思います．表現力不足ですね．

悔しいですがここまできたのでせっかくなのでいろいろ試してみました．

![diguda_interp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/377053a2-0641-f5b2-836e-88dc188b4dad.png)

![pikusi_interp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/e8c6dfba-3c23-875f-5776-2a71270a3187.png)

だいたい精神汚染度の高い感じになっていっちゃいますね...

# まとめ
自前で学習したStyleGAN2のポケモン生成モデルを使って，ポケモンを進化させようとしてみましたが微妙な感じで終わってしまいました．

解決策としては，学習モデルの改善を検討すべきですね．
表現力不足ということで，多様なポケモンをとらえるために必要なデータ量に達していないことが考えられるので今後はデータ拡張を行ってデータセットの重増しを行おうかと思っています．

色違いのデータを入れているのですが，色違いが許されるなら画像全体の色調変換を行った画像を大量に入れても問題ないんじゃないかと．画像枚数をデータ拡張で50000枚くらいに増やして学習してみて再挑戦してみたいテーマでした！

![nuo-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593087/3fc01f68-bffa-635b-ec82-b5705e32d79f.png)

詳しい方など，アドバイスを頂けると泣いて喜びます！