• 梯度下降


        转载自:http://www.cnblogs.com/tornadomeet

          梯度下降法又叫最速下降法,英文名为steepest descend method.估计搞研究的人应该经常听见这个算法吧,用来求解表达式最大或者最小值的,属于无约束优化问题。

          首先我们应该清楚,一个多元函数的梯度方向是该函数值增大最陡的方向。具体化到1元函数中时,梯度方向首先是沿着曲线的切线的,然后取切线向上增长的方向为梯度方向,2元或者多元函数中,梯度向量为函数值f对每个变量的导数,该向量的方向就是梯度的方向,当然向量的大小也就是梯度的大小。

          现在假设我们要求函数的最值,采用梯度下降法,如图所示:

          梯度下降法的基本思想还是挺简单的,现假设我们要求函数f的最小值,首先得选取一个初始点后,然后下一个点的产生时是沿着梯度直线方向,这里是沿着梯度的反方向(因为求的是最小值,如果是求最大值的话则沿梯度的方向即可)。梯度下降法的迭代公式为:

         

          其中表示的是梯度的负方向, 表示的是在梯度方向上的搜索步长。梯度方向我们可以通过对函数求导得到,步长的确定比较麻烦,太大了的话可能会发散,太小收敛速度又太慢。一般确定步长的方法是由线性搜索算法来确定,即把下一个点的坐标ak+1看做是的函数,然后求满足f(ak+1)的最小值的 即可。

          因为一般情况下,梯度向量为0的话说明是到了一个极值点,此时梯度的幅值也为0.而采用梯度下降算法进行最优化求解时,算法迭代的终止条件是梯度向量的幅值接近0即可,可以设置个非常小的常数阈值。

          下面是网上下的一个求2元函数最小值的matlab函数实现代码,在上面添加了少许注释。代码中关于步长的计算公式还是没有弄很清楚,用到了hessian矩阵,有点像牛顿法,先不管了,以后有时候慢慢研究。

    复制代码
     1 function y=fs2steep(f,e,a,b) %返回的是点坐标的2个分量
     2 % fs2steep函数 最速下降法
     3 % x=fs2steep(f,e,a,b)为输入函数 f为函数 e为允许误差 (a,b)为初始点;
     4 % fsx TJPU 2008.6.15
     5 x1=a;x2=b;
     6 Q=fs2hesse(f,x1,x2);
     7 x0=[x1 x2]';
     8 fx1=diff(f,'x1'); %对x1求偏导数
     9 fx2=diff(f,'x2'); %对x2求偏导数
    10 g=[fx1 fx2]'; %梯度
    11 g1=subs(g); %把符号变量转为数值
    12 d=-g1;%d为搜索方向
    13 while (abs(norm(g1))>=e)  %norm(g1)为g1的2范数,即sqrt(x1^2+x2^2),因为梯度其各分量=0,所以其梯度幅值=0
    14     t=(-d)'*d/((-d)'*Q*d);%求搜索步长,方法是?
    15     x0=x0-t*g1; %搜索到的点
    16     v=x0;
    17     a=[1 0]*x0;
    18     b=[0 1]*x0;
    19     x1=a;
    20     x2=b;  
    21     Q=fs2hesse(f,x1,x2);
    22     x0=[x1 x2]';
    23     fx1=diff(f,'x1'); %对x1求偏导数
    24     fx2=diff(f,'x2'); %对x2求偏导数
    25     g=[fx1 fx2]'; %梯度    
    26     g1=subs(g);
    27     d=-g1;
    28 end;
    29 y=v;
    30 
    31 function x=fs2hesse(f,a,b)
    32 % fs2hesse函数 求函数的hesse矩阵;
    33 % 本程序仅是简单的求二次函数的hesse矩阵!;
    34 % x=fs2hesse(f)为输入函数 f为二次函数 x1,x2为自变量;
    35 % fsx TJPU 2008.6.15
    36 x1=a;x2=b;
    37 fx=diff(f,'x1');     %求f对x1偏导数
    38 fy=diff(f,'x2');     %求f对x2偏导数
    39 fxx=diff(fx,'x1');   %求二阶偏导数 对x1再对x1
    40 fxy=diff(fx,'x2');   %求二阶偏导数 对x1再对x2
    41 fyx=diff(fy,'x1');   %求二阶偏导数 对x2再对x1
    42 fyy=diff(fy,'x2');   %求二阶偏导数 对x2再对x2
    43 fxx=subs(fxx);       %将符号变量转化为数值
    44 fxy=subs(fxy);
    45 fyx=subs(fyx);
    46 fyy=subs(fyy);
    47 x=[fxx,fxy;fyx,fyy]; %求hesse矩阵
    复制代码

          在matlab命令行窗口验证函数,结果如下:

         

    随机梯度下降:

    有种叫做随机梯度下降的算法能够加速学习。其思想就是通过随机选取小量训练输入样本来计算 ∇Cx ,进而估算梯度 ∇C。通过计算少量样本的平均值我们可以快速得到一个对于实际梯度 ∇C 的很好的估算,这有助于加速梯度下降,进而加速学习过程。

    更准确地说,随机梯度下降通过随机选取小量的 m 个训练输入来工作。我们将这些随机的训练输入标记为 X 1 , X 2 , . . . , X m ,并把它们称为一个小批量数据(mini-batch)。假设样本数量m 足够大,我们期望 ∇Cxj 的平均值大致相等于整个 ∇Cx的平均值,即,

    证实了我们可以通过仅仅计算随机选取的小批量数据的梯度来估算整体的梯度.

    了将其明确地和神经网络的学习联系起来,假设 wk 和 bl表示我们神经网络中权重和偏置。随即梯度下降通过随机地选取并训练输入的小批量数据来工作,

     

    其中两个求和符号是在当前小批量数据中的所有训练样本 Xj 上进行的。然后我们再挑选另一随机选定的小批量数据去训练。直到我们用完了所有的训练输入,这被称为完成了一个训练迭代期(epoch)。然后我们就会开始一个新的训练迭代期。

    我们可以把随机梯度下降想象成一次⺠意调查:在一个小批量数据上采样比对一个完整数据集进行梯度下降分析要容易得多,正如进行一次⺠意调查比举行一次全⺠选举要更容易。例如,如果我们有一个规模为 n = 60, 000 的训练集,就像 MNIST,并选取小批量数据 大小为 m = 10,这意味着在估算梯度过程中加速了 6, 000 倍!当然,这个估算并不是完美的 —— 存在统计波动 —— 但是没必要完美:我们实际关心的是在某个方向上移动来减少 C,而这意味着我们不需要梯度的精确计算。在实践中,随机梯度下降是在神经网络的学习中被广泛使用、十分有效的技术,它也是本书中展开的大多数学习技术的基础.

     

  • 相关阅读:
    c#查找窗口的两种办法
    也说自动化测试
    定位bug的基本要求
    c#调用GetModuleFileNameEx获取进程路径
    对比PG数据库结构是否一致的方法
    C#调用endtask
    提bug
    接口测试的结果校验
    ProcessExplorer使用分享
    C++如何在r3静态调用NT函数
  • 原文地址:https://www.cnblogs.com/Allen-rg/p/5483646.html
Copyright © 2020-2023  润新知