Batch Normalization层

 

1. 两种数据分析常用的标准化预处理方法

a. min-max归一化

将原始数据映射到[0,1]区间上。

b. z-score标准化

将原始数据处理为均值为0,方差为1的正态分布。

标准化的作用:

消除数据分析过程中不同样本之间的差异(量纲的差异)

标准化代码:

import numpy as np

x1 = np.array([-1,-2,-3,-4,-5])
x2 = np.array([-100,-200,-300,-400,-500])

# min-max标准化  将数组转化为[0,1]区间
def min_max_norm(x):
    x_min = np.min(x)
    x_max = np.max(x)
    return (x-x_min)/(x_max-x_min)

# z-score标准化  将数组转化为正态分布
def z_score_norm(x):
    x_mean = np.mean(x)
    x_std = np.std(x)
    return (x-x_mean)/(x_std+0.0001)

# 消除量纲对数据分析结果的影响
print("the result of min-max norm is ", min_max_norm(x1))
print("the result of min-max norm is ", min_max_norm(x2))

print("the result of z-score norm is ", z_score_norm(x1))
print("the result of z-score norm is ", z_score_norm(x2))

2. 批标准化作用

a. 提升模型的泛化性能

原因:当训练集和测试集分布稍有不同时,由于神经网络中非线性的激活函数导致输入的分布发生了变化,神经网络越深,此分布差异的变化会被放大,所以当用测试集测试此网络时,由于分布的差异被放大,所以泛化性能会降低。此时应用Batch Normalization约束各层分布则可以提高模型的泛化性能。

b. 批量标准化使得激活函数分布在更加适合的区间内(线性区间或非线性区间),加快网络梯度更新,从而加快了收敛速度。

c. 破坏了数据的原有分布,在一定程度上缓解了过拟合。

3. 批标准化公式

Batch Normalization层_第1张图片

Batch Normalization层_第2张图片

       首先,对mini-batch的输入计算均值与方差(训练过程:对mini-batch特征图对应通道所有特征页进行均值和方差的计算,即可获得通道数个均值和方差;测试过程:训练过程所有mini-batch计算的均值和方差的平均值);然后,对输入标准化操作(均值为0,方差为1的正态分布);最后,将此标准正态分布进行平移和缩放,调整为更加适合的分布(保证模型表示能力不因为标准化而下降)。

批标准化前向和反向传播训练过程:

Batch Normalization层_第3张图片

a. 为什么已经标准化后还要进行平移和缩放?是否会导致分布并没有发生改变?

        因为gamma和belta是通过反向传播学习获得的可减少损失的分布参数,若满足,则恢复为输入的分布;若不满足,则将调整输入分布为新的分布。正是因为批标准化操作可改变输入分布,又可恢复为输入分布,才保证了模型的性能不会下降。如果没有平移和缩放的操作,则将输入都调整为均值为0,方差为1的标准分布,若使用ReLU的激活函数,将导致输出一半为0,这是不合理的。

 

4. 代码实现

import tensorflow as tf

# 当前层特征图维度
img_shape = [2, 8, 8, 3]
# 初始化当前层权重
w_l = tf.Variable(tf.random_normal(img_shape))
axis = list(range(len(img_shape) - 1))
# 计算每页特征图的均值和方差
w_mean, w_var = tf.nn.moments(w_l, axis)
# 初始化缩放和平移
scale = tf.Variable(tf.ones([3]))
offset = tf.Variable(tf.zeros([3]))
variance_epsilon = 0.001
# 调用API
w_l = tf.nn.batch_normalization(w_l, w_mean, w_var, offset, scale, variance_epsilon)
# 公式实现
w_l_ = (w_l - w_mean) / tf.sqrt(w_var + variance_epsilon)
w_l_ = w_l_ * scale + offset

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    print(sess.run(w_l_))
    print(sess.run(w_l))

高级API

import tensorflow.contrib.slim as slim

z = slim.batch_norm(inputs=input)

参考资料:

1. 代码参考博客:https://blog.csdn.net/fontthrone/article/details/76652772

2. BN层:https://kratzert.github.io/2016/02/12/understanding-the-gradient-flow-through-the-batch-normalization-layer.html

你可能感兴趣的:(计算机视觉)