matlab实现梯度下降法

前记:

大三上学期学了《运筹学》课程,里面包含了许多算法和模型。模型就是线性规划及线性规划的对偶理论,单纯形法以及它的实际应用;整数规划及其解法(分支定界法、割平面法匈牙利算法);目标规划;非线性规划动态规划、决策分析等等。实际上,这些模型在参加暑假数学建模培训的时候,多多少少接触过,所以还算比较熟悉的。

然后在这门课程里面还学习了其它的一些优化算法。比如说一维搜索里面的黄金分割法、加步探索法、牛顿法、抛物线法等算法求函数的最优解。再后面还学习了无约束问题的最优化方法,约束问题的最优化方法这两个非常重要的内容。那么在无约束问题的优化算法中,最让人耳熟能详也可能是应用最广泛的就数最速下降法(也叫梯度下降法)、牛顿法共轭梯度法了。在约束问题的优化算法中主要涉及K-T条件,可行方向法、制约函数法。这些算法在当今的机器学习领域应用还是十分广泛的。

今天只分享梯度下降法。

简单描述下梯度下降法的算法步骤。至于详细的原理与算法的推导过程建议还是找一本运筹学书慢慢研究,实际上还挺简单的。

算法步骤:

算法的matlab实现:

function [k ender,value]=GraDes(f,x,e)
%【梯度下降法】
%【输入】f为目标函数(两变量x1和x2),x为初始点,e为求解精度
%【输出】k为迭代次数,ender为搜索到的点,value为求得的函数值
%【调用方法】
% syms x1 x2;
% f函数
% x初始点
% e精度
% 调用[k ender,value]=steepest(f,x,e)
syms x1 x2 m; %m为学习率
d=-[diff(f,x1);diff(f,x2)];  %分别求x1和x2的偏导数,即下降的方向
flag=1;  %循环标志
k=0; %迭代次数
ezplot('x1^2+2*x2^2-4*x1-2*x1*x2')%画出函数图像
axis([-0.5,10,-2,5])
hold on
while(flag)
    d_temp=subs(d,x1,x(1));      %将起始点代入,求得当次下降x1梯度值
    d_temp=subs(d_temp,x2,x(2)); %将起始点代入,求得当次下降x2梯度值
    nor=norm(d_temp); %范数
    if(nor>=e)
        x_temp=x+m*d_temp;            %改变初始点x的值
        f_temp=subs(f,x1,x_temp(1));  %将改变后的x1和x2代入目标函数
        f_temp=subs(f_temp,x2,x_temp(2));
        h=diff(f_temp,m);  %对m求导,找出最佳学习率
        m_temp=solve(h);   %求方程,得到当次m
        x=x+m_temp*d_temp; %更新起始点x
        drawnow;
        pause(0.2);
        k=k+1;
    else
        flag=0;
    end
    hold off
end
ender=double(x);  %终点
%输出在此点的函数值
x1=ender(1,1);
x2=ender(2,1);
value=x1^2+2*x2^2-4*x1-2*x1*x2;
end

引用方式:

>> syms x1 x2;
>> x=[0;0];
>> f=x1^2+2*x2^2-4*x1-2*x1*x2;
>> [k,ender,value]=GraDesc(f,x,e)

输出结果:

k =

    20


ender =

    3.9961
    1.9980


value =

   -8.0000

其中k是迭代次数,ender是最后计算的到的极值点,value是函数在该极值点下的函数值。

最后,再给出梯度下降法算法的评价。

优缺点:

梯度下降法对初始点的选择要求不高,每一轮迭代工作量小,可以比较快地从初始点到达极小点附近;但在接近极小点时,算法会出现锯齿现象,收敛速度很慢。因为对于一般二元函数,在极小点附近可以用极小点的二阶泰勒多项式来近似,而后者为凸函数时,它的等值线为一族共心椭圆,特别是当椭圆比较扁平时,收敛速度就非常慢。针对这种情况,解决的办法是,将梯度法与其他算法结合起来使用,前期使用梯度法,在极小点附近使用牛顿法。

 

你可能感兴趣的:(算法设计与分析)