开启成长之旅!这是我参与「日新方案 2 月更文应战」的第 9 天,点击检查活动概况。
一,数学基础
1.1,概率密度函数
随机变量(random variable)是能够随机地取不同值的变量。随机变量能够是离散的或许接连的。简略起见,本文用大写字母 XX 表明随机变量,小写字母 xx 表明随机变量能够取到的值。例如,x1x_1 和 x2x_2 都是随机变量 XX 或许的取值。随机变量必须伴跟着一个概率散布来指定每个状况的或许性。
概率散布(probability distribution)用来描绘随机变量或一簇随机变量在每一个或许取到的状况的或许性大小。咱们描绘概率散布的办法取决于随机变量是离散的仍是接连的。
当咱们研究的对象是接连型随机变量时,咱们用概率密度函数(probability density function, PDF
)而不是概率质量函数来描绘它的概率散布。
1.2,正态散布
当咱们不知道数据真实散布时运用正态散布的原因之一是,正态散布拥有最大的熵,咱们经过这个假设来施加尽或许少的结构。
实数上最常用的散布便是正态散布(normal distribution),也称为高斯散布 (Gaussian distribution)。
假如随机变量 XX ,遵守方位参数为 \mu、标准参数为 \sigma 的概率散布,且其概率密度函数为:
则这个随机变量就称为正态随机变量,正态随机变量遵守的概率散布就称为正态散布,记作:
假如方位参数 =0\mu = 0,标准参数 =1\sigma = 1 时,则称为标准正态散布,记作:
此刻,概率密度函数公式简化为:
正态散布的数学期望值或期望值 \mu 等于方位参数,决议了散布的方位;其方差 2\sigma^2 的开平方或标准差 \sigma 等于标准参数,决议了散布的幅度。正态散布的概率密度函数曲线呈钟形,常称之为钟形曲线,如下图所示:
可视化正态散布,可直接经过 np.random.normal
函数生成指定均值和标准差的正态散布随机数,然后基于 matplotlib + seaborn
库 kdeplot
函数绘制概率密度曲线。示例代码如下所示:
import seaborn as sns
x1 = np.random.normal(0, 1, 100)
x2 = np.random.normal(0, 1.5, 100)
x3 = np.random.normal(2, 1.5, 100)
plt.figure(dpi = 200)
sns.kdeplot(x1, label="=0, =1")
sns.kdeplot(x2, label="=0, =1.5")
sns.kdeplot(x3, label="=2, =2.5")
#显现图例
plt.legend()
#添加标题
plt.title("Normal distribution")
plt.show()
以上代码直接运行后,输出成果如下图:
当然也能够自己完成正态散布的概率密度函数,代码和程序输出成果如下:
import numpy as np
import matplotlib.pyplot as plt
plt.figure(dpi = 200)
plt.style.use('seaborn-darkgrid') # 主题设置
def nd_func(x, sigma, mu):
"""自定义完成正态散布的概率密度函数
"""
a = - (x-mu)**2 / (2*sigma*sigma)
f = np.exp(a) / (sigma * np.sqrt(2*np.pi))
return f
if __name__ == '__main__':
x = np.linspace(-5, 5)
f = nd_fun(x, 1, 0)
p1, = plt.plot(x, f)
f = nd_fun(x, 1.5, 0)
p2, = plt.plot(x, f)
f = nd_fun(x, 1.5, 2)
p3, = plt.plot(x, f)
plt.legend([p1 ,p2, p3], ["=0,=1", "=0,=1.5", "=2,=1.5"])
plt.show()
二,背景
练习深度神经网络的复杂性在于,由于前面的层的参数会发生改变导致每层输入的散布在练习进程中会发生改变。这又导致模型需求需求较低的学习率和十分谨慎的参数初始化策略,从而减慢了练习速度,并且具有饱满非线性的模型练习起来也十分困难。
网络层输入数据散布发生改变的这种现象称为内部协变量搬运,BN 便是来处理这个问题。
2.1,怎么理解 Internal Covariate Shift
在深度神经网络练习的进程中,由于网络中参数改变而引起网络中间层数据散布发生改变的这一进程被称在论文中称之为内部协变量偏移(Internal Covariate Shift)。
那么,为什么网络中间层数据散布会发生改变呢?
在深度神经网络中,咱们能够将每一层视为对输入的信号做了一次变换(暂时不考虑激活,由于激活函数不会改变输入数据的散布):
其间 WW 和 BB 是模型学习的参数,这个公式涵盖了全连接层和卷积层。
跟着 SGD 算法更新参数,和网络的每一层的输入数据经过公式5的运算后,其 ZZ 的散布一直在改变,因此网络的每一层都需求不断适应新的散布,这一进程就被叫做 Internal Covariate Shift。
而深度神经网络练习的复杂性在于每层的输入遭到前面一切层的参数的影响—因此当网络变得更深时,网络参数的细小改变就会被扩大。
2.2,Internal Covariate Shift 带来的问题
-
网络层需求不断适应新的散布,导致网络学习速度的降低。
-
网络层输入数据容易堕入到非线性的饱满状况并减慢网络收敛,这个影响跟着网络深度的增加而扩大。
跟着网络层的加深,后面网络输入 xx 越来越大,而假如咱们又选用
Sigmoid
型激活函数,那么每层的输入很容易移动到非线性饱满区域,此刻梯度会变得很小甚至接近于 00,导致参数的更新速度就会减慢,从而又会放慢网络的收敛速度。
饱满问题和由此产生的梯度消失通常经过运用批改线性单元激活(ReLU(x)=max(x,0)ReLU(x)=max(x,0)),更好的参数初始化办法和小的学习率来处理。可是,假如咱们能确保非线性输入的散布在网络练习时坚持更安稳,那么优化器将不太或许堕入饱满状况,从而练习也将加速。
2.3,削减 Internal Covariate Shift 的一些尝试
-
白化(Whitening): 即输入线性变换为具有零均值和单位方差,并去相关。
白化进程由于改变了网络每一层的散布,因此改变了网络层中本身数据的表达能力。底层网络学习到的参数信息会被白化操作丢失掉,并且白化核算成本也高。
-
标准化(normalization)
Normalization 操作虽然缓解了
ICS
问题,让每一层网络的输入数据散布都变得安稳,但却导致了数据表达能力的缺失。
三,批量归一化(BN)
3.1,BN 的前向核算
论文中给出的 Batch Normalizing Transform 算法核算进程如下图所示。其间输入是一个考虑一个大小为 mm 的小批量数据 B\cal B。
论文中的公式不太明晰,下面我给出更为明晰的 Batch Normalizing Transform 算法核算进程。
设 mm 表明 batch_size 的大小,nn 表明 features 数量,即样本特征值数量。在练习进程中,针对每一个 batch
数据,BN
进程进行的操作是,将这组数据 normalization
,之后对其进行线性变换,详细算法过程如下:
以上公式乘法都为元素乘,即 element wise
的乘法。其间,参数 ,\gamma,\beta 是练习出来的, \epsilon 是为零防止 B2\sigma_B^2 为 00 ,加的一个很小的数值,通常为1e-5
。公式各个符号解说如下:
符号 | 数据类型 | 数据形状 |
---|---|---|
XX | 输入数据矩阵 | [m, n] |
xix_i | 输入数据第i个样本 | [1, n] |
NN | 经过归一化的数据矩阵 | [m, n] |
nin_i | 经过归一化的单样本 | [1, n] |
B\mu_B | 批数据均值 | [1, n] |
B2\sigma^2_B | 批数据方差 | [1, n] |
mm | 批样本数量 | [1] |
\gamma | 线性变换参数 | [1, n] |
\beta | 线性变换参数 | [1, n] |
ZZ | 线性变换后的矩阵 | [1, n] |
ziz_i | 线性变换后的单样本 | [1, n] |
\delta | 反向传入的差错 | [m, n] |
其间:
能够看出 BN
本质上是做线性变换。
3.2,BN 层怎么作业
在论文中,练习一个带 BN
层的网络, BN
算法过程如下图所示:
在练习期间,咱们一次向网络供给一小批数据。在前向传达进程中,网络的每一层都处理该小批量数据。 BN
网络层按如下办法履行前向传达核算:
图片来历这儿。
留意,图中核算均值与方差的无偏估量办法是吴恩达在 Coursera 上的 Deep Learning 课程上提出的办法:对 train 阶段每个 batch 核算的 mean/variance 选用指数加权均匀来得到 test 阶段 mean/variance 的估量。
在练习期间,它只是核算此 EMA,但不对其履行任何操作。在练习结束时,它只是将该值保存为层状况的一部分,以供在推理阶段运用。
如下图能够展示BN 层的前向传达核算进程数据的 shape
,红色框出来的单个样本都指代单个矩阵,即运算都是在单个矩阵运算中核算的。
图片来历 这儿。
BN 的反向传达进程中,会更新 BN 层中的一切 \beta 和 \gamma 参数。
3.3,练习和推理式的 BN 层
批量归一化(batch normalization)的“批量”两个字,表明在模型的迭代练习进程中,BN 首先核算小批量( mini-batch,如 32)的均值和方差。可是,在推理进程中,咱们只要一个样本,而不是一个小批量。在这种情况下,咱们该怎么取得均值和方差呢?
榜首种办法是,运用的均值和方差数据是在练习进程中样本值的均匀,即:
这种做法会把一切练习批次的 \mu 和 \sigma 都保存下来,然后在最终练习完成时(或做测试时)做下均匀。
第二种办法是运用相似动量的办法,练习时,加权均匀每个批次的值,权值 \alpha 能够为0.9:
推理或测试时,直接运用模型文件中保存的 movi\mu_{mov_{i}} 和 movi\sigma_{mov_{i}} 的值即可。
3.4,试验
BN
在 ImageNet
分类数据集上试验成果是 SOTA
的,如下表所示:
3.5,BN 层的长处
-
BN 使得网络中每层输入数据的散布相对安稳,加速模型练习和收敛速度。
-
批标准化能够提高学习率。在传统的深度网络中,学习率过高或许会导致梯度爆破或梯度消失,以及堕入差的部分最小值。批标准化有助于处理这些问题。经过标准化整个网络的激活值,它能够防止层参数的细小改变跟着数据在深度网络中的传达而扩大。例如,这使 sigmoid 非线性更容易坚持在它们的非饱满状况,这对练习深度 sigmoid 网络至关重要,但在传统上很难完成。
-
BN 答应网络运用饱满非线性激活函数(如 sigmoid,tanh 等)进行练习,其能缓解梯度消失问题。
-
不需求
dropout
和LRN
(Local Response Normalization)层来完成正则化。批标准化供给了相似丢弃的正则化收益,由于经过试验能够观察到练习样本的激活遭到同一小批量样例随机挑选的影响。 -
削减对参数初始化办法的依靠。
参考资料
- 维基百科-正态散布
- Batch Norm Explained Visually — How it works, and why neural networks need it
- 15.5 批量归一化的原理
- Batch Normalization原理与实战