【问题标题】:GAN not converging. Discriminator loss keeps increasingGAN 没有收敛。鉴别器损失不断增加
【发布时间】:2018-10-06 05:01:27
【问题描述】:

我正在 mnist 数据集上制作一个简单的生成逆向网络。

这是我的实现:

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

mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)

def noise(batch_size):
    return np.random.uniform(-1, 1, (batch_size, 100))

learning_rate = 0.001
batch_size = 128

input = tf.placeholder('float', [None, 100])
real_data = tf.placeholder('float', [None, 784])

def generator(x):
    weights = {
        'hl1' : tf.Variable(tf.random_normal([100, 200])),
        'ol'  : tf.Variable(tf.random_normal([200, 784]))
    }
    biases = {
        'hl1' : tf.Variable(tf.random_normal([200])),
        'ol'  : tf.Variable(tf.random_normal([784]))
    }

    hl1 = tf.add(tf.matmul(x, weights['hl1']), biases['hl1'])
    ol = tf.nn.sigmoid(tf.add(tf.matmul(hl1, weights['ol']), biases['ol']))

    return ol


def discriminator(x):
    weights = {
        'hl1' : tf.Variable(tf.random_normal([784, 200])),
        'ol'  : tf.Variable(tf.random_normal([200, 1]))
    }
    biases = {
        'hl1' : tf.Variable(tf.random_normal([200])),
        'ol'  : tf.Variable(tf.random_normal([1]))
    }

    hl1 = tf.add(tf.matmul(x, weights['hl1']), biases['hl1'])
    ol = tf.nn.sigmoid(tf.add(tf.matmul(hl1, weights['ol']), biases['ol']))

    return ol

with tf.variable_scope("G"):
    G = generator(input)

with tf.variable_scope("D"):
    D_real = discriminator(real_data)

with tf.variable_scope("D", reuse = True):
    D_gen = discriminator(G)

generator_parameters = [x for x in tf.trainable_variables() if x.name.startswith('G/')]
discriminator_parameters = [x for x in tf.trainable_variables() if x.name.startswith('D/')]

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

G_train = tf.train.AdamOptimizer(learning_rate).minimize(G_loss,var_list=generator_parameters)
D_train = tf.train.AdamOptimizer(learning_rate).minimize(D_total_loss,var_list=discriminator_parameters)

sess = tf.Session()
init = tf.global_variables_initializer()

sess.run(init)

loss_g_function = []
loss_d_function = []

for epoch in range(200):
    for iteratiion in range(int(len(mnist.train.images)/batch_size)):
        real_batch, _ = mnist.train.next_batch(batch_size)

        _, d_err = sess.run([D_train, D_total_loss], feed_dict = {real_data : real_batch, input : noise(batch_size)})
        _, g_err = sess.run([G_train, G_loss], feed_dict = {input : noise(batch_size)})

    print("Epoch = ", epoch)
    print("D_loss = ", d_err)
    print("G_loss = ", g_err)
    loss_g_function.append(g_err)
    loss_d_function.append(d_err)

# Visualizing
import matplotlib.pyplot as plt

test_noise = noise(1)

plt.subplot(2, 2, 1)
plt.plot(test_noise[0])
plt.title("Noise")
plt.subplot(2, 2, 2)
plt.imshow(np.reshape(sess.run(G, feed_dict = {input : test_noise})[0], [28, 28]))
plt.title("Generated Image")
plt.subplot(2, 2, 3)
plt.plot(loss_d_function, 'r')
plt.xlabel("Epochs")
plt.ylabel("Discriminator Loss")
plt.title("D-Loss")
plt.subplot(2, 2, 4)
plt.plot(loss_g_function, 'b')
plt.xlabel("Epochs")
plt.ylabel("Generator Loss")
plt.title("G_Loss")
plt.show()

我试过lr = 0.001lr = 0.0001lr = 0.00003

这是我的结果:https://imgur.com/a/6KUnO1H

可能是什么原因?我的权重初始化是从正态分布中随机抽取的。另外,请检查损失函数,它们是否正确?

【问题讨论】:

  • 我不知道这是否是您的问题,但sigmoid_cross_entropy_with_logitsalready 已计算 sigmoid,因此您无需在输出中计算它们。这当然没有帮助。
  • 试过了。还是不行。 G 变为 0.0,D 继续增加。
  • 也许您的生成器只是立即超过了鉴别器?每隔几个时期将生成器设置为不可训练可能会有用吗?
  • 尝试了 50 个 epoch 和 20 个 epoch 用于 D 和 100 个 epoch 和 80 个 epoch 用于 D。一旦 G 开始,D 就开始爆炸。结果:imgur.com/hYOgTUF
  • 这不是一个真正的编程问题。您的问题更适合交叉验证

标签: python tensorflow machine-learning neural-network gradient-descent


【解决方案1】:

问题:


只有一层:

hl1 = tf.add(tf.matmul(x, weights['hl1']), biases['hl1'])    
ol = tf.nn.sigmoid(tf.add(tf.matmul(hl1, weights['ol']), biases['ol']))

为鉴别器和生成器定义的上述网络没有为第一层定义激活。这实际上意味着网络只是一层:y = act(w2(x*w1+b1)+b2) = act(x*w+b)


Sigmoid 应用了两次

ol = tf.nn.sigmoid(tf.add(tf.matmul(hl1, weights['ol']) ...
D_real_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(...)

如 cmets 中所述,激活应用了两次。


权重初始化:

tf.Variable(tf.random_normal([784, 200]))

在 sigmoid 激活的情况下,如果权重很大,梯度会很小,这意味着权重实际上不会改变值。 (更大的 w + 非常小的 delta(w))。可能是当我运行上述代码时,损失似乎没有太大变化的原因。最好采用行业最佳实践并使用以下内容:xavier_initializer()


动态范围不一致: generator 的输入在 [-1, 1] 的动态范围内,它乘以 [-1, 1] 的权重,但输出到 [0 1] 范围。这并没有错,一个bias可以学习映射输出范围。但最好使用激活层,它像tanh 一样输出 [-1, 1],这样网络可以更快地学习。如果tanh 被用作generator 的激活,那么输入到descriminator 的图像需要缩放到[-1 1] 以保证训练的一致性。


通过上述更改,您可以获得类似于:

上面的网络非常简单,输出质量不是很好。我故意不改变复杂性来找出一个简单的网络可以得到什么样的输出。

您可以构建更大的网络(包括 CNN)并尝试最近的 GAN 模型以获得更好的质量结果。


上面的复现代码可以从here获取。

【讨论】:

  • 天哪,它成功了!非常感谢你。我会在 14 小时后奖励你赏金,因为在此之前 stackoverflow 不允许。我经常发现,在大多数情况下,它的杂项实践会产生最大的不同。如果可能的话,请告诉我我可以学习它们的任何资源。谢谢。
  • 没错,实践最重要。回答 stackoverflow 问题是一种方法。
  • 第 81 行 real_batch = 2*real_batch - 1. 为什么要添加这个?
  • 正如我在上一节中所说,生成器的输出是 tanh,它输出 [-1,1],这是作为假数据馈送到鉴别器的,所以真实数据也应该在这个范围,上面将 mnist 转换为 [-1,1]
  • 部分解释:Dynamic range inconsistencies
猜你喜欢
  • 2020-05-05
  • 2020-02-28
  • 2019-12-22
  • 2021-11-18
  • 2022-12-23
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
相关资源
最近更新 更多