转载请注明出处:https://thinkgamer.blog.csdn.net/article/details/101026786
博主微博:http://weibo.com/234654758
Github:https://github.com/thinkgamer
公众号:搜索与推荐Wiki
引言
神经网络中的网络优化和正则化问题介绍主要分为一,二,三,四篇进行介绍。
- 第一篇包括
- 网络优化和正则化概述
- 优化算法介绍
- 第二篇包括
- 参数初始化
- 数据预处理
- 逐层归一化
- 第三篇包括
- 超参数优化
- 第四篇包括
- 网络正则化
参数初始化
对称权重现象
在上一篇文章中我们提到神经网络中的参数学习是基于梯度下降的,而梯度下降需要赋予一个初始的参数,所以这个参数的初始化就显得特别重要。
在感知器和逻辑回归中,一般将参数初始化为0,但是在神经网络中如果把参数初始化为0,就会导致在第一次前向计算时,所有隐藏层神经元的激活值都相同,这样会导致深层神经元没有区分性,这种现象称为对称权重现象
因此如果要高质量的训练一个网络,给参数选择一个合适的初始化区间是非常重要的,一般而言,参数初始化的区间应该根据神经元的性质进行差异化的设置,如果一个神经元的输入过多,权重就不要设置太大,以避免神经元的的输出过大(当激活函数为ReLU时)或者过饱和(激活函数为Sigmoid函数时)。
关于神经网络中的激活函数介绍可参考:
https://blog.csdn.net/Gamer_gyt/article/details/89440152
常见的参数初始化方法包括以下两种。
Gaussian初始化
高斯初始化是最简单的初始化方法,参数服从一个固定均值和固定方差的高斯分布进行随机初始化。
初始化一个深度网络时,一个比较好的初始化方案是保持每个神经元输入的方差是一个常量,当一个神经元的输入连接数量为n时,可以考虑其输入连接权重以 N ( 0 , 1 n ) N(0,\sqrt{\frac{1}{n}}) N(0,n1)的高斯分布进行初始化,如果同时考虑神经元的输出连接数量为m时,可以按照 N ( 0 , 2 m + n ) N(0,\sqrt{\frac{2}{m+n}}) N(0,m+n2)进行高斯分布初始化。
均匀分布初始化
均匀初始化是指在一个给定的区间[-r,r]内采用均匀分布来初始化参数,超参数r的设置也可以根据神经元的连接数量来进行自适应调整。
Xavier初始化方法是一种自动计算超参数r的方法,参数可以在[-r,r]之间采用均匀分布进行初始化。
如果神经元激活函数为logistic函数,对于第l-1层到第l层的权重参数区间可以设置为:
r
=
6
n
l
−
1
+
n
l
r = \sqrt{ \frac{6}{ n^{l-1} + n^l}}
r=nl−1+nl6
n
l
n^l
nl 表示第l层神经元的个数,
n
l
−
1
n^{l-1}
nl−1表示l-1层神经元的个数。
如果是tanh激活函数,权重参数区间可以设置为:
r
=
4
6
n
l
−
1
+
n
l
r =4 \sqrt{ \frac{6}{ n^{l-1} + n^l}}
r=4nl−1+nl6
在实际经验中,Xavier初始化方法用的比较多。
数据预处理
为什么要进行数据预处理
一般情况下,在原始数据中,数据的维度往往不一致,比如在电商数据中,某个商品点击的次数往往要远大于购买的次数,即特征的分布范围差距很大,这样在一些使用余弦相似度计算的算法中,较大的特征值就会起到绝对作用,显然这样做是极其不合理的。同样在深度神经网络中,虽然可以通过参数的调整来自适应不同范围的输入,但是这样训练的效率也是很低的。
假设一个只有一层的网络 y = t a n h ( w 1 x 1 + w 2 x 2 + b ) y=tanh(w_1x_1 + w_2 x_2 +b) y=tanh(w1x1+w2x2+b),其中 x 1 ∈ [ 0 , 10 ] , x 2 ∈ [ 0 , 1 ] x_1 \in [0,10], x_2 \in [0,1] x1∈[0,10],x2∈[0,1]。因为激活函数 tanh的导数在[-2,2]之间是敏感的,其余的值域导数接近0,因此 w 1 x 1 + w 2 x 2 + b w_1x_1 + w_2 x_2 +b w1x1+w2x2+b过大或者过小都会影响训练,为了提高训练效率,我们需要把 w 1 x 1 + w 2 x 2 + b w_1x_1 + w_2 x_2 +b w1x1+w2x2+b限定在[-2,2]之间,因为 x 1 , x 2 x_1,x_2 x1,x2的取值范围,需要把 w 1 w_1 w1设置的小一些,比如在[-0.1, 0.1]之间,可以想象,如果数据维度比较多的话,我们需要精心的去设置每一个参数,但是如果把特征限定在一个范围内,比如[0,1],我们就不需要太区别对待每一个参数。
除了参数初始化之外,不同特征取值范围差异比较大时也会影响梯度下降法的搜索效率,下图(图1-1)给出了数据归一化对梯度的影响,对比等高线图可以看出,归一化后,梯度的位置方向更加接近于最优梯度的方向。
数据预处理的方法
关于原始数据归一化的方法有很多,可以参考《推荐系统开发实战》中第四章节部分内容,写的很全面,而且有对应的代码实现。该书的购买链接:
逐层归一化
深层神经网络中为什么要做逐层归一化
在深层神经网络中,当前层的输入是上一层的输出,因此之前层参数的变化对后续层的影响比较大,就像一栋高楼,低层很小的变化就会影响到高层。
从机器学习的角度去看,如果某个神经网络层的输入参数发生了变化,那么其参数需要重新学习,这种现象叫做内部协变量偏移(Internal Covariate Shift)。
这里补充下机器学习中的协变量偏移(Covariate Shift)。协变量是一个统计学的概念,是影响预测结果的统计变量。在机器学习中,协变量可以看作是输入,一般的机器学习都要求输入在训练集和测试集上的分布是相似的,如果不满足这个假设,在训练集上得到的模型在测试集上表现就会比较差。
为了解决内部协变量偏移问题,需要对神经网络层的每一层输入做归一化,下面介绍几种常见的方法:
- 批量归一化
- 层归一化
- 其他方法
批量归一化
为了减少内部协变量偏移的影响,需要对神经网络每一层的净输入
z
l
z^l
zl进行归一化,相当于每一层都要做一次数据预处理,从而加快收敛速度,但是因为对每一层都进行操作,所以要求归一化的效率要很高,一般使用标准归一化,将净输入
z
l
z^l
zl的每一维都归一到标准正态分布,其公式如下:
z
^
l
=
z
l
−
E
[
z
l
]
v
a
r
(
z
l
)
+
ϵ
\hat{z}^l = \frac{ z^l - E[z^l] }{ \sqrt{var(z^l) + \epsilon } }
z^l=var(zl)+ϵzl−E[zl]
E
[
z
l
]
,
v
a
r
(
z
l
)
E[z^l],var(z^l)
E[zl],var(zl)表示在当前参数下
z
l
z^l
zl的每一维在整个训练集上的期望和方差,因为深度神经网络采用的是下批量的梯度下降优化方法,基于全部样本计算期望和方差是不可能的,因为通常采用小批量进行估计。给定一个包含K个样本的集合,第
l
l
l层神经元的净输入
z
(
1
,
l
)
,
.
.
.
.
z
(
K
,
l
)
z^{(1,l)},....z^{(K,l)}
z(1,l),....z(K,l)的均值和方差为:
μ
β
=
1
K
∑
k
=
1
K
z
(
k
,
l
)
σ
β
2
=
1
K
∑
k
=
1
K
(
z
(
k
,
l
)
−
μ
β
)
2
\mu _\beta = \frac{1 }{ K } \sum_{k=1}^{K } z^{(k,l)} \\ \sigma^2 _\beta = \frac{1 }{ K }\sum_{ k=1}^{K} (z^{(k,l)} - \mu _\beta)^2
μβ=K1k=1∑Kz(k,l)σβ2=K1k=1∑K(z(k,l)−μβ)2
对净输入
z
l
z^l
zl的标准归一化会使其取值集中在0附近,这样当使用sigmoid激活函数时,这个取值空间刚好接近线性变换的空间,减弱了神经网络的非线性性质。因此为了不使归一化对网络产生影响,需要对其进行缩放和平移处理,公式如下:
z
^
l
=
z
l
−
μ
β
σ
β
2
+
ϵ
⊙
γ
+
β
\hat{z}^l = \frac{ z^l - \mu _\beta }{ \sqrt{\sigma^2 _\beta+ \epsilon } } \odot \gamma + \beta
z^l=σβ2+ϵzl−μβ⊙γ+β
其中
γ
,
β
\gamma , \beta
γ,β分别代表缩放和平移的向量。
这里需要注意的是每次小批量样本的均值和方差是净输入 z l z^l zl的函数,而不是常量因此在计算梯度时要考虑到均值和方差产生的影响,当训练完成时,用整个数据集上的均值和方差来代替每次小样本计算得到的均值和方差。在实际实践经验中,小批量样本的均值和方差也可以使用移动平均来计算。
层归一化
批量归一化的操作对象是单一神经元,因此要求选择样本批量的时候,不能太小,否则难以计算单个神经元的统计信息,另外一个神经元的输入是动态变化的,比如循环神经网络,那么就无法应用批量归一化操作。
层归一化(Layer Normalization) 是和批量归一化非常类似的方法,但层归一化的操作对象是某层全部神经元。
对于深层神经网络,第
l
l
l层神经元的净输入为
z
l
z^l
zl,其均值和方差为:
u
l
=
1
n
l
∑
i
=
1
n
l
z
i
l
σ
l
2
=
1
n
l
∑
i
=
1
n
l
(
z
i
l
−
u
l
)
u^l = \frac{1}{n^l} \sum_{i=1}^{ n^l} z_i^l \\ \sigma ^2_l = \frac{1}{n^l} \sum_{i=1}^{ n^l} (z_i^l - u^l )
ul=nl1i=1∑nlzilσl2=nl1i=1∑nl(zil−ul)
其中
n
l
n^l
nl为第
l
l
l层神经元的数量。则层归一化定义为:
z
l
^
=
z
l
−
u
l
σ
l
2
+
ϵ
⊙
γ
+
β
\hat{z^l} = \frac{z^l - u^l }{ \sqrt {\sigma^2 _l + \epsilon } } \odot \gamma + \beta
zl^=σl2+ϵzl−ul⊙γ+β
其中
γ
,
β
\gamma ,\beta
γ,β分别代表缩放和平移的向量,和
z
l
z^l
zl的维度相同。
循环神经网络中的层归一化为:
z
t
=
U
h
t
−
1
+
W
x
t
h
t
=
f
(
z
l
^
)
z_t = U h_{t-1} + W x_t \\ h_t = f(\hat{z^l})
zt=Uht−1+Wxtht=f(zl^)
其中隐藏层为
h
t
h_t
ht,
x
t
x_t
xt为第
t
t
t时刻的净输入,
U
,
W
U,W
U,W为参数。
在标准循环网络中,循环神经层的输入一般就随着时间慢慢变大或者变小,从而引起梯度爆炸或者梯度消失,而层归一化的神经网络可以有效的缓解这种状况。
其他方法
除了上面介绍的两种归一化方法之外,还有一些其他的一些归一化方法,感兴趣的可以自行搜索查看。
- 权重归一化(Weight Normalization)
- 局部响应归一化
至此,神经网络中的优化方法第二部分介绍完成,主要包好了三部分内容:参数初始化,数据预处理和逐层归一化。再下一篇将会重点介绍超参数优化的方法不仅适用于深度神经网络,也适用于一般的机器学习任务。如果你觉得不错,分享一下吧!