梯度的定义及重新认识

      写这篇文章其实也不是什么原创,只是一个总结,好多算法都关于梯度的算法.

      大家都知道,偏导数反映的是函数延坐标轴方向的变换率,但是现实生活中,我们紧紧研究延坐标轴方向的变换率是不够的,比如热空气要向冷空气移动,那么它的方向是任意的,还有就像水的流动一样,它的方向也是任意的,还有大气温度沿着某些方向也是任意的,因此我们有意义研究一指定方向上的函数的变换率。这样就引出了方向导数

      这个就是方向导数的一个简单的计算公式,后面三个(cos a,cos b ,cos y)表示的是单位方向向量.

      最后引出梯度的概念,梯度最终的目的是表达的是函数在某一点变化最快的方向,也就是增加最快的方向,反之加一个负号就表示减少最快的方向.

      梯度下降法:转自郑海波,他写的比较好,有权威性

   

 梯度下降法是一个一阶最优化算法,通常也称为最速下降法。我之前也没有关注过这类算法。最近,听斯坦福大学的机器学习课程时,碰到了用梯度下降算法求解线性回归问题,于是看了看这类算法的思想。今天只写了一些入门级的知识。




我们知道,函数的曲线如下:


编程实现:c++ code

[cpp]  view plain copy
  1. /* 
  2.  * @author:郑海波 
  3.  * blog.csdn.net/nuptboyzhb/ 
  4.  * 2012-12-11 
  5.  */  
  6. #include <iostream>  
  7. #include <math.h>  
  8. using namespace std;  
  9. int main()  
  10. {  
  11.     double e=0.00001;//定义迭代精度  
  12.     double alpha=0.5;//定义迭代步长  
  13.     double x=0;//初始化x  
  14.     double y0=x*x-3*x+2;//与初始化x对应的y值  
  15.     double y1=0;//定义变量,用于保存当前值  
  16.     while (true)  
  17.     {  
  18.         x=x-alpha*(2.0*x-3.0);  
  19.         y1=x*x-3*x+2;  
  20.         if (abs(y1-y0)<e)//如果2次迭代的结果变化很小,结束迭代  
  21.         {  
  22.             break;  
  23.         }  
  24.         y0=y1;//更新迭代的结果  
  25.     }  
  26.     cout<<"Min(f(x))="<<y0<<endl;  
  27.     cout<<"minx="<<x<<endl;  
  28.     return 0;  
  29. }  
  30. //运行结果  
  31. //Min(f(x))=-0.25  
  32. //minx=1.5  
  33. //Press any key to continue  
  34. 下面是我写的一个程序,类似上面的code
  35. #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;
    }
  36. 输出的结果如下:
  37. x0=2.00715
  38. y0=-2.9995
  39. 接下来看一下对z=x*x+y*y的收敛,同样利用梯度下降法进行:
  40.         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();
  41. }
  42. 结果:
  43. z=0.000500
  44. x=0.015811
  45. y=0.015811
梯度下降法的缺点:
  • 靠近极小值时速度减慢。
  • 直线搜索可能会产生一些问题。
  • 可能会'之字型'地下降。
这个收敛速度特别慢,f(x, y) = (1-x)^2 + 100(y-x^2)^2 .\quad 是对这个函数做的一个收敛,其最小值在 (x, y)=(1, 1) 处,数值为f(x, y)=0


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值