tensorflow正确的batch_norm用法
代码参考这个
有空再写写batch_norm的原理把
- 设置错可能会出现的问题
- 不同batch_size 的测试结果不同(原因是因为,没有在batch_norm使用is_training = true,导致没有使用训练得出的参数值)
- 没有先更新指数加权平均, update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
- 总之按下面设置,感觉tensorflow的一些安排有问题
- 主要关注的点
with tf.name_scope("train_op"):
# fc8_optimizer = tf.train.GradientDescentOptimizer(BASE_LR1) 不能定义太多优化器,内存会爆掉
global_step = tf.train.create_global_step()
learning_rate = tf.train.exponential_decay(
PARAMS.params['model']['baseLR'],
global_step,
4*train_num / BATCH_SIZE,
PARAMS.params['model']['decayLR'])
optimizer = tf.train.AdamOptimizer(learning_rate)
full_train_op = slim.learning.create_train_op(loss_entro_mean,
optimizer,
global_step=global_step)
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
print("BN parameters: ", update_ops)
updates = tf.group(*update_ops)
full_train_op = control_flow_ops.with_dependencies([updates], full_train_op)
网络
with slim.arg_scope([slim.conv2d, slim.fully_connected],
activation_fn = tf.nn.relu,
weights_initializer=tf.truncated_normal_initializer(stddev=0.1),
weights_regularizer=slim.l2_regularizer(0.00001), # 越小惩罚项越重
normalizer_fn=tf.layers.batch_normalization,
normalizer_params={'training': is_training,
'momentum': 0.95}
):
注意:
- 别用slim.batch_norm
batch_norm原理
为什么要使用batch_norm
- 实现每一层的输入归一化
- 改变数据分布-convariable shift
如图所示,假设左边为训练分布,右边为测试分布,绿色为分类线。
此时训练分布的不能用于测试,会分错。纠正错误的方法就是改变分布
- 此外,在学习过程中,层内的z值分布可能会不断变化。使用了BN后,至少方差和均值不变,学习会更稳定,每层可以独立与其他不同的层。
batch_norm的实现
- batch_norm的位置
Z = W T ∗ X Z=W^T*X Z=WT∗X和 A = g ( Z ) A=g(Z) A=g(Z)之间,也就是在激活函数的前面 - 实现方法:
- 归一化:
u = 1 m ∗ ∑ z i u=\frac 1m*\sum z^{i} u=m1∗∑zi
σ 2 = 1 m ∑ ( z ( i ) − u ) 2 \sigma^{2}=\frac 1m\sum({z^{(i)}-u})^2 σ2=m1∑(z(i)−u)2
z n o r m ( i ) = z ( i ) − u σ 2 + ϵ z_{norm}^{(i)}=\frac{z^{(i)}-u}{\sqrt {\sigma^{2}+\epsilon} \quad } znorm(i)=σ2+ϵz(i)−u - 用
γ
\gamma
γ和
β
\beta
β改变分布
z ~ ( i ) = γ z n o r m ( i ) + β \tilde{z}^{(i)} = \gamma z_{norm}^{(i)} + \beta z~(i)=γznorm(i)+β
其中, γ \gamma γ和 β \beta β为学习参数,可训练
- 归一化:
- 如何在测试集中使用BN
因为BN归一化是以mini_batch的形式处理的,但是在测试时。可能需要对每一个样本单独处理,而根据2. 的公式可以看出。单独的 σ \sigma σ和 u u u是没有意义的。因此在测试中可以使用训练值去估计这两个参数。
具体实现可以用指数加权平均和去计算这两个值。
在测试的时候就直接用训练得出的 σ \sigma σ、 u u u、 β \beta β和 γ \gamma γ