batch 梯度下降法(批梯度下降法,我们之前一直使用的梯度下降法)是最常用的梯度下降形式,即同时处理整个训练集。其在更新参数时使用所有的样本来进行更新。简单来说就是指它在每一次迭代时使用所有样本来进行梯度的更新。
从数学上理解如下:
对整个训练集进行梯度下降法的时候,我们必须处理整个训练数据集,然后才能进行一步梯度下降,即每一步梯度下降法需要对整个训练集进行一次处理,如果训练数据集很大的时候,处理速度就会比较慢, 因为每次迭代都要对所有样本进行进行求和运算和矩阵运算。
但是如果每次处理训练数据的一部分即进行梯度下降法,则我们的算法速度会执行的更快。而处理的这些一小部分训练子集即称为 mini-batch。
Mini-Batch 梯度下降法(小批量梯度下降法)每次同时处理单个的 mini-batch,把m个训练样本分成若干个子集,称为mini-batches,这样每个子集包含的数据量就小了,例如只有1000,然后每次在单一子集上进行神经网络训练,速度就会大大提高。其他与 batch 梯度下降法一致。
假设总的训练样本个数m=5000000,其维度为 ( n x , m ) (n_x,m) (nx,m)。将其分成5000个子集,每个mini-batch含有1000个样本。我们将每个mini-batch记为 X X X{ t t t},其维度为 ( n x , 1000 ) (n_x,1000) (nx,1000)。相应的每个mini-batch的输出记为 Y Y Y{ t t t},其维度为 ( 1 , 1000 ) (1,1000) (1,1000),且 t = 1 , 2 , ⋯ , 5000 t = 1 , 2 , ⋯ , 5000 t=1,2,⋯,5000t=1,2,⋯,5000 t=1,2,⋯,5000t=1,2,⋯,5000。
这里总结一下神经网络中几类字母上标的含义:
Mini-batches Gradient Descent的实现过程是先将总的训练样本分成T个子集(mini-batches),然后对每个mini-batch进行神经网络训练, 包括Forward Propagation,Compute Cost Function,Backward Propagation,循环至T个mini-batch都训练完毕。
经过T次循环之后,所有m个训练样本都进行了梯度下降计算。这个过程,我们称之为经历了一个epoch(对整个训练集的一次遍历)。由上述伪代码可知,在中Mini-Batches Gradient Descent,一个epoch会进行T次梯度下降算法。而我们之前学过的Batch Gradient Descent中,一个epoch只进行一次梯度下降算法。
值得一提的是,对于Mini-Batches Gradient Descent,可以进行多次epoch训练。而且,每次epoch,最好是将总体训练数据重新打乱、重新分成T组mini-batches,这样有利于训练出最佳的神经网络模型。
Batch gradient descent和Mini-batch gradient descent的cost曲线如下图所示:
对于一般的神经网络模型,使用Batch gradient descent,随着迭代次数增加,cost是不断减小的。然而,使用Mini-batch gradient descent,随着在不同的mini-batch上迭代训练,其cost不是单调下降,而是受类似noise的影响,出现振荡。但整体的趋势是下降的,最终也能得到较低的cost值。
之所以出现细微振荡的原因是不同的mini-batch之间是有差异的。例如可能第一个子集( X X X{ 1 1 1}, Y Y Y{ 1 1 1})是好的子集,而第二个子集( X X X{ 2 2 2}, Y Y Y{ 2 2 2})包含了一些噪声noise。出现细微振荡是正常的。
我们来比较一下Batch gradient descent和Stachastic gradient descent的梯度下降曲线。如下图所示,蓝色的线代表Batch gradient descent,紫色的线代表Stachastic gradient descent。
Batch gradient descent会比较平稳地接近全局最小值,但是因为使用了所有m个样本,每次前进的速度有些慢。Stachastic gradient descent每次前进速度很快,但是路线曲折,有较大的振荡,最终会在最小值附近来回波动,难以真正达到最小值处。而且在数值处理上就不能使用向量化的方法来提高运算速度。
Batch梯度下降法:
随机梯度下降法:
因此,选择一个1 < size < m
的合适的大小进行 Mini-batch 梯度下降,可以实现快速学习,也应用了向量化带来的好处,且成本函数的下降处于前两者之间。
一般来说,如果总体样本数量m不太大时,例如
m
≤
2000
m≤2000
m≤2000,建议直接使用Batch gradient descent。如果总体样本数量m很大时,建议将样本分成许多mini-batches。推荐常用的mini-batch size为64,128,256,512。
这些都是2的幂。之所以这样设置的原因是计算机存储数据一般是2的幂,这样设置可以提高运算速度。
mini-batch gradient descent的梯度下降曲线如下图绿色所示,每次前进速度较快,且振荡较小,基本能接近全局最小值。
mini-batch 的大小也是一个重要的超变量,需要根据经验快速尝试,找到能够最有效地减少成本函数的值。
获得mini-batch 的步骤:① 将数据集打乱;② 按照既定的大小分割数据集。
其中打乱数据集的代码为:
m = X.shape[1] permutation = list(np.random.permutation(m)) shuffled_X = X[:, permutation] shuffled_Y = Y[:, permutation].reshape((1,m))
np.random.permutation
的含义:如果传给permutation一个矩阵,它会返回一个洗牌后的矩阵副本;而shuffle只是对一个矩阵进行洗牌,没有返回值。
该部分我们将介绍指数加权平均(Exponentially weighted averages)的概念。首先举个例子,记录半年内伦敦市的气温变化,并在二维平面上绘制出来,如下图所示:
看上去,温度数据似乎有noise,而且抖动较大。如果我们希望看到半年内气温的整体变化趋势,可以通过移动平均(moving average)的方法来对每天气温进行平滑处理。
例如我们可以设 V 0 = 0 V_0=0 V0=0,当成第0天的气温值。
第一天的气温与第0天的气温有关:
V
1
=
0.9
V
0
+
0.1
θ
1
V_1 = 0.9V_0 + 0.1θ_1
V1=0.9V0+0.1θ1
第二天的气温与第一天的气温有关:
V
2
=
0.9
V
1
+
0.1
θ
2
=
0.9
(
0.9
V
0
+
0.1
θ
1
)
+
0.1
θ
2
=
0.
9
2
V
0
+
0.9
⋅
0.1
θ
1
+
0.1
θ
2
V_2 = 0.9V_1 + 0.1θ_2 = 0.9(0.9V_0 + 0.1θ_1) + 0.1θ_2 = 0.9^2V_0 + 0.9·0.1θ_1 + 0.1θ_2
V2=0.9V1+0.1θ2=0.9(0.9V0+0.1θ1)+0.1θ2=0.92V0+0.9⋅0.1θ1+0.1θ2
第三天的气温与第二天的气温有关:
V
3
=
0.9
V
2
+
0.1
θ
3
=
0.9
(
0.
9
2
V
0
+
0.9
⋅
0.1
θ
1
+
0.1
θ
2
)
+
0.1
θ
3
=
0.
9
3
V
0
+
0.
9
2
⋅
0.1
θ
1
+
0.9
⋅
0.1
θ
2
+
0.1
θ
3
V_3 = 0.9V_2 + 0.1θ_3 = 0.9(0.9^2V_0 + 0.9·0.1θ_1 + 0.1θ_2) + 0.1θ_3 = 0.9^3V_0 + 0.9^2·0.1θ_1 + 0.9·0.1θ_2 + 0.1θ_3
V3=0.9V2+0.1θ3=0.9(0.92V0+0.9⋅0.1θ1+0.1θ2)+0.1θ3=0.93V0+0.92⋅0.1θ1+0.9⋅0.1θ2+0.1θ3
即第t天与第t-1天的气温迭代关系为:
经过移动平均处理得到的气温如下图红色曲线所示:
这种滑动平均算法称为指数加权平均(exponentially weighted average)。
根据之前的推导公式,其一般形式为: V t = β V_t = β Vt=β t − 1 t-1 t−1 + ( 1 − β ) θ t + (1 - β)θ_t +(1−β)θt
上面的例子中,
β
=
0.9
β=0.9
β=0.9。
β
β
β值决定了指数加权平均的天数,近似表示为:
当取权重值
β
=
0.98
β=0.98
β=0.98 时,可以得到图中更为平滑的绿色曲线。而当取权重值
β
=
0.5
β=0.5
β=0.5 时,得到图中噪点更多的黄色曲线。
β
β
β 越大相当于求取平均利用的天数越多,曲线自然就会越平滑而且越滞后。
简单解释为什么用上面的公式表示指数加权平均的天数:
我们将指数加权平均公式的一般形式写下来:
观察上面这个式子,
θ
θ
θ
t
t
t,
θ
θ
θ
t
−
1
t-1
t−1,
θ
θ
θ
t
−
2
t-2
t−2,…,
θ
θ
θ
1
1
1是原始数据值,
(
1
−
β
)
(1 - β)
(1−β),
(
1
−
β
)
β
(1 - β)β
(1−β)β,
(
1
−
β
)
β
2
(1 - β)β^2
(1−β)β2,…,
(
1
−
β
)
β
(1 - β)β
(1−β)βt-1类似指数曲线,从右向左呈指数下降的。
V
t
V_t
Vt 的值就是这两个式子的点乘。将原始数据值与衰减指数点乘,相当于做了指数衰减,离得越近,影响越大,离得越远,影响越小,衰减越厉害。
我们已经知道了指数加权平均的递推公式。实际应用中,为了减少内存的使用,我们可以使用这样的语句来实现指数加权平均算法:
上文中提到当
β
=
0.98
β=0.98
β=0.98 时,指数加权平均结果如下图绿色曲线所示。但是实际上,真实曲线如紫色曲线所示。
我们注意到,紫色曲线与绿色曲线的区别是,紫色曲线开始的时候相对较低一些。这是因为开始时我们设置
V
0
=
0
V_0 = 0
V0=0,所以初始值会相对小一些,直到后面受前面的影响渐渐变小,趋于正常。
修正这种问题的方法是进行偏移校正(bias correction),即在每次计算完
V
t
V_t
Vt 后,对
V
t
V_t
Vt 进行下式处理:
在刚开始的时候,t 比较小,
(
1
−
β
t
)
<
1
(1−β^t)<1
(1−βt)<1,这样就将
V
t
V_t
Vt 修正得更大一些,效果是把紫色曲线开始部分向上提升一些,与绿色曲线接近重合。随着t增大,
(
1
−
β
t
)
≈
1
(1−β^t)≈1
(1−βt)≈1,
V
t
V_t
Vt 基本不变,紫色曲线与绿色曲线依然重合。这样就实现了简单的偏移校正,得到我们希望的绿色曲线。
值得一提的是,机器学习中,偏移校正并不是必须的。因为,在迭代一次次数后(t较大), V t V_t Vt 受初始值影响微乎其微,紫色曲线与绿色曲线基本重合。所以,一般可以忽略初始迭代过程,等到一定迭代之后再取值,这样就不需要进行偏移校正了。
动量梯度下降(Gradient Descent with Momentum)是在每次训练时,对梯度进行指数加权平均处理,然后用得到的梯度值更新权重
W
W
W 和常数项
b
b
b 。
原始的梯度下降算法如上图蓝色折线所示。在梯度下降过程中,梯度下降的振荡较大,尤其对于W、b之间数值范围差别较大的情况。此时每一点处的梯度只与当前方向有关,产生类似折线的效果,前进缓慢。而如果对梯度进行指数加权平均,这样使当前梯度不仅与当前方向有关,还与之前的方向有关, 这样处理让梯度前进方向更加平滑,减少振荡,能够更快地到达最小值处。而使用动量梯度下降时,通过累加过去的梯度值来减少抵达最小值路径上的波动,加速了收敛,因此在横轴方向下降得更快,从而得到图中红色的曲线。
权重
W
W
W 和常数项
b
b
b 的指数加权平均表达式分别为:
V
V
V
d
W
dW
dW
=
β
=β
=β·
V
V
V
d
W
dW
dW
+
(
1
−
β
)
+ (1 - β)
+(1−β)·
d
W
dW
dW、
V
V
V
d
b
db
db
=
β
=β
=β·
V
V
V
d
b
db
db
+
(
1
−
β
)
+ (1 - β)
+(1−β)·
d
b
db
db
从动量的角度来看,以权重 W W W为例, V V V d W dW dW可以成速度 V V V, d W dW dW可以看成是加速度 a a a。指数加权平均实际上是计算当前的速度,当前速度由之前的速度和现在的加速度共同影响。而 β < 1 β<1 β<1,又能限制速度 V V V d W dW dW过大。也就是说,当前的速度是渐变的,而不是瞬变的,是动量的过程。这保证了梯度下降的平稳性和准确性,减少振荡,较快地达到最小值处。
动量梯度下降算法的过程如下:
初始时,令
V
V
V
d
W
dW
dW
=
0
=0
=0,
V
V
V
d
b
db
db
=
0
=0
=0。其中,将动量衰减参数 β 设置为 0.9 是超参数的一个常见且效果不错的选择。当 β 被设置为 0 时,显然就成了 batch 梯度下降法。
当前后梯度方向一致时,动量梯度下降能够加速学习;而前后梯度方向不一致时,动量梯度下降能够抑制震荡。 另外,在 10 次迭代之后,移动平均已经不再是一个具有偏差的预测。因此实际在使用梯度下降法或者动量梯度下降法时,不会同时进行偏差修正。
RMSProp(Root Mean Square Propagation,均方根传播)算法是在对梯度进行指数加权平均的基础上,引入平方和平方根。它是另外一种优化梯度下降速度的算法。每次迭代训练过程中,其权重
W
W
W和常数项
b
b
b的更新表达式为:
下面简单解释一下RMSprop算法的原理,仍然以下图为例,为了便于分析,令水平方向为W的方向,垂直方向为b的方向。
总得来说,就是如果哪个方向振荡大,就减小该方向的更新速度,从而减小振荡。
还有一点需要注意的是为了避免RMSprop算法中分母为零,通常可以在分母增加一个极小的常数
ε
ε
ε:
其中,
ε
=
10
ε = 10
ε=10-8,或者其他较小值,是为了防止分母为0或者分母太小导致的数值不稳定。
RMSProp 有助于减少抵达最小值路径上的摆动,并允许使用一个更大的学习率 α α α,从而加快算法学习速度。并且,它和 下一小节要说的Adam 优化算法已被证明适用于不同的深度学习网络结构。注意,这里的 β β β 也是一个超参数。
Adam 优化算法(Adaptive Moment Estimation,自适应矩估计)基本上就是将 Momentum 和 RMSProp 算法结合在一起,通常有超越二者单独时的效果。其算法流程如下:
首先进行初始化。然后用每一个 mini-batch 计算
d
W
、
d
b
dW、db
dW、db,每次迭代都计算
V
V
V
d
W
dW
dW、
V
V
V
d
b
db
db、
S
S
S
d
W
dW
dW、
S
S
S
d
b
db
db。一般使用 Adam 算法时需要计算偏差修正,后面使用的都是修正后的
V
V
V
d
W
dW
dW、
V
V
V
d
b
db
db、
S
S
S
d
W
dW
dW、
S
S
S
d
b
db
db。最后,用修正后的值更新
W
、
b
W、b
W、b。
Adam 优化算法有很多的超参数,其中:
β 1 β1 β1、 β 2 β2 β2、 ϵ ϵ ϵ通常不需要调试。
减小学习因子 α 也能有效提高神经网络训练速度,这种方法被称为learning rate decay。
Learning rate decay就是随着迭代次数增加,学习因子 α 逐渐减小。下面用图示的方式来解释这样做的好处。下图中,蓝色折线表示使用恒定的学习因子 α,由于每次训练 α 相同,步进长度不变,在接近最优值处的振荡也大,在最优值附近较大范围内振荡,与最优值距离就比较远。绿色折线表示使用不断减小的 α,随着训练次数增加,α 逐渐减小,步进长度减小,使得能够在最优值处较小范围内微弱振荡,不断逼近最优值。 相比较恒定的α 来说,learning rate decay更接近最优值。
Learning rate decay中对α可由下列公式得到:
其中,deacy_rate是参数(可调),epoch是训练完所有样本的次数。随着epoch增加,α会不断变小。
除了上面计算α的公式之外,还有其它可供选择的计算公式:
对于较小的模型,也有人会在训练时根据进度手动调小学习率。
在使用梯度下降算法不断减小cost function时,可能会得到局部最优解(local optima)而不是全局最优解(global optima)。之前我们对局部最优解的理解是形如碗状的凹槽,如下图左边所示。但是在神经网络中,local optima的概念发生了变化。准确地来说,大部分梯度为零的“最优点”并不是这些凹槽处,而是形如右边所示的马鞍状,称为saddle point。 也就是说,梯度为零并不能保证都是convex(极小值),也有可能是concave(极大值)。特别是在神经网络中参数很多的情况下,所有参数梯度为零的点很可能都是右边所示的马鞍状的saddle point,而不是左边那样的local optimum。
鞍点(saddle point)这个词来自
z
=
x
2
−
y
2
z = x^2 - y^2
z=x2−y2 的图形,在x轴方向向上曲,在y轴方向向下曲,像马鞍,鞍点为(0,0)。
拥有两个以上参数的函数。它的曲面在鞍点好像一个马鞍,在某些方向往上曲,在其他方向往下曲。在一幅等高线图里,一般来说,当两个等高线圈圈相交叉的地点,就是鞍点。拓展到神经网络优化问题中的鞍点即一个维度向上倾斜且另一维度向下倾斜的点。
在鞍点附近,基于梯度的优化算法(几乎目前所有的实际使用的优化算法都是基于梯度的)会遇到较为严重的问题:算法很难脱离鞍点区域,可能会长时间卡在该点附近(因为梯度在所有维度上接近于零)。
类似马鞍状的plateaus会降低神经网络学习速度。Plateaus是梯度接近于零的平缓区域,如下图所示。在plateaus上梯度很小,前进缓慢,到达saddle point需要很长时间。到达saddle point后,由于随机扰动,梯度一般能够沿着图中绿色箭头,离开saddle point,继续前进,只是在plateaus上花费了太多时间。
总结:
参考文章:
Coursera吴恩达《优化深度神经网络》课程笔记(2)-- 优化算法、优化算法、【深度学习】鞍点