1ヶ月かけて自分の偽写真をつくった話

まず下記の画像を見ていただきたい。以下はわたしの写真を元に生成した偽写真だ。

![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81883/f6819b84-81ce-4883-925d-bb5e47f77eec.gif)


要するに学習元データに自分の写真だけを使った上で、GAN(敵対的生成ネットワーク)で生成した偽写真だ。GANを使って架空の人の偽写真を生成する事例はよくあるが、何となく自分の写真を作ってみたかったので作ってみた。新しい自撮りのあり方として今後流行するかもしれない。特定人物の写真だけを元にディープラーニングで生成した画像は果たして写真なのか? 偽写真なのか? 証明写真にこの写真を使ったら詐欺なのか? といった疑問が浮かぶ。

まあ答えはよくわからないが、以下では作り方を解説していく。

ちなみに、今回はほとんど自分で実装せず、公開された実装サンプルをありがたく使用させてもらった。ディープラーニングや機械学習といったトピックは現在でもまだ難しいイメージがあると思うが、多少の基礎知識を身につければ、0から実装しなくても、公開されたソースコードを使っていろいろなことができる。
(と言いつつ動かすのに苦労したが……)

## まず素材を集めよう
- まず自分の顔写真が大量に必要。最低1000枚はほしい。
- 手動ではさすがにつらいので、動画でいこうと思いつく。
- iPhoneを自分の顔のまわりでグルグルまわしながら動画をとった。表情もいろいろあった方がいいと思ったので、マンガを読みながら撮影している。

15分くらいの動画をつくり、ffmpegを使って顔画像2400枚ほどが取れた(変な方向を見ているが実はPC上のkindleでマンガを読んでいる)。

<img width="780" alt="スクリーンショット 2019-10-17 16.41.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81883/aa8b93ac-f335-6eda-9bd9-f377e9c4f053.png">


## GAN(敵対的生成ネットワーク)の仕組み
GANの仕組みを大雑把に解説する。詳しい解説は「[今さら聞けないGAN](https://qiita.com/triwave33/items/1890ccc71fab6cbca87e)」「[はじめてのGAN](https://elix-tech.github.io/ja/2017/02/06/gan.html)」などを見てほしい。

GANでは、ディスクリミネーター(D)とジェネレーター(G)という2つのネットワークのゲームによって画像を生成する。

**ディスクリミネーター(識別者)**

- 本物の画像と、ジェネレーターが作った偽物画像を識別する。
- 入力: 画像データ
- 出力: 0／1 (または-1／1)

**ジェネレーター(生成者)**

- 乱数(潜在変数)をもとに画像を生成する。ディスクリミネーターをだますよう学習する。
- 入力: 100次元くらいの乱数(潜在変数)
- 出力: 画像と同じサイズの行列

両者の関係はよく贋金つくりと警官の関係にたとえられる。警官は贋金と本物を識別しようとし、贋金つくりは摘発を避けるため、巧妙な贋金つくりの技術を見につける。警官の技術が高まれば高まるほど、贋金つくりの能力も高まっていく。最終的には本物同様の模造品をつくるネットワークが手に入る。

## Progressive Growing of GANs
GANの変種はいくつもあるが、今回は比較的短時間の学習で大きな画像を作れるというProgressive Growing of GANs(PGGAN)を使用した。ちなみに上記の画像は128x128になっている。比較的短時間と言っても、Colaboratoryの無料GPUインスタンスでのろのろやっていたら結局一ヶ月かかってしまったが……。

詳しい解説はしないがProgressive Growing of GANsでは4x4、8x8、16x16と、生成する画像をだんだん大きくしていく。小さな画像を生成するディスクリミネーター／ジェネレーターのペアからはじめ、少しずつネットワークに付け足してより大きな画像を作れるネットワークを育てていく。

今回の実装はKerasでのチュートリアルを参考にしつつ、別のソースコードと組み合わせて修正していった。チュートリアルの方のライセンスが不明確なのでソースコード自体の公開は差し控えるが、基本的には[こちらのgithubのコード](https://github.com/MSC-BUAA/Keras-progressive_growing_of_gans)と同様なので、こちらのコードをベースに学習元の画像だけ差し替えれば動くのではないかと思う。

元論文

*Progressive Growing of GANs for Improved Quality, Stability, and Variation*, **Tero Karras** (NVIDIA), **Timo Aila** (NVIDIA), **Samuli Laine** (NVIDIA), **Jaakko Lehtinen** (NVIDIA and Aalto University) [Paper (NVIDIA research)](http://research.nvidia.com/publication/2017-10_Progressive-Growing-of)

参考にしたコード

- [Jason Brownlee, How to Implement Progressive Growing GAN Models in Keras, Machine Learning Mastery, Available from https://machinelearningmastery.com/how-to-implement-progressive-growing-gan-models-in-keras/, accessed 2019-12-16.](https://machinelearningmastery.com/how-to-implement-progressive-growing-gan-models-in-keras/)
- [Kun Yan (naykun), Yihang Yin (Somedaywilldo), Keras-progressive_growing_of_gans, Available from https://github.com/MSC-BUAA/Keras-progressive_growing_of_gans, accessed 2019-12-16.](https://github.com/MSC-BUAA/Keras-progressive_growing_of_gans)


## 学習過程
基本的にはColaboratoryの無料GPUインスタンスを使って学習させた。Google Drive上にモデルと画像を置いて、Colaboratoryを少し操作するだけで学習プロセスを実行できるようにして、地道に学習を繰り返した。記録によると23日かかっている(土日はさぼったりしていたので厳密に毎日学習させていたわけではない)。

余談だが、ColaboratoryでGPUを使いすぎると、以下のような表示が出て、しばらく使用できなくなってしまうので気をつけよう。
<img width="790" alt="スクリーンショット 2019-10-16 13.11.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81883/a81abdb9-b585-7131-ff39-81bb0be5d6cf.png">


ちなみに最近ColaboratoryはまたGPUが強化され、運がよければTesra T4とTesra P100が使えるようになった。この学習をしている当時はK80に当たることがほとんどだったので、今なら半分くらいの時間で学習が終わるかもしれない。