gpt4 book ai didi

Tensorflow 和批量归一化,批量大小==1 => 输出全零

转载 作者:行者123 更新时间:2023-11-30 08:32:31 24 4
gpt4 key购买 nike

我有一个关于 BatchNorm(BN 稍后)的理解的问题。

我有一个运行良好的卷积网络,我正在编写测试来检查形状和输出范围。我注意到当我设置batch_size = 1时,我的模型输出零(logits和激活)。

我用 BN 制作了最简单的卷积网络原型(prototype):

输入=> Conv + ReLU => BN => Conv + ReLU => BN => Conv Layer + Tanh

模型通过xavier 初始化进行初始化。我猜想 BN 在训练期间会进行一些需要 Batch_size > 1 的计算。

我在 PyTorch 中发现了一个似乎与此相关的问题:https://github.com/pytorch/pytorch/issues/1381

有人能解释一下吗?对我来说还是有点模糊。

<小时/>

示例运行:

重要提示:此脚本运行需要 Tensorlayer 库:pip install tensorlayer

import tensorflow as tf
import tensorlayer as tl

import numpy as np

def conv_net(inputs, is_training):

xavier_initilizer = tf.contrib.layers.xavier_initializer(uniform=True)
normal_initializer = tf.random_normal_initializer(mean=1., stddev=0.02)

# Input Layers
network = tl.layers.InputLayer(inputs, name='input')

fx = [64, 128, 256, 256, 256]

for i, n_out_channel in enumerate(fx):

with tf.variable_scope('h' + str(i + 1)):

network = tl.layers.Conv2d(
network,
n_filter = n_out_channel,
filter_size = (5, 5),
strides = (2, 2),
padding = 'VALID',
act = tf.identity,
W_init = xavier_initilizer,
name = 'conv2d'
)

network = tl.layers.BatchNormLayer(
network,
act = tf.identity,
is_train = is_training,
gamma_init = normal_initializer,
name = 'batch_norm'
)

network = tl.layers.PReluLayer(
layer = network,
a_init = tf.constant_initializer(0.2),
name ='activation'
)

############# OUTPUT LAYER ###############

with tf.variable_scope('h' + str(len(fx) + 1)):
'''

network = tl.layers.FlattenLayer(network, name='flatten')

network = tl.layers.DenseLayer(
network,
n_units = 100,
act = tf.identity,
W_init = xavier_initilizer,
name = 'dense'
)

'''

output_filter_size = tuple([int(i) for i in network.outputs.get_shape()[1:3]])

network = tl.layers.Conv2d(
network,
n_filter = 100,
filter_size = output_filter_size,
strides = (1, 1),
padding = 'VALID',
act = tf.identity,
W_init = xavier_initilizer,

name = 'conv2d'
)

network = tl.layers.BatchNormLayer(
network,
act = tf.identity,
is_train = is_training,
gamma_init = normal_initializer,
name = 'batch_norm'
)

net_logits = network.outputs

network.outputs = tf.nn.tanh(
x = network.outputs,
name = 'activation'
)

net_output = network.outputs

return network, net_output, net_logits


if __name__ == '__main__':

tf.logging.set_verbosity(tf.logging.DEBUG)

#################################################
# MODEL DEFINITION #
#################################################

PLH_SHAPE = [None, 256, 256, 3]

input_plh = tf.placeholder(tf.float32, PLH_SHAPE, name='input_placeholder')

convnet, net_out, net_logits = conv_net(input_plh, is_training=True)


with tf.Session() as sess:
tl.layers.initialize_global_variables(sess)

convnet.print_params(details=True)

#################################################
# LAUNCH A RUN #
#################################################

for BATCH_SIZE in [1, 2]:

INPUT_SHAPE = [BATCH_SIZE, 256, 256, 3]

batch_data = np.random.random(size=INPUT_SHAPE)

output, logits = sess.run(
[net_out, net_logits],
feed_dict={
input_plh: batch_data
}
)

if tf.logging.get_verbosity() == tf.logging.DEBUG:
print("\n\n###########################")

print("\nBATCH SIZE = %d\n" % BATCH_SIZE)

tf.logging.debug("output => Shape: %s - Mean: %e - Std: %f - Min: %f - Max: %f" % (
output.shape,
output.mean(),
output.std(),
output.min(),
output.max()
))

tf.logging.debug("logits => Shape: %s - Mean: %e - Std: %f - Min: %f - Max: %f" % (
logits.shape,
logits.mean(),
logits.std(),
logits.min(),
logits.max()
))

if tf.logging.get_verbosity() == tf.logging.DEBUG:
print("###########################")

给出以下输出:

###########################

BATCH SIZE = 1

DEBUG:tensorflow:output => Shape: (1, 1, 1, 100) - Mean: 0.000000e+00 - Std: 0.000000 - Min: 0.000000 - Max: 0.000000
DEBUG:tensorflow:logits => Shape: (1, 1, 1, 100) - Mean: 0.000000e+00 - Std: 0.000000 - Min: 0.000000 - Max: 0.000000
###########################


###########################

BATCH SIZE = 2

DEBUG:tensorflow:output => Shape: (2, 1, 1, 100) - Mean: -1.430511e-08 - Std: 0.760749 - Min: -0.779634 - Max: 0.779634
DEBUG:tensorflow:logits => Shape: (2, 1, 1, 100) - Mean: -4.768372e-08 - Std: 0.998715 - Min: -1.044437 - Max: 1.044437
###########################

最佳答案

您可能应该阅读有关批量归一化的解释,例如 this one 。您还可以查看tensorflow's related doc

基本上,有两种方法可以执行batch_norm,并且在处理批量大小为1时都存在问题:

  • 每个像素使用移动均值和方差像素,因此它们是与批处理中每个样本形状相同的张量。这是@layog 的答案中使用的,(我认为)在 the original paper 中使用的。 ,也是最常用的。

  • 在整个图像/特征空间上使用移动均值和方差,因此它们只是形状 (n_channels,) 的向量(秩 1)。

在这两种情况下,您都会:

output = gamma * (input - mean) / sigma + beta

Beta 通常设置为 0,gamma 设置为 1,因为 BN 之后有线性函数。

在训练期间均值方差是在当前批处理中计算的,这会导致问题尺寸 1:

  • 在第一种情况下,您将得到 mean=input,因此 output=0
  • 在第二种情况下,mean 将是所有像素的平均值,因此更好;但如果你的宽度和高度也为 1,那么你会再次得到 mean=input,因此你会得到 output=0

我认为大多数人(以及原始方法)使用第一种方法,这就是为什么你会得到 0 (尽管 TF 文档似乎表明第二种方法也很常见)。您提供的链接中的参数似乎正在考虑第二种方法。

无论如何(无论您使用哪种),对于 BN,只有使用更大的批量大小(例如,至少 10),您才会获得良好的结果。

关于Tensorflow 和批量归一化,批量大小==1 => 输出全零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48320854/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com