python - TensorFlow DCGAN 模型 : stability and convergence problems

标签 python machine-learning tensorflow neural-network conv-neural-network

我已经为 DCGAN 构建了自己的实现在 TensorFlow培训 MNIST .

完整代码(可运行)可在 github 上找到:https://github.com/Daniel451/tfdcgan

随时提交拉取请求:)

虽然模型尝试学习生成 MNIST 样本,但其稳定性非常差且收敛缓慢(即使在 10 个 epoch 后,生成的样本仍然看起来非常不自然)。

有趣的是,我在 Keras 中实现了非常相同的模型(使用 TensorFlow 后端)首先,这按预期工作。它学习合理的过滤器,并且当输入标准正态分布时,生成器会返回漂亮的 MNIST 样本。

我怀疑这是损失函数或模型配置的问题,但我无法找到确切的问题。

我注意到的另一个奇怪的事情是 TensorFlow 实现需要鉴别器的输出具有(batch_size, 2)的形状。因此,我使用 [0, 1] 编码生成器/假图像进行训练,并使用 [1, 0] 编码真实训练图像。

我的期望是只有 tf.nn.sparse_softmax_cross_entropy_with_logits应该需要这个形状,因为它需要稀疏标签才能工作......但即使 tf.nn.softmax_cross_entropy_with_logitstf.nn.sigmoid_cross_entropy_with_logits当鉴别器的形状为 (batch_size, 1) 时,不会返回有用的损失计算,其中生成器/假图像的编码仅为 0.0,真实训练图像的编码为 1.0。

Keras 实现可以很好地配合不同的损失函数和鉴别器的单个输出神经元。

这是生成器的(G)模型:

def model_generator(self, Z, reuse=True):

        init_op = tf.contrib.layers.xavier_initializer(uniform=True, dtype=tf.float32)

        with tf.variable_scope("g", initializer=init_op, reuse=reuse, dtype=tf.float32):

            with tf.variable_scope("reshape"):
                out = tf.layers.dense(Z, 7 * 7 * 256, activation=None)
                out = tf.reshape(out, [-1, 7, 7, 256])
                out = tf.layers.batch_normalization(out)
                out = tf.nn.tanh(out)

            with tf.variable_scope("deconv1"):
                out = tf.layers.conv2d_transpose(out, 128, [3, 3], strides=[2, 2], padding="same")
                out = tf.layers.batch_normalization(out)
                out = tf.nn.tanh(out)

            with tf.variable_scope("deconv2"):
                out = tf.layers.conv2d_transpose(out, 64, [3, 3], strides=[2, 2], padding="same")
                out = tf.layers.batch_normalization(out)
                out = tf.nn.tanh(out)

            with tf.variable_scope("output"):
                out = tf.layers.conv2d_transpose(out, 1, [5, 5], strides=[1, 1], padding="same")
                logits = out
                output = tf.nn.tanh(out)

        return output, logits

...这是鉴别器的(D)模型:

def model_discriminator(self, X, reuse=True, trainable=True):

        init_op = tf.contrib.layers.xavier_initializer(uniform=False, dtype=tf.float32)

        with tf.variable_scope("d", initializer=init_op, reuse=reuse, dtype=tf.float32):

            with tf.variable_scope("conv1"):
                out = tf.layers.conv2d(X, 64, [5, 5], strides=[2, 2], padding="same",
                                       trainable=trainable)
                out = tf.nn.tanh(out)

            with tf.variable_scope("conv2"):
                out = tf.layers.conv2d(out, 128, [3, 3], strides=[2, 2], padding="same",
                                       trainable=trainable)
                out = tf.nn.tanh(out)

            with tf.variable_scope("output"):
                out = tf.reshape(out, [-1, 7 * 7 * 128])
                out = tf.layers.dense(out, 2, activation=None, trainable=trainable)
                logits = out
                output = tf.sigmoid(out)

        return output, logits

我已经尝试了以下每个损失函数:

self.d_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.D_logits, labels=self.Y))
self.dg_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.DG_logits, labels=self.Y))

self.d_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_logits, labels=self.Y))
self.dg_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.DG_logits, labels=self.Y))

self.d_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.D_logits, labels=self.Y))
self.dg_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.DG_logits, labels=self.Y))

以下是相应的训练操作:

self.d_train_op = tf.train.AdamOptimizer(learning_rate=2e-4, beta1=0.5, beta2=0.999, name="Adam_D")\
            .minimize(self.d_loss, var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="d"))
self.g_train_op = tf.train.AdamOptimizer(learning_rate=2e-4, beta1=0.5, beta2=0.999, name="Adam_DG")\
            .minimize(self.dg_loss, var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="g"))

...beta1=0.5 由链接的论文建议,var_list=... 确保 DG 得到训练,但绝不会两者兼而有之。

我已将 MNIST 输入图像归一化为区间 [-1.0, 1.0],如多个来源所建议的那样。

self.G(生成器;用于预测)、self.D(鉴别器;用于分类)和 self.DG 的实例化(生成器+鉴别器,为了训练生成器)看起来像这样:

# placeholder for noise Z, fed into G
self.Z = tf.placeholder(tf.float32, shape=[None, 100], name="Z")
# placeholder for X, image data fed into D
self.X = tf.placeholder(tf.float32, shape=[None, 28, 28, 1], name="X")
# placeholder for Y, labels for training
self.Y = tf.placeholder(tf.int32, shape=[None], name="Y")

self.G, self.G_logits = self.model_generator(self.Z, reuse=False)
self.D, self.D_logits = self.model_discriminator(self.X, reuse=False)
self.DG, self.DG_logits = self.model_discriminator(self.G, trainable=False)

我每批处理分 3 个步骤训练 DCGAN:

  1. 使用真实图像训练 D
  2. 使用生成器/假图像训练 D
  3. 火车G

关于为什么这个网络表现不佳有什么想法吗?

最佳答案

我从你的问题中注意到的一件事是你提到你分三步进行训练。通常一个人分两步或一步进行训练。您可以单独训练鉴别器和生成器(2 个步骤),也可以一起训练(一个步骤)。

在训练鉴别器时,您可以获取真实样本和假样本的鉴别器输出,并生成两者的损失并应用梯度。

如果您一步训练,则需要确保以正确的顺序应用梯度。

关于python - TensorFlow DCGAN 模型 : stability and convergence problems,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43710471/

相关文章:

python - TensorFlow Precision/Recall/F1 分数和混淆矩阵

python - 如何编写一个可以获取函数或装饰函数的超时装饰器?

python - Azure ML 中的属性错误 : 'Logger' object has no attribute 'activity_info' during Dataset Registration

python - scikit-learn 中的样本权重在交叉验证中被破坏

machine-learning - 具有用户特定数据的 Tensorflow 模型

tensorflow - 有谁知道我们如何更改 DNNClassifier tensorflow 预制估计器中的损失函数?

python - wxGlade GUI行为问题

Python 数据类 : Mocking the default factory in a frozen Dataclass

python - 按索引将列表中的值映射到列表

python - 将 keras fit/fit_generator 与 max_queue_size、workers 和 use_multiprocessing 一起使用