梯度下降算法

在谈论梯度下降算法之前,先来看看中学时候怎么求一个二次函数的最小值。

例如,现在定义如下函数:

f=x^2-x

在中学时,我们会先对其求其导数:f'=2x-1

令f'=0即可求出该函数在x=1/2时取得最小值,然而,在程序中,该怎么求呢?

首先,可以定义x以如下的方式来迭代x的值:

x=x-rate×k

在这里,rate是x值下降的速率,也可以是讲是x值减少或增加的大小,该值是人为定义的,k值是代表该点的导数,之所以rate前的符号是减号,是因为当k值为正时,x的值会减少,在这时函数是递增的,所以函数值会随着x的减少而减少,反之则刚好相反,这就保证了函数值是一直随着x值的改变而减少,从而达到收敛,可以取得最小值,而要注意的是,如果f是多维函数,那么可能是取到一个极小值而不是最小值。

而关于为什么里面用到该点的导数,是因为导数代表着该点的变化率,确保了x下降的最大值,事实上,导数已经确定了该点是怎么变化的,也就是说导数已经确定了x在某点的变化大小了,而在导数前乘以一个rate是人为改变了x的变化,当然,rate的值不能大于1的,因为当rate的值大于1的时候,引发的后果就是函数不能达到收敛,其实,当rate小于1且不够小的时候,也有可能引发这个后果。所以在这个式子中,x的变化程度是始终小于该点的导数的,也就是说x下降的最大值是该点的导数,所以才说确保了x下降的最大值。

当函数值无限接近与某个值或者函数值处于不变的时候,便认为该函数处于收敛,已求得最小值。

下面给出求该式子最小值的c代码:

#include <iostream>
int main() {
    double rate=0.1;
    double x=4;
    double f=0;
    while(true)
    {
        std::cout<<"x="<<x<<" f(x)="<<x*x-x<<std::endl;
        x=x-rate*(2*x-1);
        if((f-(x*x-x))==0)
        {

            break;
        }
        f=x*x-x;
    }
    return 0;
}

运算结果为:


有了上述基础后,再来讨论梯度下降算法:

梯度下降算法(Gradient descent algorithm)

梯度下降算法事实上是求多维函数的在某一点收敛的极小值,可以用这个算法迭代出在哪个点收敛,也是求最小二乘问题的一种方法。先在脑海中想象一下,你站在一座山上,怎么找到最快下山的方法,这时你当然会朝着最陡峭的方向前进,到达一个点后,再次朝着陡峭的方向下山,从而循环这些步骤,到达山脚。事实上,这也是梯度下降算法名字的由来,如图所示。


先来熟悉下有关梯度下降算法的几个术语:

1)特征值(feature):是样本的输入部分,比如目标函数:,其中x1与x2是特征值,特征值的值是属于数据集的,而且是已知的,θ1与θ2是参数,也是要求的几个值。

2)学习速率(learning rate):是决定在梯度下降中下降的大小程度,或者长度。

3)目标函数(hypothesis function):又称假设函数,是在监督学习中,为了拟合输入样本而产生的目标函数。格式如下:

倘若有两个特征变量,那么表达式则为:

4)样本(sample):样本是一些数据,代表着样本中第i个输入样本,则对应着样本中第i个输出样本。假如:一组数据中有房子的大小,房间的数量和房子的价钱。其中房子的价钱受前两者的影响,那么一组房子大小和房间数量即可称为一个输入样本,一个房子价钱称为输出样本,其中房子大小与房间数量为其中两个特征值。

5)损失函数(loss function):损失函数是用来评估模型好坏的,其中函数值越小代表着拟合的越好。一般用假设函数减去输出样本的方差来评估,一般表达式如下:,其中m是样本的数量,乘以二分之一是便于计算。

上面说了,求得损失函数达到最小的时候,亦或者收敛的时候,目标函数与样本拟合的很好,也便能确定其中各个θ的值。

所以只要改变各个θ的值,来达到损失函数收敛即可,但是如何改变各个θ的值来让损失函数收敛呢?而且怎么保证下降的方向与大小是正确的呢?

借鉴于上文二次函数求最小值,同理,也可以参照这么做,只不过在多维函数中是求各个θ在那点的偏导数,这样便得到了下降的方向与大小:


推导得:


而判断损失函数是否收敛,可以根据函数图像来观察,亦或者判断损失函数减少时忽略不计时即可判断它收敛。

下面给出具有一个特征值的求解代码,matlab实现:

theta0=1;
theta1=1;
r=0.001;
t=0;
while(true)
    t=t+1;
    sum1=0;
    sum2=0;
    sum=0;
    for i=1:m
        sum1=sum1+theta0+theta1*x(i)-y(i);
        sum2=sum2+(theta0+theta1*x(i)-y(i))*x(i);
    end
    theta0=theta0-r*sum1/m;
    theta1=theta1-r*sum2/m;
    for j=1:m
        sum=sum+(theta0+theta1*x(j)-y(j))^2;
    end
    J=sum/(2*m);
    if(J<=4.5)
        break;
    end
end

运算结果为:theta0= -3.3929    theta1=1.1425

给出原始数据图:


验证:


因为取值的问题,虽然有些偏差,但是可以看出,拟合的已经比较好了。

正规方程组(Normal equation)

正规方程组是梯度下降算法的矩阵形式,其表达式为:


具体推导就不推了,谈谈其中的元素,其中θ代表着θ0,θ1.....θn组成的列向量,X代表着由输入样本组成的矩阵,y指输出样本组成的列矩阵。

根据此式子可求出各参数的值,下面给出代码:

z=ones(m,1);
x=[z,x];
theta=pinv(x'*x)*x'*y;
disp(theta);

再次利用上次使用的数据集求出:

θ0=-3.8598  θ1=1.1930

与代数法求出的结果相比相差不大,是正确的。

数据集与源代码地址:https://pan.baidu.com/s/12WMLAqY2YJH-mv58B9p22g

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值