理论知识(参照大佬):http://www.javashuo.com/article/p-mjzlbaua-mu.htmlpython
补充知识:ruby
方式1:app
x, mean, variance, offset, scale, variance_epsilon, name=None
):原始接口封装使用 x
·mean moments方法的输出之一
·variance moments方法的输出之一
·offset BN须要学习的参数
·scale BN须要学习的参数
·variance_epsilon 归一化时防止分母为0加的一个常量分布式
实现代码:ide
1 import tensorflow as tf 2 3 # 实现Batch Normalization 4 def bn_layer(x,is_training,name='BatchNorm',moving_decay=0.9,eps=1e-5): 5 # 获取输入维度并判断是否匹配卷积层(4)或者全链接层(2) 6 shape = x.shape 7 assert len(shape) in [2,4] 8 9 param_shape = shape[-1] 10 with tf.variable_scope(name): 11 # 声明BN中惟一须要学习的两个参数,y=gamma*x+beta 12 gamma = tf.get_variable('gamma',param_shape,initializer=tf.constant_initializer(1)) 13 beta = tf.get_variable('beat', param_shape,initializer=tf.constant_initializer(0)) 14 15 # 计算当前整个batch的均值与方差 16 axes = list(range(len(shape)-1)) 17 batch_mean, batch_var = tf.nn.moments(x,axes,name='moments') 18 19 # 采用滑动平均更新均值与方差 20 ema = tf.train.ExponentialMovingAverage(moving_decay) 21 22 def mean_var_with_update(): 23 ema_apply_op = ema.apply([batch_mean,batch_var]) 24 with tf.control_dependencies([ema_apply_op]): 25 return tf.identity(batch_mean), tf.identity(batch_var) 26 27 # 训练时,更新均值与方差,测试时使用以前最后一次保存的均值与方差 28 mean, var = tf.cond(tf.equal(is_training,True),mean_var_with_update, 29 lambda:(ema.average(batch_mean),ema.average(batch_var))) 30 31 # 最后执行batch normalization 32 return tf.nn.batch_normalization(x,mean,var,beta,gamma,eps)
实际上tf.contrib.layers.batch_norm对于tf.nn.moments和tf.nn.batch_normalization进行了一次封装函数
参数:学习
1 inputs: 输入测试
2 decay :衰减系数。合适的衰减系数值接近1.0,特别是含多个9的值:0.999,0.99,0.9。若是训练集表现很好而验证/测试集表现得很差,选择优化
小的系数(推荐使用0.9)。若是想要提升稳定性,zero_debias_moving_mean设为Truespa
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设置为强制更新,但可能会致使速度损失,尤为是在分布式设置中。
实现代码:
1 import tensorflow as tf 2 3 def batch_norm(x,epsilon=1e-5, momentum=0.9,train=True, name="batch_norm"): 4 with tf.variable_scope(name): 5 epsilon = epsilon 6 momentum = momentum 7 name = name 8 return tf.contrib.layers.batch_norm(x, decay=momentum, updates_collections=None, epsilon=epsilon, 9 scale=True, is_training=train,scope=name)
BN通常放哪一层?
BN层的设定通常是按照conv->bn->scale->relu的顺序来造成一个block
训练和测试时 BN的区别???
bn层训练的时候,基于当前batch的mean和std调整分布;当测试的时候,也就是测试的时候,基于所有训练样本的mean和std调整分布
因此,训练的时候须要让BN层工做,而且保存BN层学习到的参数。测试的时候加载训练获得的参数来重构测试集。