当前位置: 首页 > 知识库问答 >
问题:

如何正确地为TensorFlow中的卷积层创建批量规范化层?

韩涵衍
2023-03-14

我正在查看TensorFlow中的官方批处理规范化层(BN),但它并没有真正解释如何将其用于卷积层。有人知道如何做到这一点吗?特别重要的是,它应用并学习每个特征映射(而不是每个激活)的相同参数。以其他顺序,它应用并学习每个过滤器的BN。

在一个特定的玩具示例中,我想用MNIST上的BN(基本上是2D数据)执行conv2d。因此,我们可以做到:

W_conv1 = weight_variable([5, 5, 1, 32]) # 5x5 filters with 32 filters
x_image = tf.reshape(x, [-1,28,28,1]) # MNIST image
conv = tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='VALID') #[?,24,24,1]
z = conv # [?,24,24,32]
z = BN(z) # [?,24,24,32], essentially only 32 different scales and shift parameters to learn, per filer application
a = tf.nn.relu(z) # [?,24,24,32]

其中,z=BN(z)将BN应用于每个过滤器创建的每个特征。在伪代码中:

x_patch = x[h:h+5,w:w+h,1] # patch to do convolution
z[h,w,f] = x_patch * W[:,:,f] = tf.matmul(x_patch, W[:,:,f]) # actual matrix multiplication for the convolution

我们有一个适当的批处理规范层应用于它(在伪代码中省略重要细节):

z[h,w,f] = BN(z[h,w,f]) = scale[f] * (z[h,w,f]  - mu / sigma) + shift[f]

即对于每个过滤器f我们应用BN。

共有2个答案

薛宜
2023-03-14

下面的例子似乎对我有用:

import numpy as np

import tensorflow as tf


normalizer_fn = None
normalizer_fn = tf.contrib.layers.batch_norm

D = 5
kernel_height = 1
kernel_width = 3
F = 4
x = tf.placeholder(tf.float32, shape=[None,1,D,1], name='x-input') #[M, 1, D, 1]
conv = tf.contrib.layers.convolution2d(inputs=x,
    num_outputs=F, # 4
    kernel_size=[kernel_height, kernel_width], # [1,3]
    stride=[1,1],
    padding='VALID',
    rate=1,
    activation_fn=tf.nn.relu,
    normalizer_fn=normalizer_fn,
    normalizer_params=None,
    weights_initializer=tf.contrib.layers.xavier_initializer(dtype=tf.float32),
    biases_initializer=tf.zeros_initializer,
    trainable=True,
    scope='cnn'
)

# syntheitc data
M = 2
X_data = np.array( [np.arange(0,5),np.arange(5,10)] )
print(X_data)
X_data = X_data.reshape(M,1,D,1)
with tf.Session() as sess:
    sess.run( tf.initialize_all_variables() )
    print( sess.run(fetches=conv, feed_dict={x:X_data}) )

控制台输出:

$ python single_convolution.py
[[0 1 2 3 4]
 [5 6 7 8 9]]
[[[[ 1.33058071  1.33073258  1.30027914  0.        ]
   [ 0.95041472  0.95052338  0.92877126  0.        ]
   [ 0.57024884  0.57031405  0.55726254  0.        ]]]


 [[[ 0.          0.          0.          0.56916821]
   [ 0.          0.          0.          0.94861376]
   [ 0.          0.          0.          1.32805932]]]]
易祯
2023-03-14

重要提示:我在这里提供的链接会影响tf.contrib.layers.batch_norm模块,而不是通常的tf.nn(请参阅下面的评论和帖子)

我没有测试它,但TF希望您使用它的方式似乎记录在卷积2D文档字符串中:

def convolution2d(inputs,
              num_outputs,
              kernel_size,
              stride=1,
              padding='SAME',
              activation_fn=nn.relu,
              normalizer_fn=None,
              normalizer_params=None,
              weights_initializer=initializers.xavier_initializer(),
              weights_regularizer=None,
              biases_initializer=init_ops.zeros_initializer,
              biases_regularizer=None,
              reuse=None,
              variables_collections=None,
              outputs_collections=None,
              trainable=True,
              scope=None):
  """Adds a 2D convolution followed by an optional batch_norm layer.
  `convolution2d` creates a variable called `weights`, representing the
  convolutional kernel, that is convolved with the `inputs` to produce a
  `Tensor` of activations. If a `normalizer_fn` is provided (such as
  `batch_norm`), it is then applied. Otherwise, if `normalizer_fn` is
  None and a `biases_initializer` is provided then a `biases` variable would be
  created and added the activations.

根据这一建议,您应该在conv2d方法调用中添加normalizer\u fn='batch\u norm'

关于功能映射与激活的问题,我的猜测是TF在构建图形时会在conv2d的顶部添加规范化层作为新的“节点”,并且两者都会修改相同的权重变量(在您的示例中是W\u conv1对象)。无论如何,我不会将规范层的任务描述为“学习”,但我不太确定我是否理解你的观点(如果你详细说明,也许我可以尝试进一步帮助)

编辑:仔细查看函数体证实了我的猜测,并解释了如何使用参数normalized\u。从第354行读取:

outputs = nn.conv2d(inputs, weights, [1, stride_h, stride_w, 1],
padding=padding)
if normalizer_fn:
  normalizer_params = normalizer_params or {}
  outputs = normalizer_fn(outputs, **normalizer_params)
else:
  ...etc...

我们看到,保存每一层的相应输出的输出变量被依次覆盖。因此,如果在构建图时给出了一个规格化器fn,则nn的输出。conv2d将被额外的层normalizer\u fn覆盖。这里是发挥规范化器参数作用的地方,它作为kwarg iterable传递给给定的规范化器fn。您可以在此处找到batch\u norm的默认参数,因此将字典传递给normalizer\u参数和您希望更改的参数应该可以做到这一点,如下所示:

normalizer_params = {"epsilon" : 0.314592, "center" : False}

希望有帮助!

 类似资料:
  • 在TensorFlow中执行批量规格化的正确方法是什么?(即,我不想计算连续均值和方差)。我当前的实现基于tf。nn。batch\u normalization(批次规格化),其中x是具有形状的卷积层的输出。[批次大小、宽度、高度、通道数]。我想在通道方面执行批处理规范。 但这种实施的结果非常糟糕。与tensorflow比较。承包商。苗条的batch\u norm显示其票价较低(同样糟糕的培训表现

  • 我正在实现一个依赖于3D卷积的模型(对于类似于动作识别的任务),我想使用批量规范化(参见 下面的代码引用了TensorFlow r0.12,它显式地引用了变量——我的意思是我没有使用tf。承包商。学习tf以外的内容。承包商。图层。batch\u norm()函数。我这样做是为了更好地理解事情是如何运作的,并且有更多的实现自由度(例如,变量摘要)。 我将通过首先编写完全连接层的示例,然后编写2D卷积

  • 但似乎每个tensorflow实现(包括这个和官方的tensorflow实现)都使用(指数)移动平均和方差。 请原谅我,但我不明白为什么。是不是因为使用移动平均值对性能更好?还是纯粹为了计算速度? 参考:原稿

  • 本文向大家介绍使用Tensorflow实现可视化中间层和卷积层,包括了使用Tensorflow实现可视化中间层和卷积层的使用技巧和注意事项,需要的朋友参考一下 为了查看网络训练的效果或者便于调参、更改结构等,我们常常将训练网络过程中的loss、accurcy等参数。 除此之外,有时我们也想要查看训练好的网络中间层输出和卷积核上面表达了什么内容,这可以帮助我们思考CNN的内在机制、调整网络结构或者把

  • 我用一个卷积层建立了一个简单的CNN模型,并用Tensorflow Lite进行了转换。(对于MNIST!!)所以现在我的模型得到8位整数输入,权重也是8位整数。 我想测试从TFLite获得的参数,所以我为推理步骤编写了C代码。 输入图像像素被赋予0到255之间的8位整数,权重在-128到127之间。(偏差是32位整数。)当然,卷积结果由大于255的数字组成。 我检查了这份文件(https://a