赞
踩
主要参考了吴恩达老师【神经网络和深度学习】系列课程。
梯度下降是一个最优化算法,它的目的在于通过不断的迭代,快速找到目标函数的极小值点。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。
想象一下,如果一个人在山顶,想要采用最快的方式下山,不考虑是否能刹住车、会不会滚下去以及道路是否走得通的问题,他应该怎样做?我想,他站在当前位置时,首先会选取最陡峭的山路,然后迈出一步;接着不断选取最陡峭的方向迈步,最终抵达山脚最低点。
最快下山的方法和梯度下降的原理类似,我们通常关注三个方面的问题:① 从哪个方向走?② 选定方向后,该走多远?以及③ 如何度量模型好坏?
① 首先,如果我们将目标函数视为一座山,我们需要根据当前的坐标点,找到最陡峭的方向,即在梯度下降(GD)中,我们首先要计算梯度,定义如下所示。
在微积分里面,对多元函数的参数求 ∂ ∂ ∂ 偏导数,把求得的各个参数的偏导数以向量的形式写出,就是梯度。比如函数 f ( x , y ) f(x,y) f(x,y),分别对 x , y x,y x,y求偏导数,求得的梯度向量就是 ( ∂ f / ∂ x , ∂ f / ∂ y ) T (∂f/∂x, ∂f/∂y)^T (∂f/∂x,∂f/∂y)T,简称 g r a d grad grad f ( x , y ) f(x,y) f(x,y)或者 ▽ f ( x , y ) ▽f(x,y) ▽f(x,y)。对于在点 ( x 0 , y 0 ) (x0,y0) (x0,y0)的具体梯度向量就是 ( ∂ f / ∂ x 0 , ∂ f / ∂ y 0 ) T (∂f/∂x0, ∂f/∂y0)^T (∂f/∂x0,∂f/∂y0)T或者 ▽ f ( x 0 , y 0 ) ▽f(x0,y0) ▽f(x0,y0)。如果是3个参数的向量梯度,就是 ( ∂ f / ∂ x , ∂ f / ∂ y , ∂ f / ∂ z ) T (∂f/∂x, ∂f/∂y,∂f/∂z)^T (∂f/∂x,∂f/∂y,∂f/∂z)T,以此类推。
我们发现,计算出来的梯度是一个向量,它指向了函数变化增加最快的地方。所以我们想要找到最小值的话,就需要向梯度的负方向前进,就能更快地找到函数的最小值。
② 其次,在明确方向,即当前节点梯度的负方向后,我们需要考虑,该走多远?这就涉及到了学习率(Learning rate)或者步长 α α α的选择,我们用它来控制沿梯度负方向前进的长度,即每一步走的距离。
步长越大越好吗?下面这个图非常形象,源自文章《深入浅出–梯度下降法及其实现》。如果步长
α
α
α很小,那么我们将以龟速下山,虽然每一步的方向都很陡峭,但是步子太小了呀;如果步长选的很大,那么我们可能会完美错过最小点,一不小心就踏上了另外一座山峰。因此,步长的选择是一个不断调试的过程,从而选择一个恰当的中间点。
我们有时也会想到:步长难道就是一成不变的吗?我们可不可以将之设置为一个随迭代次数逐步递减的可变参数?这就涉及到了学习率衰减(Learning rate decay)。
我们可以在前期,距离最低点较远的时候,把步子迈大一点,这样下降速度相对较快;等到快要接近最低点的时候,或者是随着迭代次数的增加,我们逐步减少学习率,让它可以逐步收敛到最低点,防止在极小值点附近来回震荡。
这当然是最理想的情况,但是在实操中,我们不知道迭代多少次,它就接近了最低点,不知道什么时候降低学习率或者降低到多少才最为合适。因此,这也是一个不断调整参数的过程。
③ 最后,为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。我们在使用模型进行预测时,会得到一个预测值 y ^ \hat y y^,同时由于是监督训练,数据本身会有一个真实值预测值 y y y,损失函数就是度量二者的差距。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。
总而言之,梯度下降法的计算过程就是沿梯度下降的方向求解极小值。
梯度下降算法的迭代过程如下:
在神经网络模型的训练中,也使用到了梯度下降的方法。在刚开始构建了神经网络模型后,在更新参数时使用所有的样本来进行更新,因此它也被称为 B a t c h Batch Batch G r a d i e n t Gradient Gradient D e s c e n t Descent Descent。
那么,它是怎样训练的?假设有1000条数据。
要注意,在第三步中计算得出的梯度是整个1000条数据的平均梯度,代表着整体的下降方向,而不是其中某一条数据计算得出的下降方向。
下面给出了一个两层神经网络(一个隐藏层,一个输出层)传播过程的代码。我们发现,在计算cost
、w
、b
等参数的梯度时,全部进行了平均。
# 前向传播函数 def forward_propagation(X, w1, b1, w2, b2): Z1 = np.dot(w1, X) + b1 A1 = np.tanh(Z1) Z2 = np.dot(w2, A1) + b2 A2 = sigmoid(Z2) return Z1, A1, Z2, A2 # 计算成本函数 def compute_cost(A2, Y): m = Y.shape[1] # 训练样本个数 cost = -np.sum(Y * np.log(A2) + (1 - Y) * np.log(1 - A2)) / m cost = float(np.squeeze(cost)) return cost # 反向传播函数 def backward_propagation(X, Y, w2, A1, A2): m = X.shape[1] # 训练样本个数 dZ2 = A2 - Y dw2 = (1 / m) * np.dot(dZ2, A1.T) db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True) dZ1 = np.multiply(np.dot(w2.T, dZ2), 1 - np.power(A1, 2)) dw1 = (1 / m) * np.dot(dZ1, X.T) db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True) return dw1, db1, dw2, db2
Batch gradient descent的优点是理想状态下经过足够多的迭代后可以达到全局最优。而且参数更新的过程中,使用的是所有数据的梯度进行计算,因此下降会更加平稳,每次迭代成本都会下降,不会出现偏离极小值的情况(除非学习率选取的过大)。
BGD缺点也很明显,就是如果你的数据集非常的大,而且每次迭代都需要历遍整个训练集,所以计算过程会非常的慢。因此,在此基础上,有人提出了随机梯度下降和mini-batch的方法,对于大数据的梯度下降进行改进。
随机梯度下降法(Stochastic Gradient Decent, SGD)是对全批量梯度下降法(Batch Gradient Decent, BGD)计算效率 改进的算法。本质上来说,我们预期随机梯度下降法得到的结果和全批量梯度下降法相接近。
之前我们提到,batch梯度下降的缺点在于当数据量过大时计算过于缓慢。我们自然而然会想到,既然用所有样本整体算一个梯度会比较耗时,我们可不可以每次只用一条数据来计算梯度?这就是随机梯度下降的思想。
随机梯度下降是指在进行模型训练时,随机选取样本中的一条数据计算梯度,而不是遍历所有样本后进行参数迭代。那么,它和batch梯度下降的区别是什么?
二者的相同之处在于,在一次整体迭代中(Epoch),它们全部遍历了一次数据集,只不过遍历的方式有所不同。
batch梯度下降可以视为:对于每一条数据,计算参数梯度后,先将之保存起来;等到全部数据遍历完后,再将所有数据的梯度进行累加并且取平均,得到最终的整体梯度(不过我们一般是用向量化的方式,将之整合成为一个大矩阵,避免了for循环)。如果有100条数据,则一次完整迭代后,相当于更新了1次参数。
随机梯度下降可以视为:对于每一条数据,计算参数梯度后,立即对于参数进行更新。如果有100条数据,则一次完整迭代后,相当于更新了100次参数。
那么,随机梯度下降会收敛到极小值吗?结果证明是会的,从直觉上来看,SGD最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。
在随机梯度下降法中,每次迭代只对一个样本进行梯度下降,大部分时候向着极小值靠近。有时候也会远离极小值,因为那个样本恰好给你指的方向不对,因此随机梯度下降法有很多噪声。平均来看,它最终会靠近极小值,不过有时候也会方向错误,因为随机梯度下降法永远不会收敛,而是会一直在极小值附近波动,但它并不会在达到最小值并停留在此。
SGD的优势是更快地计算梯度。如果我们的数据很大,我们就没必要使用全部的数据,而是通过SGD快速的找到模型的较好参数。SGD所带来的波动有个好处就是,对于类似盆地区域(即很多局部极小值点),那么这个波动的特点可能会使得优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样便可能对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。
SGD的缺点在于每次只用一个样本来更新参数,会导致不稳定性大些,即每次更新不一定指向全局最优的方向。因为每次训练的都是随机的一个样本,会导致导致梯度的方向不会像BGD那样朝着最优点。如下图所示,SGD出现了很多震荡,而BGD相对较为稳定。另外一个缺点在于SGD失去所有了向量化带来的加速,因为一次性只处理了一个训练样本,这样效率过于低下。
batch梯度下降和stochastic梯度下降都太过于“激进”,前者使用全部数据进行更新,计算太慢;后者仅使用一条数据进行更新,会显得不太稳定,会反复震荡。因此自然而然就会想到,能不能将数据集进行拆分,每次对于一部分数据进行计算,既保留了数据相对多比SGD更加稳定的优势,而且相比起BGD来又计算的快?
mini-batch梯度下降便应运而生。是batch梯度下降和stochastic梯度下降的折中方案。在训练前,首先将整体数据进行拆分,每次用一部分样本来更新参数,即 batch_size。因此,若batch_size=1 则变成了SGD,若batch_size=m 则变成了BGD。
mini-batch梯度下降和SGD一样,并不是每次迭代成本函数都是下降的,但是总体趋势是朝向极小值的。产生噪声的原因在于,如果是比较容易计算的mini-batch,成本会低一些;若是出于偶然,选到了比较难运算的mini-batch,这样一来计算的成本会更高一些,所以才会出现这些摆动。
从上图中我们发现mini-batch比SGD更加稳定,mini-batch梯度下降降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定。相对于全量梯度下降,其提高了每次学习的速度。
(1) 批量梯度下降法:针对的是整个数据集,通过对所有的样本的计算来求解梯度的方向。
优点:全局最优解;易于并行实现
缺点:当样本数据很多时,计算量开销大,计算速度慢
(2) 随机梯度下降法:每个数据都计算算一下损失函数,然后求梯度更新参数。
优点:计算速度快
缺点:收敛性能不好
(3) mini-batch梯度下降:把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。
优点:减少了计算的开销量,降低了随机性
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。