在 TensorFlow 中使用 LSTM-CGAN 生成 MNIST 数字

Posted

技术标签:

【中文标题】在 TensorFlow 中使用 LSTM-CGAN 生成 MNIST 数字【英文标题】:Generating MNIST numbers using LSTM-CGAN in TensorFlow 【发布时间】:2018-08-04 18:35:00 【问题描述】:

受this article 的启发,我正在尝试构建一个条件GAN,它将使用LSTM 生成MNIST 数字。我希望我使用的架构与下图相同(鉴别器中的双向 RNN 除外,取自 this paper):

当我运行这个模型时,我得到了非常奇怪的结果。这张图片显示了我的模型在每个 epoch 后生成了 3 号。它应该看起来更像this。真的很糟糕。

我的 鉴别器 网络的损失非常快地下降到接近于零。然而,我的 generator 网络的损失会在某个固定点附近波动(可能会慢慢发散)。我真的不知道发生了什么。这是我的代码中最重要的部分(完整代码here):

timesteps = 28
X_dim = 28
Z_dim = 100
y_dim = 10

X = tf.placeholder(tf.float32, [None, timesteps, X_dim]) # reshaped MNIST image to 28x28
y = tf.placeholder(tf.float32, [None, y_dim]) # one-hot label
Z = tf.placeholder(tf.float32, [None, timesteps, Z_dim]) # numpy.random.uniform noise in range [-1; 1]

y_timesteps = tf.tile(tf.expand_dims(y, axis=1), [1, timesteps, 1]) # [None, timesteps, y_dim] - replicate y along axis=1

def discriminator(x, y):
    with tf.variable_scope('discriminator', reuse=tf.AUTO_REUSE) as vs:
        inputs = tf.concat([x, y], axis=2)
        D_cell = tf.contrib.rnn.LSTMCell(64)
        output, _ = tf.nn.dynamic_rnn(D_cell, inputs, dtype=tf.float32)
        last_output = output[:, -1, :]
        logit = tf.contrib.layers.fully_connected(last_output, 1, activation_fn=None)
        pred = tf.nn.sigmoid(logit)
        variables = [v for v in tf.all_variables() if v.name.startswith(vs.name)]
        return variables, pred, logit

def generator(z, y):
    with tf.variable_scope('generator', reuse=tf.AUTO_REUSE) as vs:
        inputs = tf.concat([z, y], axis=2)
        G_cell = tf.contrib.rnn.LSTMCell(64)
        output, _ = tf.nn.dynamic_rnn(G_cell, inputs, dtype=tf.float32)
        logit = tf.contrib.layers.fully_connected(output, X_dim, activation_fn=None)
        pred = tf.nn.sigmoid(logit)
        variables = [v for v in tf.all_variables() if v.name.startswith(vs.name)]
        return variables, pred

G_vars, G_sample = run_generator(Z, y_timesteps)
D_vars, D_real, D_logit_real = run_discriminator(X, y_timesteps)
_, D_fake, D_logit_fake = run_discriminator(G_sample, y_timesteps)

D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake))
G_loss = -tf.reduce_mean(tf.log(D_fake))

D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=D_vars)
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=G_vars)

我的模型很可能有问题。任何人都可以帮助我使生成器网络收敛吗?

【问题讨论】:

These tips 可能很有用,即使它们是为简单的 GAN 编写的。您的问题是鉴别器学习速度如此之快,以至于它确实允许生成器改进。这是一个常见的问题。如果您的代码没有明显的错误,那么该链接应该可以帮助您解决问题。 我想知道生成器是否需要更多信息来创建有意义的数字?它似乎在每一行输出非常相似的东西? @JacquesKvam 在某些情况下,它比上图要糟糕得多。生成器只返回垂直直线,顶部只有几行噪声。 【参考方案1】:

您可以采取一些措施来改进您的网络架构和训练阶段。

    从生成器和鉴别器中删除tf.nn.sigmoid(logit)。只返回pred

    使用数值稳定的函数来计算您的损失函数并修复损失函数:

    D_loss = -tf.reduce_mean(tf.log(D_real) + tf.log(1. - D_fake)) G_loss = -tf.reduce_mean(tf.log(D_fake))

应该是:

D_loss_real = tf.nn.sigmoid_cross_entropy_with_logits(
              logits=D_real,
              labels=tf.ones_like(D_real))
D_loss_fake = tf.nn.sigmoid_cross_entropy_with_logits(
              logits=D_fake,
              labels=tf.zeros_like(D_fake))

D_loss = -tf.reduce_mean(D_loss_real + D_loss_fake)
G_loss = -tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
              logits=D_real,
              labels=tf.ones_like(D_real)))

一旦你修复了损失并使用了数值稳定的函数,事情就会变得更好。此外,根据经验,如果损失中有太多噪声,请降低学习率(在训练 GAN 时,ADAM 的默认 lr 通常太高)。 希望对你有帮助

【讨论】:

以上是关于在 TensorFlow 中使用 LSTM-CGAN 生成 MNIST 数字的主要内容,如果未能解决你的问题,请参考以下文章

使用 GPU 无法在 tensorflow 教程中运行词嵌入示例

如何在 pytorch 和 tensorflow 中使用张量核心?

在 cmake 中使用预编译的 tensorflow

如何使用 c++ 在 tensorflow 中保存模型

在 Tensorflow 函数中使用 @ 符号

如何在 tensorflow 中使用 intel-mkl