参考资料:http://blog.csdn.net/uestc_c2_403/article/details/74910107
https://zhuanlan.zhihu.com/p/21387326?refer=intelligentunit
在之前的博客 Coursera 机器学习(by Andrew Ng)课程学习笔记 Week 1——简单的线性回归模型和梯度下降我们已经介绍了损失函数和梯度下降的概念。这一部分我们会更加详细介绍这一部分。
计算梯度
对于一个函数来说,通常有两种计算梯度的方法:(1)数值梯度法和(2)分析梯度法。数值梯度法实现相对简单,但求得的通常是近似解,同时求解速度很慢。而分析梯度法计算迅速,结果精确,但是实现时容易出错,且需要使用微分。现在对两种方法进行介绍:
数值梯度法
对于函数
J(Θ)
在
Θ
出的梯度,数学定义是:
其近似解就可以取:
通常 epsilon 取很小的值。例如 10−4 。
epsilon = 1e-4;
for i = 1:n,
thetaPlus = theta;
thetaPlus(i) += epsilon;
thetaMinus = theta;
thetaMinus(i) -= epsilon;
gradApprox(i) = (J(thetaPlus) - J(thetaMinus))/(2*epsilon)
end;
分析梯度法
对函数进行微分求出梯度,例如SVM在某个数据点的损失函数:
可以对函数进行微分。比如,对 wyi 进行微分得到:
其中1是一个示性函数,如果括号中的条件为真,那么函数值为1,如果为假,则函数值为0。虽然上述公式看起来复杂,但在代码实现的时候比较简单:只需要计算没有满足边界值的分类的数量(因此对损失函数产生了贡献),然后乘以 xi 就是梯度了。注意,这个梯度只是对应正确分类的W的行向量的梯度,那些 j≠yi 行的梯度是:
一旦将梯度的公式微分出来,代码实现公式并用于梯度更新就比较顺畅了。
梯度检验
从上面可以看出数值梯度法计算梯度比较简单,但缺点在于终究只是近似,且耗费计算资源太多。微分梯度法是利用微分来分析,能得到计算梯度的公式(不是近似),用公式计算梯度速度很快,唯一不好的就是实现的时候容易出错。为了解决这个问题,在实际操作时常常将分析梯度法的结果和数值梯度法的结果作比较,以此来检查其实现的正确性,这个步骤叫做梯度检验。
在Coursera 机器学习(by Andrew Ng)课程学习笔记 Week 5——神经网络(二)中我们曾经提到过梯度检验的概念。为了确认代码中反向传播计算的梯度是否正确,可以采用梯度检验(gradient check)的方法。通过计算数值梯度,得到梯度的近似值,然后和反向传播得到的梯度进行比较,若两者相差很小的话则证明反向传播的代码是正确无误的。
三种梯度下降方法对比
【此处参考博客 三种梯度下降的方式:批量梯度下降、小批量梯度下降、随机梯度下降】
批量梯度下降法(Batch Gradient Descent,简称BGD)是梯度下降法最原始的形式,它的具体思路是在更新每一参数时都使用所有的样本来进行更新,也就是方程中的m表示样本的所有个数。
优点:全局最优解;易于并行实现;
缺点:当样本数目很多时,训练过程会很慢。
随机梯度下降法:它的具体思路是在更新每一参数时都使用一个样本来进行更新,也就是方程中的m等于1。每一次跟新参数都用一个样本,更新很多次。如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次,这种跟新方式计算复杂度太高。
但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
优点:训练速度快;
缺点:准确度下降,并不是全局最优;不易于并行实现。
从迭代的次数上来看,SGD迭代的次数较多,在解空间的搜索过程看起来很盲目。
小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD):它的具体思路是在更新每一参数时都使用一部分样本来进行更新,也就是方程(1)中的m的值大于1小于所有样本的数量。
为了克服上面两种方法的缺点,又同时兼顾两种方法的优点。
三种方法使用的情况:
如果样本量比较小,采用批量梯度下降算法。如果样本太大,或者在线算法,使用随机梯度下降算法。在实际的一般情况下,采用小批量梯度下降算法。