JKになりたい

何か書きたいことを書きます。主にWeb方面の技術系記事が多いかも。

DCGANで遊んでみたメモ(2)

DCGANによる顔画像の生成

データセットはみんな使ってるこれ。

mmlab.ie.cuhk.edu.hk

画像サイズを28x28x3(RGB)に整形して入力とする。

ポイントは、batch_normalizationを導入すること、らしい。 これは、ミニバッチ毎にデータを標準化する手法。

各レイヤーのLeakyReluへの入力タイミングでbatch_normalizationを適用する。

以下のようなイメージ。

Generator

with tf.variable_scope('generator', reuse=not is_train):
    x1 = tf.layers.dense(z, 4*4*512)
    x1 = tf.reshape(x1, (-1, 4, 4, 512))
    x1 = tf.layers.batch_normalization(x1, training=is_train)
    x1 = tf.maximum(0.2 * x1, x1)
    
    x2 = tf.layers.conv2d_transpose(x1, 256, 5, strides=3, padding='same')
    x2 = tf.layers.batch_normalization(x2, training=is_train)
    x2 = tf.maximum(0.2 * x2, x2)
    
    x3 = tf.layers.conv2d_transpose(x2, 128, 5, strides=2, padding='same')
    x3 = tf.layers.batch_normalization(x3, training=is_train)
    x3 = tf.maximum(0.2 * x3, x3)
    
    logits = tf.layers.conv2d_transpose(x3, out_channel_dim, 5, strides=1, padding='valid')
    
    out = tf.multiply(tf.tanh(logits), 0.5)

    return out

Discriminator

with tf.variable_scope('discriminator', reuse=reuse):
    x1 = tf.layers.conv2d(images, 64, 5, strides=2, padding='same')
    relu1 = tf.maximum(0.2 * x1, x1)
    
    x2 = tf.layers.conv2d(relu1, 128, 5, strides=2, padding='same')
    bn2 = tf.layers.batch_normalization(x2, training=True)
    relu2 = tf.maximum(0.2 * bn2, bn2)
    
    x3 = tf.layers.conv2d(relu2, 256, 5, strides=2, padding='same')
    bn3 = tf.layers.batch_normalization(x3, training=True)
    relu3 = tf.maximum(0.2 * bn3, bn3)

    flat = tf.reshape(relu3, (-1, 4*4*256))
    logits = tf.layers.dense(flat, 1)
    out = tf.sigmoid(logits)
    
    return out, logits

あとハマりどころがコレ↓


Note: when training, the moving_mean and moving_variance need to be updated. By default the update ops are placed in tf.GraphKeys.UPDATE_OPS, so they need to be added as a dependency to the train_op. Also, be sure to add any batch_normalization ops before getting the update_ops collection. Otherwise, update_ops will be empty, and training/inference will not work properly. For example:


(引用)tf.layers.batch_normalization  |  TensorFlow

ということでOptimizerではこんな感じで更新を明示します

with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
    discriminator_optimizer = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(discriminator_loss, var_list=discriminator_vars)
    generator_optimizer = tf.train.AdamOptimizer(learning_rate, beta1=beta1).minimize(generator_loss, var_list=generator_vars)

結果

最初はランダムノイズです。

f:id:sakata_harumi:20180506224346p:plain

学習途中
(ミニバッチのLoss)
Discriminator Loss: 0.0795...
Generator Loss: 3.1901...

ふええ・・

f:id:sakata_harumi:20180506224416p:plain

学習途中

徐々に色があって顔っぽくなってきた。まだホラー。

f:id:sakata_harumi:20180506224812p:plain f:id:sakata_harumi:20180506224912p:plain

学習途中

Discriminator Loss > Generator Lossになってきた辺りで、 顔っぽくなってきた。

f:id:sakata_harumi:20180506225030p:plainf:id:sakata_harumi:20180506225027p:plain

学習停止直前

人の顔っぽくなってきたので、学習を打ち止めました。

ホラー感がなくなりましたね。

Discriminator Loss: 2.1258...
Generator Loss: 0.2235...

f:id:sakata_harumi:20180506225253p:plain

Discriminator Loss: 2.2205...
Generator Loss: 0.2133....

f:id:sakata_harumi:20180506225347p:plain

次は、Conditional-GANで遊んでみたいなあ。(小並感)