写这篇文章其实也不是什么原创,只是一个总结,好多算法都关于梯度的算法.
大家都知道,偏导数反映的是函数延坐标轴方向的变换率,但是现实生活中,我们紧紧研究延坐标轴方向的变换率是不够的,比如热空气要向冷空气移动,那么它的方向是任意的,还有就像水的流动一样,它的方向也是任意的,还有大气温度沿着某些方向也是任意的,因此我们有意义研究一指定方向上的函数的变换率。这样就引出了方向导数
这个就是方向导数的一个简单的计算公式,后面三个(cos a,cos b ,cos y)表示的是单位方向向量.
最后引出梯度的概念,梯度最终的目的是表达的是函数在某一点变化最快的方向,也就是增加最快的方向,反之加一个负号就表示减少最快的方向.
梯度下降法:转自郑海波,他写的比较好,有权威性
梯度下降法是一个一阶最优化算法,通常也称为最速下降法。我之前也没有关注过这类算法。最近,听斯坦福大学的机器学习课程时,碰到了用梯度下降算法求解线性回归问题,于是看了看这类算法的思想。今天只写了一些入门级的知识。
我们知道,函数的曲线如下:
编程实现:c++ code
- /*
- * @author:郑海波
- * blog.csdn.net/nuptboyzhb/
- * 2012-12-11
- */
- #include <iostream>
- #include <math.h>
- using namespace std;
- int main()
- {
- double e=0.00001;//定义迭代精度
- double alpha=0.5;//定义迭代步长
- double x=0;//初始化x
- double y0=x*x-3*x+2;//与初始化x对应的y值
- double y1=0;//定义变量,用于保存当前值
- while (true)
- {
- x=x-alpha*(2.0*x-3.0);
- y1=x*x-3*x+2;
- if (abs(y1-y0)<e)//如果2次迭代的结果变化很小,结束迭代
- {
- break;
- }
- y0=y1;//更新迭代的结果
- }
- cout<<"Min(f(x))="<<y0<<endl;
- cout<<"minx="<<x<<endl;
- return 0;
- }
- //运行结果
- //Min(f(x))=-0.25
- //minx=1.5
- //Press any key to continue
- 下面是我写的一个程序,类似上面的code
- #include "stdafx.h"
#include<math.h>
#include<stdio.h>
#include<conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
double step_width=0.05;//迭代步长,实质上就是下一个点到上一个点的距离,也就是两者之间的距离
double x0=-16.0;//起始x值
doublethreshold=0.00001;//两者之间的值域小于多少就停止迭代,找到最小值
double y0=x0*x0+4*x0+1;
double y=0.0,x=0.0;
while(1)
{
x=x0-step_width*(2*x0+4);//后面的导数可以看作是一个tan值,从几何上就比较容易看懂
y=x*x+4*x+1;
if(abs(y-y0)<threshold) break;
y0=y;
x0=x;
}
printf("\n result_x0=%f\n",x0);
printf("\n result_y0=%f\n",y0);
getch();
return 0;
}
- 输出的结果如下:
- x0=2.00715
- y0=-2.9995
- 接下来看一下对z=x*x+y*y的收敛,同样利用梯度下降法进行:
- double step_x=0.0005,step_y=0.0005;//表示沿x和y轴的收敛步进
double threshold=0.000001;
double x0=1,y0=1;
double z0=x0*x0+y0*y0;//这个表示起始值的时候z0的函数值
double x,y;
double z=0.0;//函数值中间变量
while(1)
{
x=x0-step_x*2*x0;
y=y0-step_y*2*y0;
z=x*x+y*y;
if(abs(z-z0)<threshold) break;
x0=x;
y0=y;
z0=z;
}
printf("\n result_z=%f\n",z0);
printf("\n result_x0=%f\n",x0);
printf("\n result_y0=%f\n",y0);
getch();
- }
- 结果:
- z=0.000500
- x=0.015811
- y=0.015811
梯度下降法的缺点:
- 靠近极小值时速度减慢。
- 直线搜索可能会产生一些问题。
- 可能会'之字型'地下降。
这个收敛速度特别慢,是对这个函数做的一个收敛,其最小值在 处,数值为。