1、深度学习的实用层面
1.1 训练、验证、测试集
对于一个需要解决的问题的样本数据,在建立模型的过程中,我们会将问题的data划分为以下几个部分:
-
训练集(train set):用训练集对算法或模型进行训练过程;
-
验证集(development set):利用验证集或者又称为简单交叉验证集(hold-out cross validation set)进行交叉验证,选择出最好的模型;
-
测试集(test set):最后利用测试集对模型进行测试,获取模型运行的无偏估计。
小数据时代
在小数据量的时代,如:100、1000、10000的数据量大小,可以将data做以下划分:
无验证集的情况:70% / 30%;
有验证集的情况:60% / 20% / 20%;
通常在小数据量时代,以上比例的划分是非常合理的。
大数据时代
但是在如今的大数据时代,对于一个问题,我们拥有的data的数量可能是百万级别的,所以验证集和测试集所占的比重会趋向于变得更小。
验证集的目的是为了验证不同的算法哪种更加有效,所以验证集只要足够大能够验证大约2-10种算法哪种更好就足够了,不需要使用20%的数据作为验证集。如百万数据中抽取1万的数据作为验证集就可以了。
测试集的主要目的是评估模型的效果,如在单个分类器中,往往在百万级别的数据中,我们选择其中1000条数据足以评估单个模型的效果。
100万数据量:98% / 1% / 1%;
超百万数据量:99.5% / 0.25% / 0.25%(或者99.5% / 0.4% / 0.1%)
Notation
建议验证集要和训练集来自于同一个分布
,可以使得机器学习算法变得更快;
如果不需要用无偏估计来评估模型的性能,则可以不需要测试集。
1.2 偏差、方差
对于下图中两个类别分类边界的分割:
从图中我们可以看出,在欠拟合(underfitting)的情况下,出现高偏差(high bias)的情况;在过拟合(overfitting)的情况下,出现高方差(high variance)的情况。
在bias-variance tradeoff 的角度来讲,我们利用训练集对模型进行训练就是为了使得模型在train集上使 bias 最小化,避免出现underfitting的情况;
但是如果模型设置的太复杂,虽然在train集上 bias 的值非常小,模型甚至可以将所有的数据点正确分类,但是当将训练好的模型应用在dev 集上的时候,却出现了较高的错误率。这是因为模型设置的太复杂则没有排除一些train集数据中的噪声,使得模型出现overfitting的情况,在dev 集上出现高 variance 的现象。
所以对于bias和variance的权衡问题,对于模型来说是一个十分重要的问题。
1.3 机器学习的基本方法
在训练机器学习模型的过程中,解决High bias 和High variance 的过程:
- 解决High bias:
- 增加网络结构,如增加隐藏层数目;
- 训练更长时间;
- 寻找合适的网络架构,使用更大的NN结构;
- 解决High variance:
- 获取更多的数据;
- 正则化( regularization);
- 寻找合适的网络结构;
在大数据时代,深度学习对监督式学习大有裨益,使得我们不用像以前一样太过关注如何平衡偏差和方差的权衡问题,通过以上方法可以使得再不增加另一方的情况下减少一方的值。
1.4 正则化(regularization)
利用正则化来解决High variance 的问题,正则化是在 Cost function 中加入一项正则化项,惩罚模型的复杂度。
Logistic regression
加入正则化项的代价函数:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
l
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∣
∣
w
∣
∣
2
2
J(w,b)=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}||w||_{2}^{2}
J(w,b)=m1i=1∑ml(y^(i),y(i))+2mλ∣∣w∣∣22
上式为逻辑回归的L2正则化。
- L2正则化: λ 2 m ∣ ∣ w ∣ ∣ 2 2 = λ 2 m ∑ j = 1 n x w j 2 = λ 2 m w T w \dfrac{\lambda}{2m}||w||_{2}^{2} = \dfrac{\lambda}{2m}\sum\limits_{j=1}^{n_{x}} w_{j}^{2}=\dfrac{\lambda}{2m}w^{T}w 2mλ∣∣w∣∣22=2mλj=1∑nxwj2=2mλwTw
- L1正则化: λ 2 m ∣ ∣ w ∣ ∣ 1 = λ 2 m ∑ j = 1 n x ∣ w j ∣ \dfrac{\lambda}{2m}||w||_{1}=\dfrac{\lambda}{2m}\sum\limits_{j=1}^{n_{x}}|w_{j}| 2mλ∣∣w∣∣1=2mλj=1∑nx∣wj∣
其中
λ
λ
λ为正则化因子。
注意:lambda
在python中属于保留字,所以在编程的时候,用“lambd”代表这里的正则化因子
λ
λ
λ。
Neural network
加入正则化项的代价函数:
J
(
w
[
1
]
,
b
[
1
]
,
⋯
 
,
w
[
L
]
,
b
[
L
]
)
=
1
m
∑
i
=
1
m
l
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∑
l
=
1
L
∣
∣
w
[
l
]
∣
∣
F
2
J(w^{[1]},b^{[1]},\cdots,w^{[L]},b^{[L]})=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}\sum\limits_{l=1}^{L}||w^{[l]}||_{F}^{2}
J(w[1],b[1],⋯,w[L],b[L])=m1i=1∑ml(y^(i),y(i))+2mλl=1∑L∣∣w[l]∣∣F2
其中 ∣ ∣ w [ l ] ∣ ∣ F 2 = ∑ i = 1 n [ l − 1 ] ∑ j = 1 n [ l ] ( w i j [ l ] ) 2 ||w^{[l]}||_{F}^{2}=\sum\limits_{i=1}^{n^{[l-1]}}\sum\limits_{j=1}^{n^{[l]}}(w_{ij}^{[l]})^{2} ∣∣w[l]∣∣F2=i=1∑n[l−1]j=1∑n[l](wij[l])2,因为 w w w的大小为 ( n [ l − 1 ] , n [ l ] ) (n^{[l-1]},n^{[l]}) (n[l−1],n[l]),该矩阵范数被称为“Frobenius norm”。
Weight decay
在加入正则化项后,梯度变为:
d
W
[
l
]
=
(
f
o
r
m
_
b
a
c
k
p
r
o
p
)
+
λ
m
W
[
l
]
dW^{[l]} = (form\_backprop)+\dfrac{\lambda}{m}W^{[l]}
dW[l]=(form_backprop)+mλW[l]
则梯度更新公式变为:
W
[
l
]
:
=
W
[
l
]
−
α
d
W
[
l
]
W^{[l]}:= W^{[l]}-\alpha dW^{[l]}
W[l]:=W[l]−αdW[l]
代入可得:
W
[
l
]
:
=
W
[
l
]
−
α
[
(
f
o
r
m
_
b
a
c
k
p
r
o
p
)
+
λ
m
W
[
l
]
]
=
W
[
l
]
−
α
λ
m
W
[
l
]
−
α
(
f
o
r
m
_
b
a
c
k
p
r
o
p
)
=
(
1
−
α
λ
m
)
W
[
l
]
−
α
(
f
o
r
m
_
b
a
c
k
p
r
o
p
)
W^{[l]}:= W^{[l]}-\alpha [ (form\_backprop)+\dfrac{\lambda}{m}W^{[l]}]\\ = W^{[l]}-\alpha\dfrac{\lambda}{m}W^{[l]} -\alpha(form\_backprop)\\=(1-\dfrac{\alpha\lambda}{m})W^{[l]}-\alpha(form\_backprop)
W[l]:=W[l]−α[(form_backprop)+mλW[l]]=W[l]−αmλW[l]−α(form_backprop)=(1−mαλ)W[l]−α(form_backprop)
其中, ( 1 − α λ m ) (1-\dfrac{\alpha\lambda}{m}) (1−mαλ)为一个 < 1 <1 <1的项,会给原来的 W [ l ] W^{[l]} W[l]一个衰减的参数,所以L2范数正则化也被称为“权重衰减(Weight decay)”。
正则化使得有些节点的 w w w变为0, 使其作用减小,甚至失效,本质上在减小模型的复杂度。
1.5 为什么正则化可以减小过拟合
假设下图的神经网络结构属于过拟合状态:
对于神经网络的Cost function:
J
(
w
[
1
]
,
b
[
1
]
,
⋯
 
,
w
[
L
]
,
b
[
L
]
)
=
1
m
∑
i
=
1
m
l
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∑
l
=
1
L
∣
∣
w
[
l
]
∣
∣
F
2
J(w^{[1]},b^{[1]},\cdots,w^{[L]},b^{[L]})=\dfrac{1}{m}\sum\limits_{i=1}^{m}l(\hat y^{(i)},y^{(i)})+\dfrac{\lambda}{2m}\sum\limits_{l=1}^{L}||w^{[l]}||_{F}^{2}
J(w[1],b[1],⋯,w[L],b[L])=m1i=1∑ml(y^(i),y(i))+2mλl=1∑L∣∣w[l]∣∣F2
加入正则化项,直观上理解,正则化因子 λ λ λ设置的足够大的情况下,为了使代价函数最小化,权重矩阵 W W W就会被设置为接近于0的值。则相当于消除了很多神经元的影响,那么图中的大的神经网络就会变成一个较小的网络。
当然上面这种解释是一种直观上的理解,但是实际上隐藏层的神经元依然存在,但是他们的影响变小了,便不会导致过拟合。
数学解释:
假设神经元中使用的激活函数为
g
(
z
)
=
t
a
n
h
(
z
)
g(z)=tanh(z)
g(z)=tanh(z),在加入正则化项后:
当λλ增大,导致
W
[
l
]
W^{[l]}
W[l]减小,
Z
[
l
]
=
W
[
l
]
a
[
l
−
1
]
+
b
[
l
]
Z^{[l]} = W^{[l]} a^{[l-1]} + b^{[l]}
Z[l]=W[l]a[l−1]+b[l]便会减小,由上图可知,在
z
z
z较小的区域里,
t
a
n
h
(
z
)
tanh(z)
tanh(z)函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,从而不会发生过拟合。
1.6 Dropout 正则化
Dropout(随机失活)就是在神经网络的Dropout层,为每个神经元结点设置一个随机消除的概率,对于保留下来的神经元,我们得到一个节点较少,规模较小的网络进行训练。
实现Dropout的方法:反向随机失活(Inverted dropout)
首先假设对 layer 3 进行dropout:
keep_prob = 0.8 # 设置神经元保留概率
d3 = np.random.rand(a3.shape[0], a3.shape[1]) < keep_prob
a3 = np.multiply(a3, d3)
a3 /= keep_prob
这里解释下为什么要有最后一步:a3 /= keep_prob
依照例子中的keep_prob = 0.8 ,那么就有大约20%的神经元被删除了,也就是说 a [ 3 ] a^{[3]} a[3]中有20%的元素被归零了,在下一层的计算中有 Z [ 4 ] = W [ 4 ] ⋅ a [ 3 ] + b [ 4 ] Z^{[4]}=W^{[4]}\cdot a^{[3]}+b^{[4]} Z[4]=W[4]⋅a[3]+b[4],所以为了不影响 Z [ 4 ] Z^{[4]} Z[4]的期望值,所以需要 W [ 4 ] ⋅ a [ 3 ] W^{[4]}\cdot a^{[3]} W[4]⋅a[3]的部分除以一个keep_prob。
Inverted dropout通过对“a3 /= keep_prob”,则保证无论keep_prob设置为多少,都不会对Z[4]Z[4]的期望值产生影响。
Notation:在测试阶段不要用dropout,因为那样会使得预测结果变得随机。
1.7 理解 Dropout
另外一种对于Dropout的理解。
这里我们以单个神经元入手,单个神经元的工作就是接收输入,并产生一些有意义的输出,但是加入了Dropout以后,输入的特征都是有可能会被随机清除的,所以该神经元不会再特别依赖于任何一个输入特征,也就是说不会给任何一个输入设置太大的权重。
所以通过传播过程,dropout将产生和L2范数相同的收缩权重的效果。
对于不同的层,设置的keep_prob
也不同,一般来说神经元较少的层,会设keep_prob
=1.0,神经元多的层,则会将keep_prob
设置的较小。
调节参数keep_prob,类似于L2正则化参数 λ \lambda λ。
缺点:
dropout的一大缺点就是其使得 Cost function不能再被明确的定义,以为每次迭代都会随机消除一些神经元结点,所以我们无法绘制出每次迭代
J
(
W
,
b
)
J(W,b)
J(W,b)下降的图,如下:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c2010625db322c1810e2f7d7bd0b292c.png)
使用Dropout:
- 关闭dropout功能,即设置 keep_prob = 1.0;
- 运行代码,确保 J ( W , b ) J(W,b) J(W,b)函数单调递减;
- 再打开dropout函数。
1.8 其他正则化方法
1、数据扩增(Data augmentation):通过图片的一些变换,得到更多的训练集和验证集;
2、Early stopping:在交叉验证集的误差上升之前的点停止迭代,避免过拟合。这种方法的缺点是无法同时解决bias和variance之间的最优。
1.9 归一化输入:加速训练
对数据集特征
x
1
,
x
2
x_1, x_2
x1,x2归一化的过程:
- 计算每个特征所有样本数据的均值: μ = 1 m ∑ i = 1 m x ( i ) \mu = \dfrac{1}{m}\sum\limits_{i=1}^{m}x^{(i)} μ=m1i=1∑mx(i)
- 减去均值得到对称的分布: x : = x − μ x : =x-\mu x:=x−μ
- 归一化方差: x / = σ 2 x /= \sigma^2 x/=σ2,其中 σ 2 = 1 m ∑ i = 1 m x ( i ) 2 \sigma^{2} = \dfrac{1}{m}\sum\limits_{i=1}^{m}x^{(i)^{2}} σ2=m1i=1∑mx(i)2
使用归一化的原因:
由图可以看出不使用归一化和使用归一化前后Cost function 的函数形状会有很大的区别。
在不使用归一化的代价函数中,如果我们设置一个较小的学习率,那么很可能我们需要很多次迭代才能到达代价函数全局最优解;如果使用了归一化,那么无论从哪个位置开始迭代,我们都能以相对很少的迭代次数找到全局最优解。
为什么可以加速?
因为对于不同的特征其scale不一样,在训练的时候步长较小,而且需要更长的训练时间,但是对于归一化后的数据,代价函数的图更接近于碗状,下降更快,更容易优化。
1.10 梯度消失与梯度爆炸
如下图所示的神经网络结构,以两个输入为例:
这里我们首先假定
g
(
z
)
=
z
,
b
[
l
]
=
0
g(z)=z,b^{[l]}=0
g(z)=z,b[l]=0,所以对于目标输出有:
y
^
=
W
[
L
]
(
W
[
L
−
1
]
(
⋯
(
W
[
2
]
(
W
[
1
]
X
)
)
)
)
\hat y = W^{[L]}(W^{[L-1]}(\cdots (W^{[2]}(W^{[1]}X))))
y^=W[L](W[L−1](⋯(W[2](W[1]X))))
W
[
l
]
W^{[l]}
W[l]的值大于1的情况:
如:
W
[
l
]
=
[
1.5
0
0
1.5
]
W^{[l]}=\left[ \begin{array}{l} 1.5 & 0 \\ 0 & 1.5\end{array} \right]
W[l]=[1.5001.5],那么最终,
y
^
=
W
[
L
]
[
1.5
0
0
1.5
]
L
−
1
X
\hat y = W^{[L]}\left[ \begin{array}{l} 1.5 & 0 \\\ 0 & 1.5\end{array} \right]^{L-1}X
y^=W[L][1.5 001.5]L−1X,激活函数的值将以指数级递增;
W
[
l
]
W^{[l]}
W[l]的值小于1的情况:
如:
W
[
l
]
=
[
0.5
0
0
0.5
]
W^{[l]}=\left[ \begin{array}{l} 0.5 & 0 \\ 0 & 0.5\end{array} \right]
W[l]=[0.5000.5],那么最终,
y
^
=
W
[
L
]
[
0.5
0
0
0.5
]
L
−
1
X
\hat y = W^{[L]}\left[ \begin{array}{l} 0.5 & 0 \\\ 0 & 0.5\end{array} \right]^{L-1}X
y^=W[L][0.5 000.5]L−1X,激活函数的值将以指数级递减。
上面的情况对于导数也是同样的道理,所以在计算梯度时,根据情况的不同,梯度函数会以指数级递增或者递减,导致训练导数难度上升,梯度下降算法的步长会变得非常非常小,需要训练的时间将会非常长。
在梯度函数上出现的以指数级递增或者递减的情况就分别称为梯度爆炸
或者梯度消失
。
1.11 利用初始化缓解梯度消失和爆炸问题
以一个单个神经元为例子:
由上图可知,当输入的数量
n
n
n较大时,我们希望每个
w
i
w_i
wi的值都小一些,这样它们的和得到的
z
z
z也较小。
这里为了得到较小的
w
i
w_i
wi,设置
V
a
r
(
w
i
)
=
1
n
Var(w_{i})=\dfrac{1}{n}
Var(wi)=n1,这里称为Xavier initialization。
对参数进行初始化:
WL = np.random.randn(WL.shape[0],WL.shape[1])* np.sqrt(1/n)
这么做是因为,如果激活函数的输入 x x x近似设置成均值为0,标准方差1的情况,输出z也会调整到相似的范围内。虽然没有解决梯度消失和爆炸的问题,但其在一定程度上确实减缓了梯度消失和爆炸的速度。
初始化合适的权重向量,使得输入输出都在一定范围内,不至于发生严重的梯度消失/爆炸。
不同激活函数的 Xavier initialization:
- 激活函数使用Relu: V a r ( w i ) = 2 n Var(w_{i})=\dfrac{2}{n} Var(wi)=n2
- 激活函数使用tanh: V a r ( w i ) = 1 n Var(w_{i})=\dfrac{1}{n} Var(wi)=n1
其中n是输入的神经元个数,也就是 n [ l − 1 ] n^{[l-1]} n[l−1]。
1.12 梯度的数值逼近
使用双边误差的方法去逼近导数:
由图可以看出,双边误差逼近的误差是0.0001,先比单边逼近的误差0.03,其精度要高了很多。
涉及的公式:
- 双边导数:
f ′ ( θ ) = lim ε → 0 = f ( θ + ε ) − ( θ − ε ) 2 ε f'(\theta) = \lim\limits_{\varepsilon \to 0}=\dfrac{f(\theta+\varepsilon)-(\theta-\varepsilon)}{2\varepsilon} f′(θ)=ε→0lim=2εf(θ+ε)−(θ−ε)
误差: O ( ε 2 ) O(ε^2) O(ε2)
- 单边导数:
f ′ ( θ ) = lim ε → 0 = f ( θ + ε ) − ( θ ) ε f'(\theta) = \lim\limits_{\varepsilon \to 0}=\dfrac{f(\theta+\varepsilon)-(\theta)}{\varepsilon} f′(θ)=ε→0lim=εf(θ+ε)−(θ)
误差: O ( ε ) O(ε) O(ε)
1.13 梯度检验
下面用前面一节的方法来进行梯度检验。
连接参数
因为我们的神经网络中含有大量的参数: W [ 1 ] , b [ 1 ] , ⋯   , W [ L ] , b [ L ] W^{[1]},b^{[1]},\cdots,W^{[L]},b^{[L]} W[1],b[1],⋯,W[L],b[L],为了做梯度检验,需要将这些参数全部连接起来,reshape成一个大的向量 θ \theta θ。
同时对
d
W
[
1
]
,
d
b
[
1
]
,
⋯
 
,
d
W
[
L
]
,
d
b
[
L
]
dW^{[1]},db^{[1]},\cdots,dW^{[L]},db^{[L]}
dW[1],db[1],⋯,dW[L],db[L]执行同样的操作。
进行梯度检验:
进行如下图的梯度检验:
判断 d θ a p p r o x ≈ d θ d\theta_{approx}\approx d\theta dθapprox≈dθ是否接近。
判断公式:
∣
∣
d
θ
a
p
p
r
o
x
−
d
θ
∣
∣
2
∣
∣
d
θ
a
p
p
r
o
x
∣
∣
2
+
∣
∣
d
θ
∣
∣
2
\dfrac {||d\theta_{approx}-d\theta||_{2}}{||d\theta_{approx}||_{2}+||d\theta||_{2}}
∣∣dθapprox∣∣2+∣∣dθ∣∣2∣∣dθapprox−dθ∣∣2
其中,“ ∣ ∣ ⋅ ∣ ∣ 2 ||\cdot ||_{2} ∣∣⋅∣∣2”表示欧几里得范数,它是误差平方之和,然后求平方根,得到的欧氏距离。
1.14 实现梯度检验 Notes
- 不要在训练过程中使用梯度检验,只在debug的时候使用,使用完毕关闭梯度检验的功能;
- 如果算法的梯度检验出现了错误,要检查每一项,找出错误,也就是说要找出哪个 d θ a p p r o x [ i ] d\theta_{approx}[i] dθapprox[i]与 d θ dθ dθ的值相差比较大;
- 不要忘记了正则化项;
- 梯度检验不能与dropout同时使用。因为每次迭代的过程中,dropout会随机消除隐层单元的不同神经元,这时是难以计算dropout在梯度下降上的代价函数J;
- 在随机初始化的时候运行梯度检验,或许在训练几次后再进行。
2、优化算法
2.1 Mini-batch 梯度下降法
对整个训练集进行梯度下降法的时候,我们必须处理整个训练数据集,然后才能进行一步梯度下降,即每一步梯度下降法需要对整个训练集进行一次处理,如果训练数据集很大的时候,如有500万或5000万的训练数据,处理速度就会比较慢。
但是如果每次处理训练数据的一部分即进行梯度下降法,则我们的算法速度会执行的更快。而处理的这一小部分训练子集即称为Mini-batch。
算法核心:
对于普通的梯度下降法,一个epoch只能进行一次梯度下降;而对于Mini-batch梯度下降法,一个epoch可以进行Mini-batch的个数次梯度下降。
不同size大小的比较:
普通的batch梯度下降法和Mini-batch梯度下降法代价函数的变化趋势,如下图所示:
- batch梯度下降:
- 对所有m个训练样本执行一次梯度下降,每一次迭代时间较长;
- Cost function 总是向减小的方向下降。
- 随机梯度下降:
- 对每一个训练样本执行一次梯度下降,但是丢失了向量化带来的计算加速;
- Cost function总体的趋势向最小值的方向下降,但是无法到达全局最小值点,呈现波动的形式。
- Mini-batch梯度下降:
- 选择一个 1 < s i z e < m 1<size<m 1<size<m的合适的size进行Mini-batch梯度下降,可以实现快速学习,也应用了向量化带来的好处。
- Cost function的下降处于前两者之间。
Mini-batch 大小的选择
- 如果训练样本的大小比较小时,如 m ⩽ 2000 m⩽2000 m⩽2000时 —— 选择batch梯度下降法;
- 如果训练样本的大小比较大时,典型的大小为:
2 6 、 2 7 、 ⋯ 、 2 10 2^{6}、2^{7}、\cdots、2^{10} 26、27、⋯、210 - Mini-batch的大小要符合CPU/GPU内存。
2.2 指数加权平均
指数加权平均的关键函数:
v
t
=
β
v
t
−
1
+
(
1
−
β
)
θ
t
v_{t} = \beta v_{t-1}+(1-\beta)\theta_{t}
vt=βvt−1+(1−β)θt
下图是一个关于天数和温度的散点图:
当
β
=
0.9
β=0.9
β=0.9时,指数加权平均最后的结果如图中红色线所示;
当
β
=
0.98
β=0.98
β=0.98时,指数加权平均最后的结果如图中绿色线所示;
当
β
=
0.5
β=0.5
β=0.5时,指数加权平均最后的结果如下图中黄色线所示;
理解指数加权平均
例子,当 β = 0.9 β=0.9 β=0.9时:
v 100 = 0.9 v 99 + 0.1 θ 100 v 99 = 0.9 v 98 + 0.1 θ 99 v 98 = 0.9 v 97 + 0.1 θ 98 … v_{100} = 0.9v_{99}+0.1\theta_{100}\\v_{99} = 0.9v_{98}+0.1\theta_{99}\\v_{98} = 0.9v_{97}+0.1\theta_{98}\\ \ldots v100=0.9v99+0.1θ100v99=0.9v98+0.1θ99v98=0.9v97+0.1θ98…
展开:
v
100
=
0.1
θ
100
+
0.9
(
0.1
θ
99
+
0.9
(
0.1
θ
98
+
0.9
v
97
)
)
=
0.1
θ
100
+
0.1
×
0.9
θ
99
+
0.1
×
(
0.9
)
2
θ
98
+
0.1
×
(
0.9
)
3
θ
97
+
⋯
v_{100}=0.1\theta_{100}+0.9(0.1\theta_{99}+0.9(0.1\theta_{98}+0.9v_{97}))\\=0.1\theta_{100}+0.1\times0.9\theta_{99}+0.1\times(0.9)^{2}\theta_{98}+0.1\times(0.9)^{3}\theta_{97}+\cdots
v100=0.1θ100+0.9(0.1θ99+0.9(0.1θ98+0.9v97))=0.1θ100+0.1×0.9θ99+0.1×(0.9)2θ98+0.1×(0.9)3θ97+⋯
上式中所有θθ前面的系数相加起来为1或者接近于1,称之为偏差修正。
总体来说存在, ( 1 − ε ) 1 / ε = 1 e (1-\varepsilon)^{1/\varepsilon}=\dfrac{1}{e} (1−ε)1/ε=e1,在我们的例子中, 1 − ε = β = 0.9 1-\varepsilon=\beta=0.9 1−ε=β=0.9,即 0. 9 10 ≈ 0.35 ≈ 1 e 0.9^{10}\approx 0.35\approx\dfrac{1}{e} 0.910≈0.35≈e1。相当于大约10天后,系数的峰值(这里是0.1)下降到原来的 1 e \dfrac{1}{e} e1,只关注了过去10天的天气。
指数加权平均实现
v
0
=
0
v
1
=
β
v
0
+
(
1
−
β
)
θ
1
v
2
=
β
v
1
+
(
1
−
β
)
θ
2
v
3
=
β
v
2
+
(
1
−
β
)
θ
3
…
v_{0} =0\\ v_{1}= \beta v_{0}+(1-\beta)\theta_{1}\\ v_{2}= \beta v_{1}+(1-\beta)\theta_{2}\\ v_{3}= \beta v_{2}+(1-\beta)\theta_{3}\\ \ldots
v0=0v1=βv0+(1−β)θ1v2=βv1+(1−β)θ2v3=βv2+(1−β)θ3…
因为,在计算当前时刻的平均值,只需要前一天的平均值和当前时刻的值,所以在数据量非常大的情况下,指数加权平均在节约计算成本的方面是一种非常有效的方式,可以很大程度上减少计算机资源存储和内存的占用。
指数加权平均的偏差修正
在我们执行指数加权平均的公式时,当
β
=
0.98
β=0.98
β=0.98时,我们得到的并不是图中的绿色曲线,而是下图中的紫色曲线,其起点比较低。
-
原因:
v 0 = 0 v 1 = 0.98 v 0 + 0.02 θ 1 = 0.02 θ 1 v 2 = 0.98 v 1 + 0.02 θ 2 = 0.98 × 0.02 θ 1 + 0.02 θ 2 = 0.0196 θ 1 + 0.02 θ 2 v_{0}=0\\v_{1}=0.98v_{0}+0.02\theta_{1}=0.02\theta_{1}\\v_{2}=0.98v_{1}+0.02\theta_{2}=0.98\times0.02\theta_{1}+0.02\theta_{2}=0.0196\theta_{1}+0.02\theta_{2} v0=0v1=0.98v0+0.02θ1=0.02θ1v2=0.98v1+0.02θ2=0.98×0.02θ1+0.02θ2=0.0196θ1+0.02θ2
如果第一天的值为如40,则得到的v1=0.02×40=0.8,则得到的值要远小于实际值,后面几天的情况也会由于初值引起的影响,均低于实际均值。 -
偏差修正:
使用 v t 1 − β t \dfrac{v_{t}}{1-\beta^{t}} 1−βtvt- 当t=2时:
1 − β t = 1 − ( 0.98 ) 2 = 0.0396 1-\beta^{t}=1-(0.98)^{2}=0.0396 1−βt=1−(0.98)2=0.0396
v 2 0.0396 = 0.0196 θ 1 + 0.02 θ 2 0.0396 \dfrac{v_{2}}{0.0396}=\dfrac{0.0196\theta_{1}+0.02\theta_{2}}{0.0396} 0.0396v2=0.03960.0196θ1+0.02θ2
偏差修正得到了绿色的曲线,在开始的时候,能够得到比紫色曲线更好的计算平均的效果。随着 t t t逐渐增大, β t β^t βt接近于0,所以后面绿色的曲线和紫色的曲线逐渐重合了。
- 当t=2时:
虽然存在这种问题,但是在实际过程中,一般会忽略前期均值偏差的影响,因为经过几次迭代训练偏差基本消失。
2.3 动量(Momentum)梯度下降法
动量梯度下降的基本思想就是计算梯度的指数加权平均数,并利用该梯度来更新权重。
在我们优化 Cost function 的时候,以下图所示的函数图为例:
在利用梯度下降法来最小化该函数的时候,每一次迭代所更新的代价函数值如图中蓝色线所示在上下波动,而这种幅度比较大波动
,减缓了梯度下降的速度,而且我们只能使用一个较小的学习率
来进行迭代。
如果用较大的学习率,结果可能会如紫色线一样偏离函数的范围,所以为了避免这种情况,只能用较小的学习率。
但是我们又希望在如图的纵轴方向梯度下降的缓慢一些,不要有如此大的上下波动,在横轴方向梯度下降的快速一些,使得能够更快的到达最小值点,而这里用动量梯度下降法既可以实现,如红色线所示。
算法实现
β β β常用的值是0.9。
在我们进行动量梯度下降算法的时候,由于使用了指数加权平均的方法。原来在纵轴方向上的上下波动,经过平均以后,接近于0,纵轴上的波动变得非常的小
;但在横轴方向上,所有的微分都指向横轴方向,因此其平均值仍然很大
。最终实现红色线所示的梯度下降曲线。
算法本质解释
在对应上面的计算公式中,将Cost function想象为一个碗状,想象从顶部往下滚球,其中:
- 微分项 d w , d b dw,db dw,db想象为球提供的加速度;
- 动量项 v d w , v d b v_{dw},v_{db} vdw,vdb相当于速度;
小球在向下滚动的过程中,因为加速度的存在速度会变快,但是由于 β β β的存在,其值小于1,可以认为是摩擦力,所以球不会无限加速下去。
2.4 RMSprop
除了上面所说的Momentum梯度下降法,RMSprop(root mean square prop)也是一种可以加快梯度下降的算法。
同样算法的样例实现如下图所示:
这里假设参数 b b b的梯度处于纵轴方向,参数 w w w的梯度处于横轴方向(当然实际中是处于高维度的情况),利用 R M S p r o p RMSprop RMSprop算法,可以减小某些维度梯度更新波动较大的情况,如图中蓝色线所示,使其梯度下降的速度变得更快,如图绿色线所示。
在如图所示的实现中,RMSprop将微分项进行平方,然后使用平方根进行梯度更新,同时为了确保算法不会除以0,平方根分母中在实际使用会加入一个很小的值如 ε = 1 0 − 8 \varepsilon=10^{-8} ε=10−8。
1.5 Adam 优化算法
Adam 优化算法的基本思想就是将 Momentum 和 RMSprop 结合起来形成的一种适用于不同深度学习结构的优化算法。
算法实现
- 初始化: V d w = 0 , S d w = 0 , V d b = 0 , S d b = 0 V_{dw} = 0,S_{dw}=0,V_{db}=0,S_{db} = 0 Vdw=0,Sdw=0,Vdb=0,Sdb=0
- 第t次迭代:
- Compute d w dw dw, d b db db on the current mini-batch
- V d w = β 1 V d w + ( 1 − β 1 ) d w , V d b = β 1 V d b + ( 1 − β 1 ) d b V_{dw}=\beta_{1}V_{dw}+(1-\beta_{1})dw,V_{db}=\beta_{1}V_{db}+(1-\beta_{1})db Vdw=β1Vdw+(1−β1)dw,Vdb=β1Vdb+(1−β1)db Momentum
- S d w = β 2 S d w + ( 1 − β 2 ) ( d w ) 2 , S d b = β 2 S d b + ( 1 − β 2 ) ( d b ) 2 S_{dw}=\beta_{2}S_{dw}+(1-\beta_{2})(dw)^{2},S_{db}=\beta_{2}S_{db}+(1-\beta_{2})(db)^{2} Sdw=β2Sdw+(1−β2)(dw)2,Sdb=β2Sdb+(1−β2)(db)2 RMSprop
- V d w c o r r e c t e d = V d w / ( 1 − β 1 t ) , V d b c o r r e c t e d = V d b / ( 1 − β 1 t ) V_{dw}^{corrected} = V_{dw}/(1-\beta_{1}^{t}),V_{db}^{corrected} = V_{db}/(1-\beta_{1}^{t}) Vdwcorrected=Vdw/(1−β1t),Vdbcorrected=Vdb/(1−β1t) 偏差修正
- S d w c o r r e c t e d = S d w / ( 1 − β 2 t ) , S d b c o r r e c t e d = S d b / ( 1 − β 2 t ) S_{dw}^{corrected} = S_{dw}/(1-\beta_{2}^{t}),S_{db}^{corrected} = S_{db}/(1-\beta_{2}^{t}) Sdwcorrected=Sdw/(1−β2t),Sdbcorrected=Sdb/(1−β2t) 偏差修正
- w : = w − α V d w c o r r e c t e d S d w c o r r e c t e d + ε , b : = b − α V d b c o r r e c t e d S d b c o r r e c t e d + ε w:=w-\alpha\dfrac{V_{dw}^{corrected}}{\sqrt{S_{dw}^{corrected}}+\varepsilon},b:=b-\alpha\dfrac{V_{db}^{corrected}}{\sqrt{S_{db}^{corrected}}+\varepsilon} w:=w−αSdwcorrected+εVdwcorrected,b:=b−αSdbcorrected+εVdbcorrected
超参数的选择
α
α
α:需要进行调试;
β
1
β_1
β1:常用缺省值为0.9,
d
w
dw
dw的加权平均;
β
2
β_2
β2:推荐使用0.999,
d
w
2
dw^2
dw2的加权平均值;
ε
ε
ε:推荐使用
1
0
−
8
10^{-8}
10−8。
Adam代表的是Adaptive Moment Estimation。
1.6 学习率衰减
在我们利用 mini-batch 梯度下降法来寻找Cost function的最小值的时候,如果我们设置一个固定的学习速率αα,则算法在到达最小值点附近后,由于不同batch中存在一定的噪声,使得不会精确收敛,而一直会在一个最小值点较大的范围内波动,如下图中蓝色线所示。
但是如果我们使用学习率衰减,逐渐减小学习速率αα,在算法开始的时候,学习速率还是相对较快,能够相对快速的向最小值点的方向下降。但随着αα的减小,下降的步伐也会逐渐变小,最终会在最小值附近的一块更小的区域里波动,如图中绿色线所示。
学习率衰减的实现
- 常用:
α = 1 1 + d e c a y _ r a t e ∗ e p o c h _ n u m α 0 \alpha = \dfrac{1}{1+decay\_rate*epoch\_num}\alpha_{0} α=1+decay_rate∗epoch_num1α0 - 指数衰减:
α = 0.9 5 e p o c h _ n u m α 0 \alpha = 0.95^{epoch\_num}\alpha_{0} α=0.95epoch_numα0 - 其他:
α = k e p o c h _ n u m ⋅ α 0 \alpha = \dfrac{k}{epoch\_num}\cdot\alpha_{0} α=epoch_numk⋅α0 - 离散下降(不同阶段使用不同的学习速率)
1.6 局部最优问题
在低纬度的情形下,我们可能会想象到一个Cost function 如左图所示,存在一些局部最小值点,在初始化参数的时候,如果初始值选取的不得当,会存在陷入局部最优点的可能性。
但是,如果我们建立一个神经网络,通常梯度为零的点,并不是如左图中的局部最优点,而是右图中的鞍点(叫鞍点是因为其形状像马鞍的形状)。
在一个具有高维度空间的函数中,如果梯度为0,那么在每个方向,Cost function可能是凸函数,也有可能是凹函数。但如果参数维度为2万维,想要得到局部最优解,那么所有维度均需要是凹函数,其概率为
2
−
20000
2^{-20000}
2−20000,可能性非常的小。也就是说,在低纬度中的局部最优点的情况,并不适用于高纬度,我们在梯度为0的点更有可能是鞍点。
在高纬度的情况下:
- 几乎不可能陷入局部最小值点;
- 处于鞍点的停滞区会减缓学习过程,利用如Adam等算法进行改善。