DeepLearning
アイドルマスター
TensorFlow
ミリオンライブ
ポケモン

画像生成の最近流行り、DCGANを使ってみました。
これをポケモンで学習させれば、いい感じの新しいポケモン作れるのでないか、と思ってやってみました。
今回はTensorflowで実装された
DCGAN-tensorflow [ https://github.com/carpedm20/DCGAN-tensorflow ]
を使ってみました。

[追記]
既に試されている方がいらしたらしいです。
http://bohemia.hatenablog.com/entry/2016/08/13/132314
こちらではポケGOの画像から生成したようです。

インストール

Tensorflowがインストールされていれば、git cloneで取るだけです。
Tensorflowインストールはこちら
https://qiita.com/nagayosi/items/7ecd9ef446d255c7d866

サンプルデータ取得

デモ学習で使うデータ Mnist と セレブ(CelebA) をダウンロードします。

python download.py mnist celebA

デモ学習

Mnistの学習は下記らしいです。

python main.py --dataset mnist --input_height=28 --output_height=28 --train

CelebAの学習は下記らしいです。

python main.py --dataset celebA --input_height=108 --train --crop

オリジナル学習

自分で容易したデータでの学習方法です。

学習データの位置

dataディレクトリの中に、学習データを格納するディレクトリを作ります(今回はSampleという名前)。

$DCGAN-tensorflow --- data --- Sample --- data1.jpg
                                       |- data2.jpg ...

学習のコマンド

学習するには下記コマンドで行えます。

python main.py --train --dataset Sample --input_height 120 --output_height 120 --crop

--train で学習フラグを立てます。
--dataset の後に学習データを保存したディレクトリの名前をつけます。
--input_height の後に入力画像の縦幅をつけます。(多分、Discriminator)
--output_height の後に出力画像の縦幅をつけます。(こっちが多分Generator)
--crop は学習画像の中心から切り抜く、ということらしいです。

引数は他にも色々ありました。
詳しくはmain.pyのflagsという部分にありました。

ポケモンで学習させた

ポケモンの画像で学習させてみました。
https://kamigame.jp/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3USUM/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3/%E8%89%B2%E9%81%95%E3%81%84%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3%E4%B8%80%E8%A6%A7.html
こちらのサイトから画像を拝借しました。
容易したのは、カントー151匹のイロチありで、全部で302データです。

学習結果

Macbook AirのCPUでやらせた結果、100epochに31228秒(8時間)かかってしまいました。
これからは研究室のGPUを乱用するしかないです。

各パラメータは以下の通り、これ以外はデフォ値です。

--input_height: 120
--output_height: 120
--epoch: 100
--learning_rate: 0.0001
--crop

各エポックでの途中結果はこんな感じでした。
回数が進むとなぜか色が変わるんですよね笑
一応形っぽいものはできてきている感じですね。

  • 100epoch

もっと頑張りたいですね。
せめて、ポケモンの形はだしたい。。

<考察>
おそらくポケモンの画像だと値の分散が大きいのが、問題だと思います。
MNISTや人の顔だと、画像にある程度ベースの形があるのですが、ポケモンだと形、色などがバラバラすぎて対応しきれないのかもしれません。

学習結果v2!

前回より色々変えて試してみました。
今回はGPUを使ったので、前回よりゴリ押しでできました
各パラメータは以下の通り、これ以外はデフォ値です。

--input_height: 120
--output_height: 120
--epoch: 1000
--learning_rate: 0.0001

各エポックでの成果はこんな感じです!

  • 25epoch, 50epoch, 75epoch、100epoch
  • 200epoch, 300epoch, 400epoch, 500epoch
  • 600epoch, 700epoch, 800epoch, 900epoch
  • 1000epoch

こんな感じです。

<考察>
200epochまでは、”形”を学習しているのでしょう。
色に関しては各epochで、一色にしかなっていませんが、形が段々できている印象です。
300epochくらいから、漸く”色”の学習ができているようです。
400epochくらいからポケモンっぽくなってますね。

前回より”ポケモンっぽい”画像になったかと思います。
まだ、画像が鮮明にならないのは、やはりポケモンの色・形の分散が大きいので、ネットワークが対応しきれてないのかもしれません。
ネットワークのアーキテクチャをいじれるようになれば、更にポケモンにできるのかもしれません。

学習結果v3!

いろいろ試した結果、次のパラメータでいい感じでできました。
(これをshファイルにするとあとあと便利だと思います!)

train.sh
DATA='Pokemon'

python main.py    --train \
     --dataset ${DATA} \
     --input_height 120 --output_height 120 \
     --input_fname_pattern=*.png \
     --epoch=5000 \
     --batch_size=64 \
     --learning_rate=0.001

python main.py   --train \
     --dataset ${DATA} \
     --input_height 120 --output_height 120 \
     --input_fname_pattern=*.png \
     --epoch=5000 \
     --batch_size=64 \
     --learning_rate=0.0001
  • 4500epoch, 5000epoch

すごくポケモンっぽくなりました!
ラプラスが多い気がしますが。
いろんなポケモンのパーツと色が合わさってできた感じです。

所恵美ちゃんを創る

ミリシタの所恵美ちゃんで学習させました。
グーグル画像検索の結果の顔の部分をクリップして160枚の学習データを集めました。

いろいろ試した結果、次のパラメータでいい感じでできました。
(これをshファイルにするとあとあと便利だと思います!)

train.sh
DATA='Megumi'

python main.py    --train \
     --dataset ${DATA} \
     --input_height 120 --output_height 120 \
     --input_fname_pattern=*.png \
     --epoch=5000 \
     --batch_size=64 \
     --learning_rate=0.001

python main.py   --train \
     --dataset ${DATA} \
     --input_height 120 --output_height 120 \
     --input_fname_pattern=*.png \
     --epoch=5000 \
     --batch_size=64 \
     --learning_rate=0.0001

白石紬ちゃんを創る

同じくミリシタのつむつむこと白石紬ちゃんを創ってみました。
学習データは同じくググ検から153画像を集めました。

結果はこんな感じです。

両方とも顔の画像になっています。(GANすごい!)
しかしエポックを増やすと学習データに近くなりすぎて、しかも同じ画像が出やすくなってしまう、という問題があります。
おそらくこれは、GANがDiscriminatorのLossに依存していることが大きいと思います。
エポックが進むとDiscriminatorのLossが小さく、GeneratorのLossが小さくなっていました。つまり、DiscriminatorのLossによってGeneratorが上手く学習されますが、途中からある画像でDiscriminatorが判別できるようになるため、その画像でGeneratorの学習もサチってしまう、のではないかと思います。
つまり、GeneratorのLossとDiscriminatorのLossの他に、新しいLossを導入すれば、生成画像の分散を制御できると思います。

エラー集

Traceback (most recent call last):
  File "main.py", line 100, in <module>
    tf.app.run()
  File "/home/usrs/nagayosi/miniconda3/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 126, in run
    _sys.exit(main(argv))
  File "main.py", line 83, in main
    dcgan.train(FLAGS)
  File "/var/autofs/home/casa/usrs/nagayosi/DCGAN-tensorflow/model.py", line 180, in train
    sample_inputs = np.array(sample).astype(np.float32)
ValueError: could not broadcast input array from shape (120,120,3) into shape (120,120)

util.pyのimread関数を以下に書き換える。

def imread(path, grayscale = False):
     if (grayscale):
        return scipy.misc.imread(path, flatten = True).astype(np.float)
     else:
         import cv2
         return cv2.imread(path)
         #return scipy.misc.imread(path).astype(np.float)