矩阵取用的常用方式
在numpy中的nonzero()文章中偶然看到的一个不相关的图,太有用了,就偷来保存下
这几种方式不仅是对矩阵的处理方式,还是很好的取样策略;当矩阵具有它的物理意义时,我们就可以根据物理意义来进行筛选,从而降低计算成本,提高模型性能
Batch Normalization、Layer Normalization
对于这个知识点,比理解如何操作更重要的是明白为什么要使用这两种方式,即动机,以及使用这两种方式的作用
动机
首先来看Batch Normalization。Batch Normalization的提出是基于深度学习中的一个共识:独立同分布的数据的训练效果更好
独立同分布是说,训练集中的每个数据可以看作一个随机变量,不同随机变量之间的关系应该是独立的,且服从相同的分布,那么如何将本来无法独立同分布的数据变成独立同分布呢?可以使用白化(whitening)操作,包括两个步骤:1)独立,去除数据之间的关联性 2)同分布,使得特征具有相同的均值和方差;
然而神经网络的每一层的参数更新,都会导致上层的输入数据在输出时的分布规律发生变化,而且这种差异会随着网络的深度增大而增大,这种现象称为内部变量偏移(Internal Covariate Shift);
举个例子,假如我们在神经网络的每一层都使用了sigmoid函数作为激活函数,那么
f
(
x
)
=
1
1
+
e
(
−
x
)
f(x) = \frac{1}{1+e^{(-x)}}
f(x)=1+e(−x)1,导数为
f
(
x
)
(
1
−
f
(
x
)
)
f(x)(1-f(x))
f(x)(1−f(x)),那么对于
x
=
0
x=0
x=0,导数值为
0.25
0.25
0.25,那么每经过一层sigmoid,导数的值就会缩小
0.25
0.25
0.25,而根据sigmoid的函数图像:
导数越远离
0
0
0,导数就越小,也就是说随着深度的加深,梯度的衰减会非常大,迅速接近
0
0
0,这种现象就是梯度消失
解决方案
Batch Normalization就是从白化的2)同分布出发,希望在每一层之后,都将特征调整为相同的分布,那么具体调整为哪种分布呢?可以看到sigmoid函数中,越靠近 0 0 0,函数越接近线性,所以可以把越来越偏的分布强行拉回到均值为 0 0 0方差为 1 1 1的标准正态分布,从而使得梯度变大,避免梯度消失问题
而Layer Normalization的动机和解决方案与Batch Normalization相差不大,只是为了适应不同结构的数据和网络,在实施细节中会具体谈到
实施细节
Batch Normalization,顾名思义,就是对整个batch进行标准化,假设某一层一个batch中的样本为 B = x 1 , x 2 , . . . , x m B = x_1, x_2, ..., x_m B=x1,x2,...,xm,该层的输出为 y 1 , y 2 , . . . y m y_1, y_2, ... y_m y1,y2,...ym,那么标准化的操作为:
- 计算均值
μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m}\sum_{i=1}^mx_i μB=m1∑i=1mxi - 计算方差
σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_B^2 = \frac{1}{m}\sum_{i=1}^m(x_i-\mu_B)^2 σB2=m1∑i=1m(xi−μB)2 - 标准化
x i ^ = x i − μ B ∣ σ B ∣ \hat{x_i} = \frac{x_i-\mu_B}{|\sigma_B|} xi^=∣σB∣xi−μB - 这种做法会导致网络的表达能力下降,所以我们还要进行一种反变换,增强网络的表达能力,反变换由scale
γ
\gamma
γ(对应均值)和shift
β
\beta
β(对应方差)两个参数组成,两个参数由学习得到:
y i ^ = γ x i ^ + β \hat{y_i} = \gamma \hat{x_i}+\beta yi^=γxi^+β
Batch Normalization在图像处理中比较常见,比如对于不同feature map中相同位置的元素,我们统一进行这种标准化,相当于对具有类似语义含义的输入进行标准化,这种情景对于大多数图像任务来说是合理的,因为网络中的每一层参数的调整,应该是以这种语义含义为原则的
但是我们再来看文本数据,举例:
我是中国人我爱中国
武汉抗疫非常成功0
大家好才是真的好0
人工智能很火000
如果是使用Batch Normalization来处理的话,相当于我们会对相同位置的字进行处理,如:我、武、大、人;然而时序网络的处理原则,应该更倾向于去挖掘每句话中前后文的相关性,所以我们应该以单个句子为处理单位,统一对所有层的输出进行标准化,设时序网络中某个样本的所有时刻的节点输出为 a 1 , a 2 , . . . , a T {a_1, a_2, ..., a_T} a1,a2,...,aT:
- 计算均值
μ = 1 T ∑ i = 1 T a i \mu = \frac{1}{T}\sum_{i=1}^T a_i μ=T1∑i=1Tai - 计算方差
σ = 1 T ∑ i = 1 T ( a i − μ ) 2 \sigma = \frac{1}{T}\sum_{i=1}^T (a_i-\mu)^2 σ=T1∑i=1T(ai−μ)2 - 标准化
a i ^ = a i − μ σ \hat{a_i} = \frac{a_i-\mu}{\sigma} ai^=σai−μ
那么将整个句子进行这种处理的作用是什么呢?时序网络常常有很多层的,每一层的这种标准化,就是为了后面层的稳定(同Batch Normalization的动机),所以层数多的时序网络会更需要Layer Normalization这种方式,比如transformer、Bert等