梯度下降法

今天开始看到损失函数(错误函数)求解时,可以用最小二乘法,Andrew Ng视频中讲的梯度下降法,于是决定学习梯度下降法求损失函数的最小值,如下:

比如估计函数如下,例子源自这里


加入X0 = 1,我们就可以用向量表示为:

损失函数表示为:


最后主要是求 的最小值,上面公式中利用估计值与真实值y(i)差的平方作为错误估计函数,1/2是为了在求导的时候,消去平方项的系数。

梯度下降法又称最速下降法

原理是:将函数比作一座山,站在某个山坡上,往四周看,从哪个方向向下走一小步,能够下降的最快;

首先,对J(theta)求偏导得到

θi会向着梯度最小的方向进行减少。θi表示更新之前的值,-后面的部分表示按梯度方向减少的量,α表示步长,也就是每次按照梯度减少的方向变化多少。

具体如下:


其中a决定了下降的步伐,负号后面的导数部分决定了下降的方向


在一维空间内可以理解为

梯度下降法_第1张图片

如上图所示如果当前点为A,那么A点的偏导数小于0,也就是斜率小于0.那么此时A应该往右走找到B才是正确的方向,也就是说

此时应该是A的横坐标+A的偏导数的相反数*系数

同理:对于C点,此时应该是向左走才是正确的方向,C点的偏导数大于0,

应该表示为

C点的横坐标+C点偏导数的相反数。这个形象的描述了上面的公式。

通过循环迭代的方法,使得 当连续两点之间的函数值小于一个给定的阈值时,循环结束,停止下降,得到极小值。

步长太小 就会出现局部极小的现象 就像一个小坑里跳不出来,步长大一些就可以跳过局部极值 但是会在 极值左右不断震荡。

梯度下降法_第2张图片

梯度下降法_第3张图片

C++代码为:(本段摘自这里)

#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;  
}  
结果为:

梯度下降法_第4张图片

三维图中显示如下:

梯度下降法_第5张图片

你可能感兴趣的:(梯度下降法)