MNIST GAN发电机中间被黑色包围的白色区域

时间:2018-10-15 21:29:09

标签: tensorflow generator mnist

以下代码是从有关UDEMY的GAN MNIST教程中复制的。当我运行代码时,它趋向于创建在中心具有较大白色区域的图像,该区域的侧面为黑色(在黑色背景上绘制一个空的实心圆)。我不知道问题出在哪里,因为我只完成了教程告诉我的逐字逐句的操作。唯一的区别是我以不同的方式提取MNIST数据。关于tensorflow的事情最近发生了变化吗?

import tensorflow as tf
import numpy as np
import gzip
from PIL import Image
import os.path

def extract_data(filename, num_images):
        """Extract the images into a 4D tensor [image index, y, x, channels].
        Values are rescaled from [0, 255] down to [-0.5, 0.5].
        """
        print('Extracting', filename)
        with gzip.open(filename) as bytestream:
            bytestream.read(16)
            buf = bytestream.read(28 * 28 * num_images)
            data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)
            #data = (data - (PIXEL_DEPTH / 2.0)) / PIXEL_DEPTH
            data = data.reshape(num_images, 28, 28, 1)
            return data

fname_img_train = extract_data('../Data/MNIST/train-images-idx3-ubyte.gz', 60000)

def generator(z, reuse=None):
    with tf.variable_scope('gen',reuse=reuse):
        hidden1 = tf.layers.dense(inputs=z,units=128)
        alpha = 0.01
        hidden1=tf.maximum(alpha*hidden1,hidden1)
        hidden2=tf.layers.dense(inputs=hidden1,units=128)
        hidden2 = tf.maximum(alpha*hidden2,hidden2)
        output=tf.layers.dense(hidden2,units=784, activation=tf.nn.tanh)
        return output

def discriminator(X, reuse=None):
    with tf.variable_scope('dis',reuse=reuse):
        hidden1=tf.layers.dense(inputs=X,units=128)
        alpha=0.01
        hidden1=tf.maximum(alpha*hidden1,hidden1)
        hidden2=tf.layers.dense(inputs=hidden1,units=128)
        hidden2=tf.maximum(alpha*hidden2,hidden2)
        logits=tf.layers.dense(hidden2,units=1)
        output=tf.sigmoid(logits)
        return output, logits

real_images=tf.placeholder(tf.float32,shape=[None,784])
z=tf.placeholder(tf.float32,shape=[None,100])
G = generator(z)
D_output_real, D_logits_real = discriminator(real_images)
D_output_fake, D_logits_fake = discriminator(G,reuse=True)

def loss_func(logits_in,labels_in):
    return tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
        logits=logits_in,labels=labels_in))

D_real_loss = loss_func(D_logits_real,tf.ones_like(D_logits_real)*0.9)
D_fake_loss = loss_func(D_logits_fake,tf.zeros_like(D_logits_real))

D_loss = D_real_loss + D_fake_loss
G_loss = loss_func(D_logits_fake,tf.ones_like(D_logits_fake))

learning_rate = 0.001

tvars = tf.trainable_variables()

d_vars= [var for var in tvars if 'dis' in var.name]
g_vars = [var for var in tvars if 'gen' in var.name]

D_trainer = tf.train.AdamOptimizer(learning_rate).minimize(D_loss,var_list=d_vars)
G_trainer = tf.train.AdamOptimizer(learning_rate).minimize(G_loss,var_list=g_vars)

batch_size=100
epochs=30
set_size=60000

init = tf.global_variables_initializer()
samples=[]
def create_image(img, name):
        img = np.reshape(img, (28, 28))
        print("before")
        print(img)
        img = (np.multiply(np.divide(np.add(img, 1.0), 2.0),255.0).astype(np.int16))
        print("after")
        print(img)
        im = Image.fromarray(img.astype('uint8'))
        im.save(name)
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(epochs):
        np.random.shuffle(fname_img_train)
        num_batches=int(set_size/batch_size)
        for i in range(num_batches):
            batch = fname_img_train[i*batch_size:((i+1)*batch_size)]
            batch_images = np.reshape(batch, (batch_size,784))
            batch_images = batch_images*2.0-1.0
            batch_z = np.random.uniform(-1,1,size=(batch_size,100))
            _ = sess.run(D_trainer, feed_dict={real_images:batch_images,z:batch_z})
            _ = sess.run(G_trainer,feed_dict={z:batch_z})

        print("ON EPOCH {}".format(epoch))
        sample_z = np.random.uniform(-1,1,size=(batch_size,100))
        gen_sample = sess.run(G,feed_dict={z:sample_z})
        create_image(gen_sample[0], "img"+str(epoch)+".png")

1 个答案:

答案 0 :(得分:1)

据我所知,您尚未标准化训练数据。与使用您的extract_data()函数相比,执行以下操作要容易得多:

from tensorflow.keras.datasets.mnist import load_data()
(train_data, train_labels), _ = load_data()
train_data /= 255.

通常,人们每个时代从潜在空间采样两次:一次用于鉴别器,一次用于生成器。不过,这似乎没有什么改变。

实施这些更改之后,使用200的批处理量和100个纪元的训练,我得到了以下结果:gen_sample。结果非常糟糕,但是绝对比“黑色背景上的空圆”要好。 请注意,生成器和所使用的鉴别器的体系结构非常简单。根据我的经验,堆叠一些卷积层可以得到完美的结果。另外,我不会使用tf.maximum()函数,因为它会产生可能会对梯度流产生负面影响的不连续性。

最后,我使用了以下内容,而不是您的create_image()函数:

def plot_mnist(samples, name):
    fig = plt.figure(figsize=(6,6))
    gs = gridspec.GridSpec(6,6)
    gs.update(wspace=0.05, hspace=0.05)
    for i, sample in enumerate(samples):
        ax = plt.subplot(gs[i])
        plt.axis('off')
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        ax.set_aspect('equal')
    plt.imshow(sample.reshape(28,28), cmap='Greys_r')
    plt.savefig('{}.png'.format(name))
    plt.close()

有许多不同的方法可以改善GAN模型的质量,并且其中大多数技术都可以在网上轻松找到。如果您有任何具体问题,请告诉我。