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

TensorFlow中的三维卷积批量归一化

钱浩荡
2023-03-14

我正在实现一个依赖于3D卷积的模型(对于类似于动作识别的任务),我想使用批量规范化(参见

下面的代码引用了TensorFlow r0.12,它显式地引用了变量——我的意思是我没有使用tf。承包商。学习tf以外的内容。承包商。图层。batch\u norm()函数。我这样做是为了更好地理解事情是如何运作的,并且有更多的实现自由度(例如,变量摘要)。

我将通过首先编写完全连接层的示例,然后编写2D卷积,最后编写3D卷积,顺利地讨论3D卷积情况。在查看代码时,如果您可以检查是否所有操作都正确,那就太好了-代码运行了,但我不能百分之百确定我应用批处理规范化的方式。我以一个更详细的问题结束这篇文章。

import tensorflow as tf

# This flag is used to allow/prevent batch normalization params updates
# depending on whether the model is being trained or used for prediction.
training = tf.placeholder_with_default(True, shape=())
# Input.
INPUT_SIZE = 512
u = tf.placeholder(tf.float32, shape=(None, INPUT_SIZE))

# FC params: weights only, no bias as per [Ioffe & Szegedy 2015].
FC_OUTPUT_LAYER_SIZE = 1024
w = tf.Variable(tf.truncated_normal(
    [INPUT_SIZE, FC_OUTPUT_LAYER_SIZE], dtype=tf.float32, stddev=1e-1))

# Layer output with no activation function (yet).
fc = tf.matmul(u, w)

# Batch normalization.
fc_bn = tf.contrib.layers.batch_norm(
    fc,
    center=True,
    scale=True,
    is_training=training,
    scope='fc-batch_norm')

# Activation function.
fc_bn_relu = tf.nn.relu(fc_bn)
print(fc_bn_relu)  # Tensor("Relu:0", shape=(?, 1024), dtype=float32)
# Input: 640x480 RGB images (whitened input, hence tf.float32).
INPUT_HEIGHT = 480
INPUT_WIDTH = 640
INPUT_CHANNELS = 3
u = tf.placeholder(tf.float32, shape=(None, INPUT_HEIGHT, INPUT_WIDTH, INPUT_CHANNELS))

# CNN params: wights only, no bias as per [Ioffe & Szegedy 2015].
CNN_FILTER_HEIGHT = 3  # Space dimension.
CNN_FILTER_WIDTH = 3  # Space dimension.
CNN_FILTERS = 128
w = tf.Variable(tf.truncated_normal(
    [CNN_FILTER_HEIGHT, CNN_FILTER_WIDTH, INPUT_CHANNELS, CNN_FILTERS],
    dtype=tf.float32, stddev=1e-1))

# Layer output with no activation function (yet).
CNN_LAYER_STRIDE_VERTICAL = 1
CNN_LAYER_STRIDE_HORIZONTAL = 1
CNN_LAYER_PADDING = 'SAME'
cnn = tf.nn.conv2d(
    input=u, filter=w,
    strides=[1, CNN_LAYER_STRIDE_VERTICAL, CNN_LAYER_STRIDE_HORIZONTAL, 1],
    padding=CNN_LAYER_PADDING)

# Batch normalization.
cnn_bn = tf.contrib.layers.batch_norm(
    cnn,
    data_format='NHWC',  # Matching the "cnn" tensor which has shape (?, 480, 640, 128).
    center=True,
    scale=True,
    is_training=training,
    scope='cnn-batch_norm')

# Activation function.
cnn_bn_relu = tf.nn.relu(cnn_bn)
print(cnn_bn_relu)  # Tensor("Relu_1:0", shape=(?, 480, 640, 128), dtype=float32)
# Input: sequence of 9 160x120 RGB images (whitened input, hence tf.float32).
INPUT_SEQ_LENGTH = 9
INPUT_HEIGHT = 120
INPUT_WIDTH = 160
INPUT_CHANNELS = 3
u = tf.placeholder(tf.float32, shape=(None, INPUT_SEQ_LENGTH, INPUT_HEIGHT, INPUT_WIDTH, INPUT_CHANNELS))

# CNN params: wights only, no bias as per [Ioffe & Szegedy 2015].
CNN3D_FILTER_LENGHT = 3  # Time dimension.
CNN3D_FILTER_HEIGHT = 3  # Space dimension.
CNN3D_FILTER_WIDTH = 3  # Space dimension.
CNN3D_FILTERS = 96
w = tf.Variable(tf.truncated_normal(
    [CNN3D_FILTER_LENGHT, CNN3D_FILTER_HEIGHT, CNN3D_FILTER_WIDTH, INPUT_CHANNELS, CNN3D_FILTERS],
    dtype=tf.float32, stddev=1e-1))

# Layer output with no activation function (yet).
CNN3D_LAYER_STRIDE_TEMPORAL = 1
CNN3D_LAYER_STRIDE_VERTICAL = 1
CNN3D_LAYER_STRIDE_HORIZONTAL = 1
CNN3D_LAYER_PADDING = 'SAME'
cnn3d = tf.nn.conv3d(
    input=u, filter=w,
    strides=[1, CNN3D_LAYER_STRIDE_TEMPORAL, CNN3D_LAYER_STRIDE_VERTICAL, CNN3D_LAYER_STRIDE_HORIZONTAL, 1],
    padding=CNN3D_LAYER_PADDING)

# Batch normalization.
cnn3d_bn = tf.contrib.layers.batch_norm(
    cnn3d,
    data_format='NHWC',  # Matching the "cnn" tensor which has shape (?, 9, 120, 160, 96).
    center=True,
    scale=True,
    is_training=training,
    scope='cnn3d-batch_norm')

# Activation function.
cnn3d_bn_relu = tf.nn.relu(cnn3d_bn)
print(cnn3d_bn_relu)  # Tensor("Relu_2:0", shape=(?, 9, 120, 160, 96), dtype=float32)

我想确定的是上面的代码是否完全实现了[Ioffe中描述的批处理规范化

对于卷积层,我们还希望规范化遵循卷积特性,以便以相同的方式规范化位于不同位置的同一特征图的不同元素。为了实现这一点,我们在一个小型批处理中,在所有位置联合规范化所有激活。[…]Alg公司。2进行了类似的修改,以便在推理过程中,BN变换对给定特征映射中的每个激活应用相同的线性变换。

更新我想上面的代码对于3D conv情况也是正确的。事实上,当我定义我的模型时,如果我打印所有可训练变量,我还会看到beta和gamma变量的预期数量。例如:

Tensor("conv3a/conv3d_weights/read:0", shape=(3, 3, 3, 128, 256), dtype=float32)
Tensor("BatchNorm_2/beta/read:0", shape=(256,), dtype=float32)
Tensor("BatchNorm_2/gamma/read:0", shape=(256,), dtype=float32)

这对我来说看起来不错,因为由于BN,每个特征图(总共256个)都会学习一对beta和gamma。

[Ioffe

共有1个答案

孟英锐
2023-03-14

这是一篇关于3D batchnorm的好文章,人们通常没有注意到batchnorm可以应用于任何秩大于1的张量。您的代码是正确的,但我忍不住在这方面添加了一些重要注释:

>

  • “标准”2D batchnorm(接受4D tensor)在tensorflow中可能比3D或更高版本快得多,因为它支持应用一个内核操作的fused\u batch\u norm实现:

    融合的批处理规范将进行批处理规范化所需的多个操作组合到一个内核中。批量定额是一个昂贵的过程,对于某些型号来说,它占了很大比例的操作时间。使用融合批次标准可导致12%-30%的加速。

    GitHub上也存在支持3D过滤器的问题,但最近没有任何活动,目前该问题已关闭未解决。

    虽然最初的论文规定在ReLU激活之前使用batchnorm(这就是您在上面的代码中所做的),但有证据表明,在激活之后使用batchnorm可能更好。以下是Francois Chollet对Keras GitHub的评论:

    。。。我可以保证Christian[Szegedy]最近编写的代码在BN之前应用relu。不过,这偶尔还是一个争论的话题。

    对于任何有兴趣在实践中应用规范化思想的人来说,这一思想的最新研究进展,即权重规范化和层规范化,它们修复了原始batchnorm的某些缺点,例如,它们更适用于LSTM和递归网络。

  •  类似资料:
    • 我是卷积神经网络新手,对特征映射和如何在图像上进行卷积来提取特征有概念。我很高兴知道一些关于在CNN应用批量标准化的细节。 我知道什么是特征图和不同的元素是权重在每一个特征图。但我不能理解什么是位置或空间位置。 我完全不能理解下面的句子“在alg.1中,我们让B是一个特征映射中的所有值的集合,它跨越了一个小批处理的元素和空间位置。” 如果有人能用更简单的术语来解释我,我会很高兴的

    • 我很难理解Tensorflow中批量规范化的实现。为了举例说明,我创建了一个简单的网络,其中包含一个输入节点、一个隐藏节点和一个输出节点,并使用1个批运行,批大小为2。我的输入x由一个标量组成,该标量有2个值(即批大小为2),一个值设置为0,另一个值设置为1。 我运行一个纪元,并写出隐藏层的输出(批处理规范化之前和之后)以及批处理范数移动均值、方差、γ和beta。 这是我的代码: 以下是我运行代码

    • 我用TensorFlow来解决一个多目标回归问题。具体地说,在具有逐像素标记的卷积网络中,输入为图像,标签为“热图”,其中每个像素具有浮点值。更具体地说,每个像素的地面真值标记的下界为零,虽然技术上没有上界,但通常不会大于1e-2。 在不进行批量归一化的情况下,该网络能够给出合理的热图预测。通过批量归一化,网络需要很长时间才能获得合理的损耗值,而它所做的最好的工作就是使每个像素都成为平均值。这是使

    • 请问以下对卷积神经网络中批量归一化的理解是否正确? 如下图所示,均值和方差是使用当前小批量中各个示例生成的相同特征图上的所有单元格计算的,即它们是跨h、w和m轴计算的。

    • 由于其简单性,我将slim框架用于tensorflow。但我想有一个卷积层,既有偏差又有批量规范化。在vanilla tensorflow中,我有: 我将其改写为slim: 但这段代码并没有给conv层添加偏差。那是因为https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/laye