2017年7月29日土曜日

DCGAN で数字画像を生成

色々なところでGenerative Adversarial Network (GAN) が使われているということなので、GANの初心者向け解説である
https://elix-tech.github.io/ja/2017/02/06/gan.html
を参考にして数字画像生成を試してみました。

試したのは、GANの中でもCNNを使うDeep Convolutional GAN (DCGAN) です。
同解説の中でコードを含めて解説されているのでほぼそのまま使いました。
学習に用いるデータはおなじみのMNISTです。
ただし、Keras 2.0.6 を用いたため、少し修正が必要になりました。

修正後のコードは

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from keras.models import Sequential
from keras.layers import Dense, Activation, Reshape
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import UpSampling2D, Conv2D

# For discriminator
from keras.layers.advanced_activations import LeakyReLU
from keras.layers import Flatten, Dropout

def generator_model():
    model = Sequential()
    model.add(Dense(1024, input_dim=100))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dense(128*7*7))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Reshape((128, 7, 7), input_shape=(128*7*7,)))
    model.add(UpSampling2D((2, 2), data_format='channels_first'))
    model.add(Conv2D(64, (5, 5), padding='same', data_format='channels_first'))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(UpSampling2D((2, 2), data_format='channels_first'))
    model.add(Conv2D(1, (5, 5), padding='same', data_format='channels_first'))
    model.add(Activation('tanh'))
    print(model.summary())
    return model

def discriminator_model():
    model = Sequential()
    model.add(Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=(1, 28, 28), 
                     data_format='channels_first'))
    model.add(LeakyReLU(0.2))
    model.add(Conv2D(128, (5, 5), strides=(2, 2), data_format='channels_first'))
    model.add(LeakyReLU(0.2))
    model.add(Flatten())
    model.add(Dense(256))
    model.add(LeakyReLU(0.2))
    model.add(Dropout(0.5))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))
    print(model.summary())
    return model
となります。これ以外の部分のコードは、同解説を参照ください。

5エポックまで学習を進めてみたところ、うまく文字が生成できる場合と、全く文字を生成できない場合がありました。文字が生成できる場合がSuccess{1,2,3}で、出来ない場合がFailです。

Epoch=0, Batch=0

Epoch=0, Batch=500

Epoch=0, Batch=1000

Epoch=0, Batch=1500

Epoch=1, Batch=0

Epoch=2, Batch=0

Epoch=3, Batch=0

Epoch=4, Batch=0

Epoch=5, Batch=0




Lossは次の図のようになりました。バッチサイズは32で、1エポックで実行されるバッチの総数は1875です。バッチごとにプロットしています。




初期値に大きく依存しているようで、全く同じように実行しても成功したり失敗したりします。安定して画像が生成できるようにするためにはもう少し工夫が必要なようです。

また、こうやって単純に画像を生成すると、生成した画像にラベルが付かないので、MNISTの学習データを増やす目的には使えません。ラベルと画像をペアで生成できればいいのですが、この点についてももう少し工夫が必要そうです。

0 件のコメント :