http://m.blog.csdn.net/article/details?id=51188876
一、梯度下降法
在机器学习算法中,对于很多监督学习模型,需要对原始的模型构建损失函数,接下来便是通过优化算法对损失函数进行优化,以便寻找到最优的参数。在求解机器学习参数的优化算法中,使用较多的是基于梯度下降的优化算法(Gradient Descent, GD)。
梯度下降法有很多优点,其中,在梯度下降法的求解过程中,只需求解损失函数的一阶导数,计算的代价比较小,这使得梯度下降法能在很多大规模数据集上得到应用。梯度下降法的含义是通过当前点的梯度方向寻找到新的迭代点。
基本思想可以这样理解:我们从山上的某一点出发,找一个最陡的坡走一步(也就是找梯度方向),到达一个点之后,再找最陡的坡,再走一步,直到我们不断的这么走,走到最“低”点(最小花费函数收敛点)。
如上图所示,得到了局部最优解。x,y表示的是theta0和theta1,z方向表示的是花费函数,很明显出发点不同,最后到达的收敛点可能不一样。当然如果是碗状的,那么收敛点就应该是一样的。
二、梯度下降法的变形形式
在具体使用梯度下降法的过程中,主要有以下几种不同的变种,即:batch、mini-batch、SGD。其主要区别是不同的变形在训练数据的选择上。
1、批量梯度下降法BGD
批梯度下降法(Batch Gradient Descent)针对的是整个数据集,通过对所有的样本的计算来求解梯度的方向。
批量梯度下降法的损失函数为:
进一步得到批量梯度下降的迭代式为:
每迭代一步,都要用到训练集所有的数据,如果样本数目很大,那么可想而知这种方法的迭代速度!
优点:全局最优解;易于并行实现;
缺点:当样本数目很多时,训练过程会很慢。
从迭代的次数上来看,BGD迭代的次数相对较少。其迭代的收敛曲线示意图可以表示如下:
2、小批量梯度下降法MBGD
在上述的批梯度的方式中每次迭代都要使用到所有的样本,对于数据量特别大的情况,如大规模的机器学习应用,每次迭代求解所有样本需要花费大量的计算成本。是否可以在每次的迭代过程中利用部分样本代替所有的样本呢?基于这样的思想,便出现了mini-batch的概念。
假设训练集中的样本的个数为1000,则每个mini-batch只是其一个子集,假设,每个mini-batch中含有10个样本,这样,整个训练数据集可以分为100个mini-batch。伪代码如下:

3、随机梯度下降法SGD
随机梯度下降算法(stochastic gradient descent)可以看成是mini-batch gradient descent的一个特殊的情形,即在随机梯度下降法中每次仅根据一个样本对模型中的参数进行调整,等价于上述的b=1情况下的mini-batch gradient descent,即每个mini-batch中只有一个训练样本。
随机梯度下降法的优化过程为:
随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
优点:训练速度快;
缺点:准确度下降,并不是全局最优;不易于并行实现。
从迭代的次数上来看,SGD迭代的次数较多,在解空间的搜索过程看起来很盲目。其迭代的收敛曲线示意图可以表示如下:

三 通俗的理解梯度下降
(1)批量梯度下降—最小化所有训练样本的损失函数(对全部训练数据求得误差后再对参数进行更新),使得最终求解的是全局的最优解,即求解的参数是使得风险函数最小。批梯度下降类似于在山的某一点环顾四周,计算出下降最快的方向(多维),然后踏出一步,这属于一次迭代。批梯度下降一次迭代会更新所有theta,每次更新都是向着最陡的方向前进。
(2)随机梯度下降—最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。随机也就是说我用样本中的一个例子来近似我所有的样本,来调整theta,其不会计算斜率最大的方向,而是每次只选择一个维度踏出一步;下降一次迭代只更新某个theta,报着并不严谨的走走看的态度前进。
四 随机梯度下降代码
load data;
epsilon = 0.0001;
alpha = 0.001;
k = 1;
n = size(X,2);
m = size(X,1);
theta = zeros(n,1);
theta_new = zeros(n,1);
converge = 0;
while(converge==0)
for(i=1:m)
J(k) = 1/2 * (norm(X*theta - Y))^2;
for(j = 1:n)
theta_new(j) = theta(j)-alpha*(X(i,:)*theta-Y(i,:))*X(i,j);
end;
if norm(theta_new-theta) < epsilon
converge=1;
theta = theta_new;
break;
else
theta = theta_new;
k = k + 1;
end
end;
end;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
相关文献:
http://www.zhizhihu.com/html/y2011/3632.html
http://www.th7.cn/system/win/201511/142910.shtml
=======================================================
下面链接先看
http://www.cnblogs.com/python27/p/MachineLearningWeek10.html
2015-03-01 12:05
3633人阅读
收藏
举报
分类:
版权声明:本文为博主原创文章,未经博主允许不得转载。
一、回归函数及目标函数

以均方误差作为目标函数(损失函数),目的是使其值最小化,用于优化上式。

二、优化方式(Gradient Descent)
1、最速梯度下降法
也叫批量梯度下降法Batch Gradient Descent,BSD
a、对目标函数求导

b、沿导数相反方向移动theta

原因:
(1)对于目标函数,theta的移动量应当如下,其中a为步长,p为方向向量。

(2)对J(theta)做一阶泰勒级数展开:

(3)上式中,ak是步长,为正数,可知要使得目标函数变小,则
应当<0,并且其绝对值应当越大越好,这样下降的速度更快。在泰勒级数中,g代表J(theta k)的梯度,所以为了使得
为负并且绝对值最大,应当使theta的移动方向与梯度g相反。
2、随机梯度下降法(stochastic gradient descent,SGD)
SGD是最速梯度下降法的变种。
使用最速梯度下降法,将进行N次迭代,直到目标函数收敛,或者到达某个既定的收敛界限。每次迭代都将对m个样本进行计算,计算量大。
为了简便计算,SGD每次迭代仅对一个样本计算梯度,直到收敛。伪代码如下(以下仅为一个loop,实际上可以有多个这样的loop,直到收敛):

(1)由于SGD每次迭代只使用一个训练样本,因此这种方法也可用作online learning。
(2)每次只使用一个样本迭代,若遇上噪声则容易陷入局部最优解。
3、Mini-batch Gradient Descent
(1)这是介于BSD和SGD之间的一种优化算法。每次选取一定量的训练样本进行迭代。
(2)从公式上似乎可以得出以下分析:速度比BSD快,比SGD慢;精度比BSD低,比SGD高。
4、带Mini-batch的SGD
(1)选择n个训练样本(n<m,m为总训练集样本数)
(2)在这n个样本中进行n次迭代,每次使用1个样本
(3)对n次迭代得出的n个gradient进行加权平均再并求和,作为这一次mini-batch下降梯度
(4)不断在训练集中重复以上步骤,直到收敛。
=============================================
梯度下降(GD)是最小化风险函数、损失函数的一种常用方法,随机梯度下降和批量梯度下降是两种迭代求解思路,下面从公式和实现的角度对两者进行分析,如有哪个方面写的不对,希望网友纠正。
下面的h(x)是要拟合的函数,J(theta)损失函数,theta是参数,要迭代求解的值,theta求解出来了那最终要拟合的函数h(theta)就出来了。其中m是训练集的记录条数,j是参数的个数。


1、批量梯度下降的求解思路如下:
(1)将J(theta)对theta求偏导,得到每个theta对应的的梯度

(2)由于是要最小化风险函数,所以按每个参数theta的梯度负方向,来更新每个theta

(3)从上面公式可以注意到,它得到的是一个全局最优解,但是每迭代一步,都要用到训练集所有的数据,如果m很大,那么可想而知这种方法的迭代速度!!所以,这就引入了另外一种方法,随机梯度下降。
2、随机梯度下降的求解思路如下:
(1)上面的风险函数可以写成如下这种形式,损失函数对应的是训练集中每个样本的粒度,而上面批量梯度下降对应的是所有的训练样本:

(2)每个样本的损失函数,对theta求偏导得到对应梯度,来更新theta

(3)随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
3、对于上面的linear regression问题,与批量梯度下降对比,随机梯度下降求解的会是最优解吗?
(1)批量梯度下降---最小化所有训练样本的损失函数,使得最终求解的是全局的最优解,即求解的参数是使得风险函数最小。
(2)随机梯度下降---最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。
4、梯度下降用来求最优解,哪些问题可以求得全局最优?哪些问题可能局部最优解?
对于上面的linear regression问题,最优化问题对theta的分布是unimodal,即从图形上面看只有一个peak,所以梯度下降最终求得的是全局最优解。然而对于multimodal的问题,因为存在多个peak值,很有可能梯度下降的最终结果是局部最优。
5、随机梯度和批量梯度的实现差别
以前一篇博文中NMF实现为例,列出两者的实现差别(注:其实对应Python的代码要直观的多,以后要练习多写python!)
-
- public void updatePQ_stochastic(double alpha, double beta) {
- for (int i = 0; i < M; i++) {
- ArrayList<Feature> Ri = this.dataset.getDataAt(i).getAllFeature();
- for (Feature Rij : Ri) {
-
- double PQ = 0;
- for (int k = 0; k < K; k++) {
- PQ += P[i][k] * Q[k][Rij.dim];
- }
- double eij = Rij.weight - PQ;
-
-
- for (int k = 0; k < K; k++) {
- double oldPik = P[i][k];
- P[i][k] += alpha
- * (2 * eij * Q[k][Rij.dim] - beta * P[i][k]);
- Q[k][Rij.dim] += alpha
- * (2 * eij * oldPik - beta * Q[k][Rij.dim]);
- }
- }
- }
- }
-
-
- public void updatePQ_batch(double alpha, double beta) {
-
- for (int i = 0; i < M; i++) {
- ArrayList<Feature> Ri = this.dataset.getDataAt(i).getAllFeature();
-
- for (Feature Rij : Ri) {
-
- double PQ = 0;
- for (int k = 0; k < K; k++) {
- PQ += P[i][k] * Q[k][Rij.dim];
- }
- Rij.error = Rij.weight - PQ;
- }
- }
-
- for (int i = 0; i < M; i++) {
- ArrayList<Feature> Ri = this.dataset.getDataAt(i).getAllFeature();
- for (Feature Rij : Ri) {
- for (int k = 0; k < K; k++) {
-
- double eq_sum = 0;
- double ep_sum = 0;
-
- for (int ki = 0; ki < M; ki++) {
- ArrayList<Feature> tmp = this.dataset.getDataAt(i).getAllFeature();
- for (Feature Rj : tmp) {
- if (Rj.dim == Rij.dim)
- ep_sum += P[ki][k] * Rj.error;
- }
- }
- for (Feature Rj : Ri) {
- eq_sum += Rj.error * Q[k][Rj.dim];
- }
-
-
- P[i][k] += alpha * (2 * eq_sum - beta * P[i][k]);
- Q[k][Rij.dim] += alpha * (2 * ep_sum - beta * Q[k][Rij.dim]);
- }
- }
- }
- }
- ================================================================================================
-