MATLAB利用最速梯度下降法求解f(x)函数极小点附讲解
问题描述
利用最速梯度下降法求解:
函数接口:[xstar,fxstar,iter]=SteepDescent(f_name,x0,eps)
其中xstar为最优解,fxstar为最优函数值,iter为迭代次数。
f_name为目标函数值,可取[1,1]’,eps=1e-3,利用0.618法搜索步长。
解题步骤
在步骤三搜索步长因子时,首先需要选择一个初始的搜索空间[a0,b0]。首先判断初始值是在极值点的左边或者右边,根据函数在极值点左侧单调下降,在极值点右侧单调上升。实际上根据步长一定是大于0的条件,alpha初始值直接设置0就可以了,这样搜索区间的左端点a0=0,只要再找到b0就可以了。
寻找b0,此时f0=feval(f_name,xk+a0dk);让a0等长度增加,如a1=a0+iterh0,h0为每次增加的长度,如h0=0.1;iter=1起始。计算f1=feval(f_name,xk+a1*dk);如果f1>f0,则b0=a1;否则iter=iter+1;
注意:为了防止数值误差引起的错误,可以加一个约束条件abs(f1-f0)>eps,a0和b0点处的函数值差异明显。找到初始搜索空间之后利用0.618搜索方法。
MATLAB函数代码
// SteepDescent_script.m
%脚本文件,调用函数接口
[xstar,fxstar,iter] = SteepDescent(@Myexam1,[1,1]',1e-3)
// SteepDescentt.m
function [xstar,fxstar,iter] = SteepDescent(f_name,x0,eps)
%函数文件
iter=0;%初始化迭代次数
[~,g]=Myexam1(x0);%初始梯度
x=x0;
dk=-g;%确定当前搜索方向
while norm(g)>eps %未达到精度要求
iter=iter+1;
[b] = Trial(@Myexam1,x,dk,1,0.1,eps);%确定搜索区间,左端为0,只需计算出右端b,a0取1,h取0.1
[lamda]=S618(@Myexam1,x,dk,[0,b],eps);%0.618搜索
x_0=x;
x=x_0+lamda*dk;
[~,g]=Myexam1(x);
dk=-g;
s1 =sqrt((x - x_0)'*(x - x_0));
if s1 <= eps
break;
end
end
xstar=x;
[fxstar,~]=Myexam1(xstar);
end
// Myexam1.m
function [f,g]=Myexam1(x)
%%%%调用[f,g] = feval(f_name,xk);
f=x(1)^2+2*x(2)^2;
g=[2*x(1);4*x(2)];
end
// Trial.m
function [b] = Trial(f_k,xk,dk,a0,h0,eps)
%确定区间右端点
f0 = feval(f_k,xk+a0*dk);% 计算初始点函数值
a1 = a0 + h0;
f1 = feval(f_k,xk+a1*dk);
%防止数值误差引起的错误,加入约束条件abs(f1-f0)>eps
while abs(f1-f0)<eps
a1 = a1 + h0;
f1 = feval(f_k,xk+a1*dk);
end
b=a1;
%让a1等长度增加,h0=0.1,如果找到f1>f0,退出
while f1<=f0
a1=a1+ h0;
f1=feval(f_k,xk+a1*dk);
end
b=a1;
end
// S618.m
function [x] = S618(f_name,xk,dk,range,e)
%0.618搜索确定lamda的极小点
% xk: 当前搜索点
% dk: 当前搜索方向
% e: 精度要求
a = range(1);b = range(2);
flag = 0;%设置一个退出标志
while flag==0
u = a+0.382*(b-a);
v = a+0.618*(b-a);
m = feval(f_name,xk+u*dk);
n = feval(f_name,xk+v*dk);
if m>n %区间变成[u,b]
if b-u<e %区间大小满足要求
x = v;
flag = 1;
else %更改区间,继续迭代
a = u;
flag = 0;
end
else %区间变成[a,v]
if v-a<e %区间大小满足要求
x = u;
flag = 1;
else %更改区间,继续迭代
b=v;
flag = 0;
end
end
end