神经网络在进行训练时,主要是用来学习数据的分布规律,如果数据的训练部分和测试部分分布不一样,那么网络的泛化能力会变得非常差.而且对于训练的数据,每批分布也是不一样的,那么网络在迭代的过程中也要学习和适应不同的分布.这会大大降低网络的训练速度.此外,数据的分布对于激活函数来说也非常重要,有时数据分布范围太大不利于利用激活函数的非线性特性,比如激活函使用Sigmoid函数时,会导致训练时出现饱和的问题。而批量归一化就是为了缓解这个问题提出的。在实际应用中,批量归一化的收敛非常快,并且具有很强的泛化能力,某种情况下完全可以替代正则化和弃权。
一 批量归一化函数
归一化算法可以描述为:
其中xi是batch_size样本中的第i个样本,μB是求得的每个特征均值,σB2是求得每个特征的方差。
1.TensorFlow中自带BN函数的定义:
def batch_normalization(x,
mean,
variance,
offset,
scale,
variance_epsilon,
name=None):
各个参数的说明如下:
- x:代表任意维度的输入张量。
- mean:代表样本的均值。
- variance:代表样本的方差。
- offset:代表偏移,即相加一个转化值,也是公式中的beta。
- scale:代表缩放,即乘以一个转化值,也是公式中的gamma。
- variance_epsilon:是为了避免分母为0的情况下,给分母加上的一个极小值,默认即可。
- name:名称。
要想使用这个整数,必须由另一个函数配合使用,tf.nn.moments,由它来计算均值和方差,然后就可以使用BN了。
2.tf.nn.moment()函数的定义如下:
def moments(x, axes, shift=None, name=None, keep_dims=False):
- x:输入张量。
- axes:指定沿哪个轴计算平均值和方差。
- shift:A `Tensor` containing the value by which to shift the data for numerical stability, or `None` in which case the true mean of the data is used as shift. A shift close to the true mean provides the most numerically stable results.
- name:名称。
- keep_dims:是否保留维度,即形状是否和输入一样。
有了以上两个函数还不够,因为如果使用tf.nn.moment()函数计算均值和方差,我们需要保存每批次训练的均值和方差,然后求平均。为了有更好的效果,我们通常使