神经网络设计的技巧
局部极小值与鞍点
介绍
1.local minima
local minima没有办法可以解决
2.saddle point
critical point:gradient为0的点
鞍点saddle point:gradient为0的点,但不是local minima的地方
L
(
θ
)
L(\theta)
L(θ)在
θ
=
θ
′
\theta = \theta'
θ=θ′附近的函数值可以表示如下(泰勒展开),其中的
g
g
g为梯度(一次微分),H(Hessian矩阵)是二次微分:
L
(
θ
)
≈
L
(
θ
′
)
+
(
θ
−
θ
′
)
T
g
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
g
=
▽
L
(
θ
′
)
,
g
i
=
∂
L
(
θ
′
)
∂
θ
i
H
i
,
j
=
∂
2
∂
θ
i
∂
θ
j
L
(
θ
′
)
L(\theta) \approx L(\theta') + (\theta - \theta')^Tg + \frac{1}{2}(\theta - \theta')^TH(\theta - \theta') \\ g = \triangledown L(\theta'), \space g_i=\frac{\partial L(\theta')}{\partial \theta_i} \\ H_{i,j} = \frac{\partial^2}{\partial\theta_i\partial\theta_j}L(\theta')
L(θ)≈L(θ′)+(θ−θ′)Tg+21(θ−θ′)TH(θ−θ′)g=▽L(θ′), gi=∂θi∂L(θ′)Hi,j=∂θi∂θj∂2L(θ′)
当点为critical point时,令
v
=
(
θ
−
θ
′
)
v = (\theta - \theta')
v=(θ−θ′),这个时候的损失函数如下:
L
(
θ
)
≈
L
(
θ
′
)
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
≈
L
(
θ
′
)
+
v
T
H
v
\begin{aligned} L(\theta) &\approx L(\theta') + \frac{1}{2}(\theta - \theta')^TH(\theta - \theta') \\ &\approx L(\theta') + v^THv \\ \end{aligned}
L(θ)≈L(θ′)+21(θ−θ′)TH(θ−θ′)≈L(θ′)+vTHv
- 对于所有的
v
v
v,如果
v
T
H
v
>
0
v^THv > 0
vTHv>0,说明
L
(
θ
)
>
L
(
θ
′
)
L(\theta) > L(\theta')
L(θ)>L(θ′),所以在
θ
′
\theta'
θ′为local minima
- 等价于 H H H是正定矩阵(positive definite matrix),也就是说所有的特征值(eigen values)为正
- 对于所有的
v
v
v,如果
v
T
H
v
<
0
v^THv < 0
vTHv<0,说明
L
(
θ
)
<
L
(
θ
′
)
L(\theta) < L(\theta')
L(θ)<L(θ′),所以在
θ
′
\theta'
θ′为local maxima
- 等价于 H H H是负定矩阵(negative definite matrix),也就是说所有的特征值(eigen values)为负
- 对于所有的
v
v
v,有时
v
T
H
v
>
0
v^THv > 0
vTHv>0,有时
v
T
H
v
<
0
v^THv < 0
vTHv<0,这个时候是saddle point
- 特征值有正有负
3.举例如下:
鞍点的更新方向
如果这个时候遇到的critical point是saddle point,那么 H H H可以告诉我们参数的更新方向。
举例如下:
但是这种方法在实际情况中基本上不适用,因为计算Hessan矩阵运算量非常大。
补:在实际的训练中(高维空间中),其实local minima的情况并不多见,更常见的是卡在了saddle point的情况
批次与动量
批次batch
动量momentum
打乱化shuffle
批次batch
直观的来看(是错误的),batch size:
- 过大:需要很长时间来到达结果,但是很有效
- 过小:可以较短时间到达结果,但是很noisy
但是batch size较大并不一定需要很长时间来计算梯度,因为在一定范围内,可以使用GPU的并行计算来计算梯度,只要batch size不是过大。
batch size较小需要更长时间来完成一次epoch,
较大的batch size在得到model时可能会有问题,较小的batch size反而是好的(在training data和testing data都表现较好),也就意味着“noisy” update反而是较好的。
总结:
动量momentum
1.一般情况下的gradient descent
2.gradient descent + momentum
总结
自适应学习率
介绍
在实际训练中,可能critical point并不是最困难的事情,更有可能遇到如下情况:
loss不在减少,但是gradient反而一直在变化,对应的情况可能如上图中的“绿色箭头”所示,也就是参数在两个点来回跳动。
因此,我们需要改进gradient descent,在gradient descent中,梯度gradient已经确定,因此我们需要调整学习速率learning rate η \eta η,有两种调整方式:
- 不同的参数有不同的learning rate
- learning rate是动态变化的
n o r m a l g r a d i e n t d e s c e n t : θ i t + 1 ← θ i t − η g i t a d a p t i v e l e a r n i n g r a t e : θ i t + 1 ← θ i − η σ i t g i t normal\space gradient\space descent: \theta_i^{t+1} \leftarrow \theta_i^t - \eta g_i^t \\ adaptive\space learning\space rate: \theta_i^{t+1} \leftarrow \theta_i - \frac{\eta}{\sigma_i^t}g_i^t normal gradient descent:θit+1←θit−ηgitadaptive learning rate:θit+1←θi−σitηgit
其中的
σ
i
t
\sigma_i^t
σit是跟当前参数和迭代次数相关的,在前文中的”误差和梯度下降“已经讲到,可以取如下值(计算的结果称为Root Mean Square):
σ
i
t
=
1
t
+
1
∑
i
=
0
t
(
g
i
t
)
2
\sigma_i^t = \sqrt{\frac{1}{t+1}\sum_{i=0}^t(g_i^t)^2}
σit=t+11i=0∑t(git)2
这个计算方式在Adagrad算法中使用,举例如下:
但是
σ
i
t
\sigma_i^t
σit也可以使用如下计算方式,被称为RMSProp(Root Mean Square):
σ
i
t
=
α
(
σ
i
t
−
1
)
2
+
(
1
−
α
)
(
g
i
t
)
2
,
0
<
α
<
1
\sigma_i^t = \sqrt{\alpha(\sigma_i^{t-1})^2 + (1 - \alpha)(g_i^t)^2}, 0 < \alpha < 1
σit=α(σit−1)2+(1−α)(git)2,0<α<1
举例如下:
Adam:RMSProp + Momentum
对比
可以发现,使用了Adagram时,参数的变化会在一定迭代次数之后上下震荡,然后继续前进,具体的原因是因为这个时候它的更新和前面所有的gradient都有关,一定次数后,他就会往上下走,然后继续受到gradient的影响又继续往前走。
解决这个问题的一个方法就是给learning rate scheduling,也就是让learning rate与时间有关。
Learning Rate Scheduling
具体的策略可以是:
- Learning Rate Decay,随着训练继续进行,我们接近了结果,因此我们减少learning rate
- Warm up:learning rate要先变大然后变小
其中的warm up在两篇论文中都提到,如下:
其中,也可以参考RAdam,它是Adam算法的改进版,其中也使用了Warm up
Summary
其中需要注意, m i t m_i^t mit和 σ i t \sigma_i^t σit都是计算gradient,但是它们的计算方式是不一样的, m i t m_i^t mit考虑了每次gradient的方向,而 σ i t \sigma_i^t σit只考虑了gradient的大小。
这里只给出了Optimization的一些简单策略,如SGD、SGD with momentum、Adagrad、Adam、RMSProp等,还有其它的Optimization策略,可以参考视频1和视频2
介绍
1.回归Regress
回归的模型为 y = w x + b y = wx + b y=wx+b,其中的 y y y为实数,与真实值 y ^ \hat{y} y^进行对比得到loss function
2.分类Classification
从回归来看,其中的 y y y定义为不同的数字是不合理的,这样会隐含每个类别有大小关系,这里的处理方式是将每个类别使用one-hot编号来表示,模型的输出结果需要是对应类别的向量,具体的做法如下:
注:这里还需要在结果y进行一次softmax,然后再与
y
^
\hat{y}
y^进行比较结果,softmax的计算公式如下:
y
i
′
=
e
x
p
(
y
i
)
∑
j
e
x
p
(
y
i
)
y_i' = \frac{exp(y_i)}{\sum_jexp(y_i)}
yi′=∑jexp(yi)exp(yi)
得到的
0
<
y
i
′
<
1
,
∑
i
y
i
′
=
1
0<y_i'<1, \sum_iy_i'=1
0<yi′<1,∑iyi′=1,该操作会让原本的差距变得更大,其中的
y
i
y_i
yi被称为logit,当类别为两个类别时,一般是使用sigmoid来计算,而不使用softmax。
在计算
y
′
y'
y′和
y
^
\hat{y}
y^的损失时,不像回归中使用Mean Square Error,而是使用交叉熵Cross-entropy,公式如下:
e
=
−
∑
i
y
i
^
ln
y
i
′
e = -\sum_i\hat{y_i}\ln y_i'
e=−i∑yi^lnyi′
补:最小化交叉熵的过程等价于求极大似然估计的过程
Minimizing cross-entropy is equivalent to maximizing likelihood
优化Optimization
为什么在分类问题中使用Cross-entropy比Mean Square Error更好呢,具体解释如下:
因此可以得出结论:loss function的改变也会影响到optimization的难度。
批次标准化
Training tips:Batch Normalization,这个方法是用来change landscape of loss function的。
介绍
假设有一个模型为 y = w 1 x 1 + w 1 x 2 + b y=w1x1+w1x2+b y=w1x1+w1x2+b:
-
如果 x 1 x1 x1值很小时,那么当 w 1 w1 w1变化为 w 1 + △ w 1 w1+\triangle w1 w1+△w1时,对 y y y的影响就会很小,也就是 △ y \triangle y △y会很小,对应的 y y y与真实值 y ^ \hat{y} y^的误差 △ e \triangle e △e也会很小,最终的损失 L L L改变的 △ L \triangle L △L也会很小。
-
如果 x 2 x2 x2值很大时,那么当 w 2 w2 w2变化为 w 2 + △ w 2 w2+\triangle w2 w2+△w2时,对 y y y的影响就会很大,也就是 △ y \triangle y △y会很大,对应的 y y y与真实值 y ^ \hat{y} y^的误差 △ e \triangle e △e也会很小,最终的损失 L L L改变的 △ L \triangle L △L也会很大。
如下图:
上述的输入值对应的损失函数如左上角图所示,会比较陡峭,这个时候使用梯度下降法进行模型优化,很可能就没法走到最优点。
一个可行的解决方案就是保证特征值在同一范围,具体的方法统称为特征标准化feature normalization。通过特征标准,可以让梯度下降收敛得更快。
特征标准化
特征标准化包含一系列方法,其中一个可行的标准化方式如下图:
针对特征的同一个维度的值提取出来,计算平均值和标准差,然后将该维度的所有值变为 x ~ i r ← x i r − m i σ i \widetilde{x}_i^r \leftarrow \frac{x_i^r - m_i}{\sigma_i} x ir←σixir−mi
但是设想一下,如果有多层模型,对于第一层得到的结果是否要标准化呢?经过激活函数的值又是否要标准化呢?很显然,也是可以进行标准化的,因为它们并不会在同一范围。
这里以
z
z
z为例,讲解如何针对结果值进行标准化,具体的做法其实很简单,把最后的
z
z
z值作为向量,分别计算其平均值和标准差,然后在一一对应得到每个维度的
z
i
z_i
zi即可。对应的计算公式如下:
μ
=
1
3
∑
i
=
1
3
z
i
σ
=
1
3
∑
i
=
1
3
(
z
i
−
μ
)
2
z
~
i
=
z
i
−
μ
σ
\boldsymbol{\mu} = \frac{1}{3}\sum_{i=1}^3\mathbf{z}^i \\ \boldsymbol{\sigma} = \sqrt{\frac{1}{3}\sum_{i=1}^3(\mathbf{z}^i - \boldsymbol{\mu})^2} \\ \widetilde{\mathbf{z}}^i = \frac{\mathbf{z}^i - \boldsymbol{\mu}}{\boldsymbol{\sigma}}
μ=31i=1∑3ziσ=31i=1∑3(zi−μ)2z
i=σzi−μ
需要注意,上述的
z
~
i
\widetilde{z}^i
z
i计算过程中,除法表示的是每个元素一一相除,向量中没有除法。
Batch Normalization
1.介绍
考虑到实际情况中,因为 μ \mu μ和 σ \sigma σ都是通过前面的 z z z计算来的,其中 z z z表示一个向量,也就意味着,如果其中的某一个元素 z i z^i zi发生变化,对应的 μ \mu μ和 σ \sigma σ都要发生变化。而在梯度下降的过程中,参数的变化是比较频繁的,如果整个模型是一个非常大的网络,那么整个计算量就会非常大。
因此可以考虑一个优化,只针对一个batch进行标准化,可以减少计算量。
在进行batch normalization时,通常还会增加一个新操作:
z
~
i
=
z
i
−
μ
σ
z
^
i
=
γ
⊙
z
~
i
+
β
\widetilde{\mathbf{z}}^i = \frac{\mathbf{z}^i - \boldsymbol{\mu}}{\boldsymbol{\sigma}} \\ \widehat{\mathbf{z}}^{i}=\boldsymbol{\gamma} \odot \tilde{\mathbf{z}}^{i}+\boldsymbol{\beta}
z
i=σzi−μz
i=γ⊙z~i+β
新增的操作,是为了让它们的平均值不为0。
2.测试过程中的batch normalization
在测试过程中,我们没有batch的概念,那么如果计算出
μ
\mu
μ和
σ
\sigma
σ呢,这个时候使用
μ
ˉ
\bar{\mu}
μˉ和
σ
ˉ
\bar{\sigma}
σˉ来代替,是在训练过程中通过计算每次的
μ
\mu
μ和
σ
\sigma
σ的moving average来得到的。计算公式为:
μ
ˉ
←
p
μ
ˉ
+
(
1
−
p
)
μ
t
\bar{\mu} \leftarrow p\bar{\mu} + (1 - p) \mu^t
μˉ←pμˉ+(1−p)μt
其中的
μ
t
\mu^t
μt表示第
t
t
t次训练过程的
μ
\mu
μ,
p
p
p是一个超参数,使用batch normalization的对比结果如下:
对应的论文,其中也讲解了CNN中的batch normalization怎么实现。
那么batch normalization是如何帮助优化的呢,一个直观的解释为batch normalization把中间结果有了相同的统计分布,但是该解释被一篇论文给解释为错误的。这篇论文也支持batch normalization可以改变the landscape of error surface,该篇论文也通过实验说明batch normalization并不是唯一的使得landscape不崎岖的方法,还有其他的标准化方法,给出对应的论文如下:
- Batch Renormalization
- Layer Normalization
- Instance Normalization
- Group Normalization
- Weight Normalization
- Spectrum Normalization
References
1.Adam
4.RAdam