【问题标题】:Tensorflow - Prediction output dependent on batch sizeTensorflow - 取决于批量大小的预测输出
【发布时间】:2018-01-27 13:45:47
【问题描述】:

我在 Tensorflow 中实现了一个生成对抗网络。在测试期间,如果我使用与训练期间相同的 batch_size 生成图像(64),则生成的图像非常好;如果我一次生成一张图像,结果会很糟糕。

可能的原因可能是2:

  • 批量标准化?
  • 错误使用 tf.shape 获取动态批量大小

这是我的代码:

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)

【问题讨论】:

  • 你找到问题了吗?

标签: python tensorflow deep-learning batch-normalization


【解决方案1】:

问题实际上在于批量标准化。批量标准化有两个阶段:训练和测试(推理)。在训练阶段,批量归一化使用批量统计数据(均值和标准差)进行归一化,而在测试阶段,它使用从孔数据集收集的统计数据。此平均统计数据是在训练阶段使用移动平均值收集的(使用 decay 参数)。

为了区分这两个阶段,layers.batch_norm 具有名为 is_training 的参数,在训练期间应设置为 True,在推理时应设置为 False。最简单的方法是使用placeholder 类型为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, ...}

关于推理:

feed_dict = {..., is_training: False, ...}

【讨论】:

  • 谢谢 Dmitriy,实际上我在训练期间使用了一个占位符(为训练设置为 true,为验证设置为 false),在预测期间使用了一个常量=false。但是发生的情况是,预测期间的准确率下降到 20%(即使批量大小相同!),而在训练/验证时为 99%
  • 你的训练/测试时间有什么不同?您是使用相同的图表/会话,还是创建新的?
  • 训练完成后我保存模型。在测试时,我使用另一个会话并恢复模型
【解决方案2】:

您可能还有其他错误,但批量标准化在这里肯定是一个大问题。

批量归一化计算每一层所有变量的均值和方差以进行归一化。这意味着作为变量的真实均值和方差的代理,这意味着在整个总体而不是子集(小批量)上估计的均值和方差。如果您的 mini-batch 足够大,则近似的均值和方差与真实值足够接近,但如果您的 mini-batch 中只有一个示例,则均值和方差的估计显然是灾难性的。

解决这个问题的方法是,在完成训练后,您确实会从输入的某个大子集(大于小批量)计算所有模型变量的均值和方差。然后(以某种方式)将这些值插入批量标准化层并关闭小批量的均值和方差计算。这是相当重要的事情,但我假设您使用的任何库都可以处理这个问题。如果一个库不能处理这个问题,那么它就毫无用处,因为训练过的模型永远不会被使用(除非你也像你一样在小批量上评估它)。

经过快速搜索,我在网上找到了这个tutorial。它可能已被弃用,可能会有更好的。

【讨论】:

    猜你喜欢
    • 2018-02-21
    • 2016-09-22
    • 2018-06-27
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 2018-09-19
    • 2019-06-24
    • 1970-01-01
    相关资源
    最近更新 更多