我正在实现一个依赖于3D卷积的模型(对于类似于动作识别的任务),我想使用批处理规范化(参见[Ioffe & Szegedy 2015])。我找不到任何关于3D凸体的教程,所以我在这里做一个简短的教程,我想和你一起复习一下。
下面的代码引用了TensorFlow r0.12及其显式实例变量--我的意思是,除了tf.contrib.layers.batch_norm()函数之外,我不使用tf.contrib.layers.batch_norm。我这样做是为了更好地理解事物在幕后是如何工作的,并且有更多的实现自由度(例如,变量摘要)。
我将顺利地获得三维卷积的情况,首先写一个完全连接的层的例子,然后为一个2D卷积,最后为三维的情况。在查看代码时,如果您能够检查所有操作是否正确--代码运行,但我不能100%肯定我应用批处理规范化的方式,这将是很好的。我以一个更详细的问题结束这篇文章。
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=())
全连通(FC)案
# 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)
二维卷积(CNN)层实例
# 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)
三维卷积(CNN3D)层壳
# 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 & Szegedy 2015]中描述的那样。3.2:
对于卷积层,我们还希望归一化服从卷积性质,从而使同一特征映射的不同元素在不同的位置以相同的方式规范化。为了实现这一点,我们联合标准化了所有小型批次中的所有激活,覆盖所有位置。..。阿尔格。2作了类似的修改,使得在推理过程中BN变换对给定特征映射中的每一次激活都应用相同的线性变换。
UPDATE --我想上面的代码对于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,每一个特征图都要学习一对beta和gamma (总共256)。
Ioffe & Szegedy 2015:批量规范化:通过减少内部协变量转移加快深度网络培训
发布于 2017-10-07 05:07:41
这是一篇关于3D批范数的很棒的文章,人们常常没有注意到,批范数可以应用于任何等级大于1的张量。您的代码是正确的,但是我不得不在这里添加一些重要的注释:
fused_batch_norm
的一核运算实现:
融合批处理规范将进行批处理规范化所需的多个操作合并到一个内核中。批处理规范是一个昂贵的过程,对某些模型来说,它占了操作时间的很大一部分。使用融合批处理范数可导致12%-30%的加速比。关于GitHub的一个问题也支持3D过滤器,但目前还没有任何新的活动,目前这个问题还没有解决。
https://stackoverflow.com/questions/41830723
复制