使用GAN来生成mnist,但什么都不学习

时间:2017-11-16 02:05:24

标签: python tensorflow deep-learning

最近,我正在研究GAN网络,我用它来生成一个mnisit图像,我的电脑中的环境是ubuntu16.04,tensorflow,python3。

代码可以无任何错误地运行。但是结果显示网络学习没什么,通过训练,输出图像仍然是嘈杂的图像。

首先,我设计了一个生成器网络:输入是784维度的噪声数据,通过隐藏层并对其进行规则生成784维度的图像。

然后我设计了一个鉴别器网络:输入是真实图像和假图像,通过隐藏层并对其进行规则,输出为1维的logits。

然后我定义了generator_loss和discriminator_loss,然后训练生成器和鉴别器。它可以运行,但结果表明网络学习没什么,损失不能收敛。

import tensorflow as tf
import numpy as np 
import tensorflow.contrib.slim as slim
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("/home/zyw/data/tensor_mnist-master/MNIST_data/",one_hot=True)
batch_size = 100

G_in = tf.placeholder(tf.float32,[None,784])
G_h1 = tf.layers.dense(G_in, 128)
G_h1 = tf.maximum(0.01 * G_h1, G_h1)
G_out = tf.tanh(tf.layers.dense(G_h1, 784)) 

real = tf.placeholder(tf.float32,[None,784]) 
Dl0 = tf.layers.dense(G_out, 128)
Dl0 = tf.maximum(0.01 * Dl0, Dl0)
p0 = tf.layers.dense(Dl0, 1)

Dl1 = tf.layers.dense(real, 128)
Dl1 = tf.maximum(0.01 * Dl1, Dl1)
p1 = tf.layers.dense(Dl1, 1)

G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits =p0,labels=tf.ones_like(p0)*0.9))
D_real_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits =p1,labels=tf.ones_like(p1)*0.9))
D_fake_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits =p0,labels=tf.zeros_like(p0)))
D_total_loss = tf.add(D_fake_loss,D_real_loss) 

G_train = tf.train.AdamOptimizer(0.01).minimize(G_loss)
D_train = tf.train.AdamOptimizer(0.01).minimize(D_total_loss)

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    for i in range(1000):
        mnist_data,_ = mnist.train.next_batch(batch_size)

        # noise_org = tf.random_normal([batch_size,784],stddev = 0.1,dtype = tf.float32)
        noise_org = np.random.randn(batch_size, 784)
        a,b,dloss=  sess.run([D_real_loss,D_fake_loss,D_total_loss,G_train,D_train],feed_dict={G_in:noise_org,real:mnist_data})[:3]
        if i%100==0:
            print(a,b,dloss)
    #test_generative_image
    noise_org = np.random.randn(1, 784)
    image = sess.run(G_out,feed_dict ={G_in:noise_org})
    outimage = tf.reshape(image, [28,28])
    plt.imshow(outimage.eval(),cmap='gray')
    plt.show()
    print('ok')

结果是:

0.80509 0.63548 1.44057
0.33512 0.20223 0.53735
0.332536 0.97737 1.30991
0.328048 0.814452 1.1425
0.326688 0.411907 0.738596
0.325864 0.570807 0.896671
0.325575 0.970406 1.29598
0.325421 1.02487 1.35029
0.325222 1.34089 1.66612
0.325217 0.747129 1.07235

1 个答案:

答案 0 :(得分:1)

我添加了修改后的代码以及我做出更改的注释。此外,我已在下面描述了我的更改。

import tensorflow as tf
import numpy as np
import tensorflow.contrib.slim as slim
import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("/home/zyw/data/tensor_mnist-master/MNIST_data/",one_hot=True)

batch_size = 100

#define the generator function
def generator(input):
    G_h1 = tf.layers.dense(input, 128)
    # G_h1 = tf.maximum(0.01 * G_h1, G_h1)
    G_out = tf.sigmoid(tf.layers.dense(G_h1, 784))  # sigmoid function added
    return G_out

#Define the discrminator function
def discriminator(input):
    Dl0 = tf.layers.dense(input, 128)
    # Dl0 = tf.maximum(0.01 * Dl0, Dl0)
    p0 = tf.layers.dense(Dl0, 1)
    return p0

#Generator
with tf.variable_scope('G'):
    G_in = tf.placeholder(tf.float32, [None, 784])
    G_out = generator(G_in)

real = tf.placeholder(tf.float32, [None, 784])

#Discrimnator that takes the real data
with tf.variable_scope('D'):
    D1 = discriminator(real)

#Discriminator that takes fake data
with tf.variable_scope('D', reuse=True):  # need to use the same copy of Discrminator
    D2 = discriminator(G_out)

G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D2, labels=tf.ones_like(D2)))
D_real_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D1, labels=tf.ones_like(D1)))
D_fake_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D2, labels=tf.zeros_like(D2)))
D_total_loss = tf.add(D_fake_loss, D_real_loss)

vars = tf.trainable_variables() #all trainable variables
d_training_vars = [v for v in vars if v.name.startswith('D/')]  # varibles associated with the discrminator
g_training_vars = [v for v in vars if v.name.startswith('G/')]  # varibles associated with the generator

G_train = tf.train.AdamOptimizer(0.001).minimize(G_loss,var_list=g_training_vars)  # only train the variables associated with the generator
D_train = tf.train.AdamOptimizer(0.001).minimize(D_total_loss,var_list=d_training_vars)  # only train the variables associated with the discriminator

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    for i in range(1000):
        mnist_data, _ = mnist.train.next_batch(batch_size)
        # noise_org = tf.random_normal([batch_size,784],stddev = 0.1,dtype = tf.float32)
        noise_org = np.random.randn(batch_size, 784)

        a, b, dloss = sess.run([D_real_loss, D_fake_loss, D_total_loss, G_train, D_train],feed_dict={G_in: noise_org, real: mnist_data})[:3]
        if i % 100 == 0:
            print(a, b, dloss)

    # test_generative_image
    noise_org = np.random.randn(1, 784)
    image = sess.run(G_out, feed_dict={G_in: noise_org})
    outimage = tf.reshape(image, [28, 28])

    plt.imshow(outimage.eval(), cmap='gray')
    plt.show()
    print('ok')

实施 GAN 时,您应该注意几点,

  1. 需要使用相同的鉴别器副本(共享相同的副本 权重)当实施鉴别器损失时(在您的情况下 Dl0 Dl1 应该共享相同的句子。)
  2. 生成器激活功能应为 sigmoid 而不是 tanh 因为生成器的输出应该只在0之间变化 和(1.从它的图像)
  3. 在训练鉴别器时,您应该只训练与鉴别器相关的变量。同样,在训练生成器时,您只应训练与生成器相关联的变量。

  4. 有时确保鉴别器非常重要 比生成器更强大,否则它就没有了 足够的能力学习能够准确区分 在生成的和真实的样本之间。

  5. 这些只是你应该注意的 GAN 的基本内容。但是,在开发 GAN 时,您应该考虑许多其他方面。通过阅读以下两篇文章,您可以了解 GAN 的基本概念。

    1. http://blog.aylien.com/introduction-generative-adversarial-networks-code-tensorflow/
    2. http://blog.evjang.com/2016/06/generative-adversarial-nets-in.html
    3. 希望这有帮助。