我在Tensorflow中实现了一个Generative Adversarial Network。在测试期间,如果我使用我在训练期间使用的相同batch_size生成它们,则生成的图像非常好(64);如果我一次生成一个图像,结果很糟糕。
可能的原因可能是2:
这是我的代码:
from tensorflow.contrib.layers.python.layers import batch_norm
def conc(x, y):
"""Concatenate conditioning vector on feature map axis."""
x_shapes = x.get_shape()
y_shapes = y.get_shape()
x0 = tf.shape(x)[0]
x1 = x_shapes[1].value
x2 = x_shapes[2].value
y3 = y_shapes[3].value
return tf.concat([x, y * tf.ones(shape=(x0,x1,x2,y3))], 3)
def batch_normal(input, scope="scope", reuse=False):
return batch_norm(input, epsilon=1e-5, decay=0.9, scale=True, scope=scope, reuse=reuse, updates_collections=None)
def generator(z_var, y):
y_dim = y.get_shape()[1].value
z_var = tf.concat([z_var, y], 1)
d1 = tf.layers.dense(z_var, 1024,
kernel_initializer=tf.random_normal_initializer(stddev=0.02),
name='gen_fc1')
d1 = tf.nn.relu(batch_normal(d1, scope='gen_bn1'))
# add the second layer
d1 = tf.concat([d1, y], 1)
d2 = tf.layers.dense(d1, 7 * 7 * 128,
kernel_initializer=tf.random_normal_initializer(stddev=0.02),
name='gen_fc2')
d2 = tf.nn.relu(batch_normal(d2, scope='gen_bn2'))
d2 = tf.reshape(d2, [-1, 7, 7, 128])
y = tf.reshape(y, shape=[-1, 1, 1, y_dim])
d2 = conc(d2, y)
deconv1 = tf.layers.conv2d_transpose(d2, 64, (4, 4), strides=(2, 2), padding='same',
kernel_initializer=tf.random_normal_initializer(stddev=0.02),
name='gen_deconv1')
d3 = tf.nn.relu(batch_normal(deconv1, scope='gen_bn3'))
d3 = conc(d3, y)
deconv2 = tf.layers.conv2d_transpose(d3, 1, (4, 4), strides=(2, 2), padding='same',
kernel_initializer=tf.random_normal_initializer(stddev=0.02),
name='gen_deconv2')
return tf.nn.sigmoid(deconv2)
答案 0 :(得分:3)
实际上问题在于批量标准化。批量标准化有两个阶段:培训和测试(推理)。在训练阶段,批量标准化使用批次统计(平均值和标准偏差)进行标准化,而在测试阶段,它使用从空洞数据集收集的统计数据。这个平均统计数据是在培训阶段使用移动平均线收集的(使用decay
参数的地方)。
为了区分这两个阶段,layers.batch_norm
有一个名为is_training
的参数,在培训期间应设置为True
,在推理时设置为False
。最简单的方法是使用类型为placeholder
的{{1}}。
所以你应该这样做:
tf.bool
然后,在训练时:
is_training = tf.placeholder(tf.bool)
# some code here
output = batch_norm(input,
epsilon=1e-5,
decay=0.9,
scale=True,
scope=scope,
reuse=reuse,
updates_collections=None,
is_training=is_training)
推论:
feed_dict = {..., is_training: True, ...}
答案 1 :(得分:1)
您可能有其他错误,但批量规范化肯定是一个大问题。
批量标准化计算每层的所有变量的均值和方差,以进行标准化。这意味着作为变量的实际均值和方差的代理,意味着在完整群体而不是子集(小批量)上估计的均值和方差。如果你的小批量足够大,近似的均值和方差足够接近真实的那些,但如果你的小批量中只有一个例子,那么均值和方差的估计显然是灾难性的。
如何解决这个问题,即在完成训练后,您可以从输入的大型子集(大于小批量)计算所有模型变量的均值和方差。然后,您(以某种方式)在批量标准化层中插回这些值,并关闭小批量的均值和方差的计算。这是非常重要的,但我认为你使用的任何库都可以解决这个问题。如果一个库无法处理这个问题,那么它就没用了,因为训练有素的模型永远不会被使用(除非你像你一样在迷你批次上评估它)。
我在快速搜索后在网上找到了此tutorial。它可能会被弃用,可能会有更好的。