BN使用方法

本文转载:https://blog.csdn.net/m0_37987687/article/details/80241893

                    https://blog.csdn.net/heiheiya/article/details/81000756 

                    https://blog.csdn.net/candy_gl/article/details/79551149 

1.原理

公式如下:

y=γ(x-μ)/σ+β

其中x是输入,y是输出,μ是均值,σ是方差,γ和β是缩放(scale)、偏移(offset)系数。

一般来讲,这些参数都是基于channel来做的,比如输入x是一个16*32*32*128(NWHC格式)的feature map,那么上述参数都是128维的向量。其中γ和β是可有可无的,有的话,就是一个可以学习的参数(参与前向后向),没有的话,就简化成y=(x-μ)/σ。而μ和σ,在训练的时候,使用的是batch内的统计值,测试/预测的时候,采用的是训练时计算出的滑动平均值。

 

2.tensorflow中使用

tensorflow中batch normalization的实现主要有下面三个:

tf.nn.batch_normalization

tf.nn.batch_normalization(x,mean,variance,offset,scale,variance_epsilon,name=None)
x:input
mean:样本均值
variance:样本方差
offset:样本偏移(相加一个转化值)
scale:缩放(默认为1)
variance_epsilon:为了避免分母为0,添加的一个极小值

tf.layers.batch_normalization

tf.layers.batch_normalization(
    inputs,
    axis=-1,
    momentum=0.99,
    epsilon=0.001,
    center=True,
    scale=True,
    beta_initializer=tf.zeros_initializer(),
    gamma_initializer=tf.ones_initializer(),
    moving_mean_initializer=tf.zeros_initializer(),
    moving_variance_initializer=tf.ones_initializer(),
    beta_regularizer=None,
    gamma_regularizer=None,
    beta_constraint=None,
    gamma_constraint=None,
    training=False,
    trainable=True,
    name=None,
    reuse=None,
    renorm=False,
    renorm_clipping=None,
    renorm_momentum=0.99,
    fused=None,
    virtual_batch_size=None,
    adjustment=None

)

其中参数解释

inputs:输入Tensor。

axis:整数,应该归一化(通常是特征轴)。例如,在一个data_format="channels_first"的Convolution2D layer之后,BatchNormalization设置axis=1。

momentum:moving average。

epsilon:给variance加一个小浮点数以避免除以零。

center:如果为True,则给normalized Tensor添加一个beta offset。如果为False,beta 则忽略。

scale:如果为True,则乘以gamma。如果为False,gamma则不使用。当下一layer是线性的(例如nn.relu)时,它可以被禁用,因为缩放可以由下一layer完成。

beta_initializer:beta的initializer。

gamma_initializer:gamma的initializer。

moving_mean_initializer:moving mean的initializer。

moving_variance_initializer:moving variance的initializer。

beta_regularizer:beta的可选regularizer。

gamma_regularizer:gamma的可选regularizer。

beta_constraint:当beta被一个Optimizer更新后,对其应用一个可选的映射函数(例如,用于实现层权重的范数约束或值约束)。该函数必须将未映射的变量作为输入,并且必须返回映射变量(必须具有相同的形状)。在进行异步分布式训练时,使用约束是不安全的。

gamma_constraint:当gamma被一个Optimizer更新后,对其应用一个可选的映射函数。

training:一个Python布尔值或TensorFlow布尔标量Tensor(例如placeholder)。无论是否在训练模式下返回输出或在预测模式下。注意:确保正确设置此参数,否则训练/预测将无法正常工作。

trainable:布尔值,如果True还将变量添加到图集合中 GraphKeys.TRAINABLE_VARIABLES(请参阅tf.Variable)。

name:String,图层的名称。

reuse:布尔值,是否以同一名称重用前一层的权重。

renorm:是否使用 Batch Renormalization(https://arxiv.org/abs/1702.03275)。这会在训练期间增加额外的变量。对于此参数的任一值,预测都是相同的。

renorm_clipping:一个字典,可以将键'值rmax','rmin','dmax'映射到标量Tensors,用于剪辑renorm correction。校正 (r, d)使用公式corrected_value = normalized_value * r + d,r在[RMIN,RMAX]之间,d为在-dmax,DMAX]之间。如果没有设定,则rmax,rmin,dmax分别设定为inf,0,inf。

renorm_momentum:momentum用于更新moving means和standard deviations与renorm。与momentum不同的是,这会影响训练,既不能太小(会增加噪音)也不能太大(这会产生过时的估计)。请注意,momentum仍然应用于获取预测的均值和方差。

fused:if None或者True,如果可能的话,使用更快,更融合的实现。如果False,请使用系统推荐的实现。

virtual_batch_size:一个整数。默认情况下,virtual_batch_size是None,这表示在整个batch中执行Batch Renormalization。如果 virtual_batch_size不是None,则执行“Ghost Batch Normalization”,创建虚拟sub-batches,每个sub-batches分别进行Batch Renormalization(具有共享的gamma,beta和moving statistics)。必须在执行期间划分实际batch size。

adjustment:一个函数,例如,如果axis == - 1, adjustment = lambda shape: ( tf.random_uniform(shape[-1:], 0.93, 1.07), tf.random_uniform(shape[-1:], -0.1, 0.1)) 。
简单用法:

  1. x_norm = tf.layers.batch_normalization(x, training=training)

tf.contrib.layers.batch_norm

tf.contrib.layers.batch_norm(
    inputs,
    decay=0.999,
    center=True,
    scale=False,
    epsilon=0.001,
    activation_fn=None,
    param_initializers=None,
    param_regularizers=None,
    updates_collections=tf.GraphKeys.UPDATE_OPS,
    is_training=True,
    reuse=None,
    variables_collections=None,
    outputs_collections=None,
    trainable=True,
    batch_weights=None,
    fused=None,
    data_format=DATA_FORMAT_NHWC,
    zero_debias_moving_mean=False,
    scope=None,
    renorm=False,
    renorm_clipping=None,
    renorm_decay=0.99,
    adjustment=None
)

其中参数

1 inputs: 输入

2 decay :衰减系数。合适的衰减系数值接近1.0,特别是含多个9的值:0.999,0.99,0.9。如果训练集表现很好而验证/测试集表现得不好,选择

小的系数(推荐使用0.9)。如果想要提高稳定性,zero_debias_moving_mean设为True

3 center:如果为True,有beta偏移量;如果为False,无beta偏移量

4 scale:如果为True,则乘以gamma。如果为False,gamma则不使用。当下一层是线性的时(例如nn.relu),由于缩放可以由下一层完成,

所以可以禁用该层。

5 epsilon:避免被零除

6 activation_fn:用于激活,默认为线性激活函数

7 param_initializers : beta, gamma, moving mean and moving variance的优化初始化

8 param_regularizers : beta and gamma正则化优化

9 updates_collections :Collections来收集计算的更新操作。updates_ops需要使用train_op来执行。如果为None,则会添加控件依赖项以

确保更新已计算到位。

10 is_training:图层是否处于训练模式。在训练模式下,它将积累转入的统计量moving_mean并 moving_variance使用给定的指数移动平均值 decay。当它不是在训练模式,那么它将使用的数值moving_mean和moving_variance。
11 scope:可选范围variable_scope

注意:训练时,需要更新moving_mean和moving_variance。默认情况下,更新操作被放入tf.GraphKeys.UPDATE_OPS,所以需要添加它们作为依赖项train_op。例如:

  update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)  with tf.control_dependencies(update_ops):    train_op = optimizer.minimize(loss)
可以将updates_collections = None设置为强制更新,但可能会导致速度损失,尤其是在分布式设置中。
 

3.训练

训练的时候需要注意两点,(1)输入参数training=True,(2)计算loss时,要添加以下代码(即添加update_ops到最后的train_op中)。这样才能计算μ和σ的滑动平均(测试时会用到)

 
  1. update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)

  2. with tf.control_dependencies(update_ops):

  3. train_op = optimizer.minimize(loss)

 

4.测试

测试时需要注意一点,输入参数training=False,其他就没了

 

5.预测

预测时比较特别,因为这一步一般都是从checkpoint文件中读取模型参数,然后做预测。一般来说,保存checkpoint的时候,不会把所有模型参数都保存下来,因为一些无关数据会增大模型的尺寸,常见的方法是只保存那些训练时更新的参数(可训练参数),如下:

 
  1. var_list = tf.trainable_variables()

  2. saver = tf.train.Saver(var_list=var_list, max_to_keep=5)

 

但使用了batch_normalization,γ和β是可训练参数没错,μ和σ不是,它们仅仅是通过滑动平均计算出的,如果按照上面的方法保存模型,在读取模型预测时,会报错找不到μ和σ。更诡异的是,利用tf.moving_average_variables()也没法获取bn层中的μ和σ(也可能是我用法不对),不过好在所有的参数都在tf.global_variables()中,因此可以这么写:

 
  1. var_list = tf.trainable_variables()

  2. g_list = tf.global_variables()

  3. bn_moving_vars = [g for g in g_list if 'moving_mean' in g.name]

  4. bn_moving_vars += [g for g in g_list if 'moving_variance' in g.name]

  5. var_list += bn_moving_vars

  6. saver = tf.train.Saver(var_list=var_list, max_to_keep=5)

按照上述写法,即可把μ和σ保存下来,读取模型预测时也不会报错,当然输入参数training=False还是要的。

注意上面有个不严谨的地方,因为我的网络结构中只有bn层包含moving_mean和moving_variance,因此只根据这两个字符串做了过滤,如果你的网络结构中其他层也有这两个参数,但你不需要保存,建议使用诸如bn/moving_mean的字符串进行过滤。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值