BN的使用

在TensorFlow中,如果我们要使用batch normalization层,可以使用的API有tf.layers.batch_normalization和tf.contrib.layers.batch_norm,如果我们直接使用这两个API构建我们的网络,往往会出现训练的时候网络的表现非常好,而当测试的时候我们将其中的参数is_training设置为False时,网络的表现非常的差。这往往是因为我们训练的时候忽视了一个细节。
方法1:
在tf.contrib.layers.batch_norm的帮助文档中我们看到有以下的文字

Note: when training, the moving_mean and moving_variance need to be updated. By default the update ops are placed in tf.GraphKeys.UPDATE_OPS, so they need to be added as a dependency to the train_op.
也就是说,我们需要在代码运行的过程中手动对moving_mean和moving_variance进行手动更新,代码如下:

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
    train_op = optimizer.minimize(loss)

这一步非常的重要,很多人在训练的时候往往会忽略这一步,导致训练/测试时结果相差巨大。

还有一个方法:需要将is_training改成True。
要注意的地方是,在做测试的时候,如果将is_training改为 False,就会出现测试accuracy很低的现象,需要将is_training改成True。虽然这样能得到高的accuracy,但是明显不合理!!

自己写,用tf.nn.batch_normalization
tensorflow实现:

def batchNorm_layer(inputs, is_training, decay = 1e-5, epsilon = 1e-3):
    scale = tf.Variable(tf.ones(inputs.get_shape()[1:].as_list()))
    beta = tf.Variable(tf.zeros(inputs.get_shape()[1:].as_list()))
    pop_mean = tf.Variable(tf.zeros(inputs.get_shape()[1:].as_list()), trainable=False)
    pop_var = tf.Variable(tf.ones(inputs.get_shape()[1:].as_list()), trainable=False)

    if is_training:
        batch_mean, batch_var = tf.nn.moments(inputs, [0])
        train_mean = tf.assign(pop_mean, pop_mean * decay + batch_mean * (1 - decay))
        train_var = tf.assign(pop_var, pop_var * decay + batch_var * (1 - decay))
        with tf.control_dependencies([train_mean, train_var]):
            return tf.nn.batch_normalization(inputs, batch_mean, batch_var, beta, scale, epsilon)
    else:
        return tf.nn.batch_normalization(inputs, pop_mean, pop_var, beta, scale, epsilon)
### 结合使用 tanh 激活函数和批量归一化(BN) 在深度学习中,tanh 激活函数与批量归一化(Batch Normalization, BN)可以有效结合以提升模型性能。以下是关于两者联合使用的具体说明: #### 1. 批量归一化的意义 批量归一化是一种用于加速神经网络训练的技术,通过在网络的每一层输入上应用标准化操作来减少内部协变量偏移现象[^3]。它能够将每一批次的数据调整至均值为0、方差为1的标准正态分布范围,从而使激活值更稳定并缓解梯度消失或梯度爆炸问题。 #### 2. tanh 激活函数的特点 tanh 是一种双极型非线性激活函数,在理论上具有良好的性质,其输出范围位于 [-1, 1] 之间。然而,当未经适当预处理的数据直接送入含有 tanh 的深层网络时,容易导致激活值进入饱和区域[-1 或者接近于-1;以及1或者接近于1],这会使得梯度变得非常小甚至趋于零,进而阻碍参数更新过程正常进行[^4]。 #### 3. 联合使用方法 为了克服上述挑战,可以在每次前向传播之前先执行批量归一化步骤再施加tanh变换: ```python import torch.nn as nn class TanhWithBN(nn.Module): def __init__(self): super(TanhWithBN, self).__init__() self.bn = nn.BatchNorm1d(num_features=...) # 根据实际需求设置num_features self.tanh = nn.Tanh() def forward(self, x): normalized_x = self.bn(x) # 对x做批量归一化 activated_x = self.tanh(normalized_x) # 应用tanh激活函数 return activated_x ``` 在此实现中,`nn.BatchNorm1d`负责完成批量归一化工作,而 `nn.Tanh` 则定义了随后要被调用的激活功能。注意这里的维度需依据具体情况设定好。 另外值得注意的是虽然经过批量归一化之后数据已经被规范化但是为了让模型拥有足够的表达能力batchnorm还引入了两个可学习参数γ(缩放因子scale factor) 和β(位移offset),允许转换后的表示重新映射回适合当前任务的空间内。 因此最终得到的结果既保留了原始信号特性又避免落入极端状态从而促进整个系统的稳健收敛表现良好[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值