概要
本篇博客主要讲解了BP算法和BGD、SGD和MBGD三种梯度下降算法。本篇博客很多数学符号请参考机器学习(周志华)——神经网络模型(一)。对于BP神经网络算法的手写代码请移步:利用BP神经网络对语音特征信号数据集进行分类
1.BP算法
误差反向传播(Error Back Propagation )算法简称BP算法,该算法在神经网络发展史起着至关重要的作用。虽然神经网络之所以在深度学习和人工智能领域应用如此之广,很大程度上BP算法起到了关键性的引领作用。虽然20世纪40年中后期神经网络方面研究开始兴起,期间神经元模型、感知器的先后提出给神经网络研究带来了巨大的发展。但是受限于当时计算机的计算性能与硬件技术的落后,这让神经网络的研究陷入低谷。直至1974年BP算法的提出与1986年BP神经网络的提出,才让神经网络的研究在此复苏。尽管之后神经网络的研究再次陷入低谷,但是BP算法自提出以后就成为所有神经网络的超参数更新的核心算法。下面是BP算法的主要流程。
在BP神经网络中,BP算法的主要思想是:先将输入数据提供给输入层神经元,然后逐层将信号前传,直到产生输出层的结果,然后利用真实结果与预测结果计算输出层的误差,再讲误差依次逆向传播到隐藏层神经元和输入层神经元,最后根据误差分别输出层阈值、隐藏层与输出层连接权重、隐藏层阈值、输入层与隐藏层连接权重进行调整。该迭代过程循环进行,直到某种停止条件位置。下面给出整个算法伪码描述。
从上述算法流程可以看出,BP算法的实质就是利用预测值与真实值之间差异,结合梯度下降算法对神经网络的连接权重与阈值进行反复调整直至误差收敛到可接受范围内,使预测输出无限接近真实输出。在参数调整过程当中,梯度下降算法起到决定向作用。因此,有必要对梯度下降算法进行详细介绍。
2.梯度下降算法
首先定义BP神经网络的损失函数为:
E=12∑k=1m∑j=1l(y^(k)j−y(k)j)2=∑k=1m12∑j=1l(y^(k)j−y(k)j)2=∑k=1mEk(1)(2)(3)
其中
m
为数据集规模,
l
为输出层神经元个数。我们的目标就是让损失函数
Ek
取得最小值。神经网络中的BP算法主要是依靠梯度下降(Gradient Descent)策略[43],以目标的负梯度方向对参数进行调整,对于上述的损失函数
Ek
,给定学习率
η
,梯度下降算法中的任意参数
ν
的更新公式如式(4-2)所示:
ν=ν+ηΔν(4)
本文以隐藏层与输出层的连接权重更新为例,那么有如下公式:
△w(h)j=−∂Ek∂w(h)j(5)
注意到
w(h)j
先影响到第
j
个输出层神经元的输入值
β(j)
,再影响其输出值
y^(j)k
,然后影响到
Ek
,根据求导的链式法则有:
∂Ek∂w(h)j=∂Ek∂y^(k)j⋅∂y^(k)j∂β(j)⋅∂β(j)∂w(h)j(6)
根据式
β(j)
的定义,显然有:
∂β(j)∂w(h)j=b(h)(7)
那么可计算得出:
gj=−∂Ek∂y^(k)j⋅f′(y^(k)j)=−(y^(k)j−y(k)j)f′(y^(k)j)=y^(k)j(1−y^(k)j)(y(k)j−y^(k)j)(8)(9)
那么就能得到BP算法中的关于
w(h)j
的更新公式:
Δw(h)j=gjb(h)(10)
类似可以得到:
Δγj=−gjΔv(i)h=ehx(i)Δθi=−eh(11)(12)(13)
其中:
eh=−∂Ek∂b(h)⋅∂b(h)∂α(h)=−∑j=1l∂Ek∂β(j)⋅∂β(j)∂b(h)f′(b(h))=∑j=1lw(h)jgjf′(b(h))=b(h)(1−b(h))∑j=1lw(h)jgj(14)(15)
2.1 批量梯度下降算法(BGD)
批量梯度下降算法(Batch Gradient Descent,BGD)的主要思想是首先对整个数据集进行遍历,保存相应参数的梯度增量。待遍历结束之后对每组数据的梯度增量进行求和后进行更新所有层与层之间的权重与阈值。通过多次迭代,BGD算法将会得到全局最优解。同时也可以得知,虽然BGD算法最终能够获得全局最优解,但是一次迭代过程中只进行一次参数更新,这使得收敛速度极其缓慢。因此在处理大型数据集时速度很慢且难以控制,甚至会因为临时保存参数梯度增量的内存过大而导致溢出。具体BGD算法流程如下所示:
Repeat until convergence {θj:=θj+η∑i=1mΔθ(i)j(for every j)}(16)(17)(18)
其中,
θj
代表需要进行优化的参数,
α
为学习率,
m
是数据个数,
Δθ(i)j
为第
i
个样本所求得的参数梯度增量。BGD算法下神经网络中各个参数的更新公式为:
w(h)j=w(h)j+η∑i=1mg(i)jb(h)γj=γj−η∑i=1mg(i)jv(i)h=v(i)h+η∑j=1me(j)hx(i)θi=θi−η∑j=1me(j)h(19)(20)(21)(22)
2.2 随机梯度下降算法(SGD)
实际中使用批梯度下降算法时,会对每一组数据进行一次权值调整,这里面涉及大量的矩阵运算而耗费大量时间。因此为了加快算法的收敛速度,随机梯度下降(Stochastic Gradient Descent,SGD)算法是一个不错的选择。
SGD算法的主要思想是在遍历整个数据集时,对每组数据分别进行一次参数更新。即对于一个含有
m
组数据的数据集,每做一次迭代得做
m
次参数更新。SGD算法的具体流程如下:
Loop { for i = 1 to m {θj:=θj+ηΔθ(i)j(for every j)}}(23)(24)(25)(26)
其中,
θj
代表需要进行优化的参数,
α
为学习率,
m
是数据个数,
Δθ(i)j
为第
i
个样本所求得的参数梯度增量。SGD算法下神经网络中各个参数的更新公式为:
w(h)j=w(h)j+ηgjb(h)γj=γj−ηgjv(i)h=v(i)h+ηehx(i)θi=θi−ηeh(27)(28)(29)(30)
然而,SGD算法也是有缺陷的。虽然与BGD算法相比,SGD算法在每次迭代中有频繁的参数更新,这加快了SGD算法收敛速度。但是,SGD算法不可能完全使损失函数 收敛到全局最小值,只能在其附近波动。同时,不管是BGD算法还是SGD算法,其本质都是贪心算法。贪心算法的本质是沿着梯度变化最大的方向寻找全局最优解。相比BGD算法,SGD算法存在大量的利用梯度增量进行参数更新,这也导致每一次更新SGD算法不一定式沿着全局最小值方向,那么这也导致了SGD算法很容易陷入局部最优解而导致过拟合。
2.3 小批量梯度下降算法(MBGD)
BGD算法能够经过多次迭代得到全局最优解。但是由于每次迭代你能够需要临时保存每组数据对应的梯度增量而带来了带量的内存开销,同时每次迭代时只进行一次参数更新使得算法收敛缓慢。即对于大规模样本的问题效率低下。SGD算法虽相较于BGD算法有更快的收敛速度,但是在收敛过程中,SGD算法会在全局最小值附近区间振荡。换句话说,SGD算法不是每次迭代沿着损失函数全局最小值方向。同时SGD算法由于参数更新次数过于频繁而更容易陷入局部最优解。
显然,BGD算法与SGD算法都有其优缺点。那么小批量梯度下降(Mini Batch Gradient Descent,MBGD)算法则是BGD算法与SGD算法的一个折中方案。该算法的主要思想是将整个数据集随机平分成若干个小样本,每次迭代过程中利用每个小样本中梯度增量的平均值进行参数更新。即当小批量样本足够大时,小样本梯度向量的平均值就能代替全局的梯度。具体分析如下。对于每个训练实例
x(i)
,都要计算梯度向量
∇C
。如果训练数据集规模过大,那么一次迭代训练会BGD算安抚花费很长时间,这直接导致了整个学习过程过慢。同时SGD算法会以过多调整超参数而容易陷入过拟合。所以实际中为了加快模型的收敛速度,通常使用小批量梯度下降算法(MBGD)来代替BGD算法与SGD算法。其基本思想:从所有训练实例中取一个小的批量样本:
x(1),x(2),⋯x(n)
,来估计梯度, 大大提高学习速度。如果样本够大则有:
1n∑j=1n∇Cx(j)≈1m∑j=1m∇Cx(j)∇C≈1n∑j=1n∇Cx(j)(31)(32)
其中 是样本总数,
n
是mini-batch中样本个数。在实际运用中利用小批量样本的平均梯度来估算整个数据集的平均梯度,从而加快模型的收敛速度。MBGD算法的算法流程如下:
m = Data Sizen = Mini Batch SizeRepeat until convergence {for i = 1 to mn:θj:=θj+ηn∑k=1nΔθ(k)j(for every j)}(33)(34)(35)(36)
那么,MBGD算法中神经网络的各个参数更新公式如下:
w(h)j=w(h)j+ηn∑i=1ng(i)jb(h)γj=γj−ηn∑i=1ng(i)jv(i)h=v(i)h+ηn∑j=1ne(j)hx(i)θi=θi−ηn∑j=1ne(j)h(37)(38)(39)(40)
2.4 三种梯度下降算法之间的联系
在2.1、2.2和2.3这三小节中所论述的三种梯度下降算法都各有优势与缺点,使用场景也不仅相同,但他们也有一定的联系与区别。在这里,本文统一神经网络中梯度下降算法的更新公式为:
θj:=θj+ηε∑i=1mΔθ(i)j(41)
其中:
θj
为需要更新的参数,
η
为学习率,
m
为数据集规模,
Δθ(i)j
为每组数据的梯度增量,
ε
为常数。那么当
ε=1
时,这就是SGD算法;当
ε=n
,其中
1<n<m
时, 则变成MBGD算法;当
ε=m
时,则变成了BGD算法。换种说法,在同样的数据集下,BGD算法只进行一次参数更新;MBGD算法则会进行
mn
次参数更新;SGD算法会进行
m
次参数更新,其中
m
为数据集规模,
n
为小批量规模。那么理所当然收敛速度自然是
BGD<MBGD<SGD
。