牛顿法的关键就是利用了Hesse的曲率信息,但是Hesse的计算和存储都很困难,那可否用梯度和目标函数这些信息来构造曲率近似呢?
实际上就是用Bk代替牛顿法中的Hesse矩阵,Hk替牛顿法中的Hesse逆矩阵
牛顿法 | 拟牛顿法 | |
---|---|---|
迭代公式 | xk+1= xk - αk(▽2f(xk))-1 ▽f(xk)) | xk+1 = xk - αkBk-1 . ▽f(xk) |
dk 搜索方向 | - (▽2f(xk))-1 ▽f(xk)) | - Bk-1 . ▽f(xk) |
所以就是搜索方向用 - Bk-1 . ▽f(xk) 迭代,
初始时Bk为单位矩阵,搜索方向为最速方向
性质
- 仅需一阶导数
- Bk 正定 即可使该方法有下降性质
- 搜索方向互相共轭
Hk更新
xk+1 = xk - αkBk-1 . gk
sk = xk+1 - xk,yk = gk+1 - gk
那么如何更新Hesse逆的近似——Hk呢?我们提出了两种修正方法。
DFP校正
BFGS校正
两次运用秩一校正得到关于Bk的迭代公式
matlab代码实现
function [best_x,best_fx,count]=BFGS(x0,ess)
% ###########################
digits(5);
syms x1 x2 t;
f=100*(x1^2-x2)^2+(x1-1)^2;
fx=diff(f,x1);%求表达式f对x1的一阶求导
fy=diff(f,x2);%求表达式f对x2的一阶求导
fi=[fx fy];%构造函数f的梯度函数
%初始点的梯度和函数值
g0=subs(fi,[x1 x2],x0);
g0=vpa(g0,5);
f0=subs(f,[x1 x2],x0);
B0=hessian(f,[x1,x2]); %B0是二阶梯度
B0=subs(B0,[x1,x2],x0);
x0
f0
g0
B0
xk=x0;
fk=f0;
gk=g0;
Bk=B0;
k=1;
while(norm(gk)>ess)%迭代终止条件||gk||<=ess
xk0=xk;
% X = sprintf('x%d=',k);
% disp(X);
% disp(xk0);
disp('************************************************************')
disp(['第' num2str(k) '次寻优'])
%确定搜索方向
pk=-inv(Bk)*gk';
%由步长找到下一点x(k+1)
xk=xk+t*pk';
f_t=subs(f,[x1 x2],xk); %构造一元搜索的一元函数φ(t) %由一维搜索找到最优步长
%更新原函数为关于步长t的函数,用以求解最优步长
df_t=diff(f_t,t);%关于t求导
tk=solve(df_t);% 计算导数为0处t的值
X = sprintf('步长为 %f',tk);
disp(X);
%计算下一点的函数值和梯度
xk = subs(xk,t,tk(1));
fk=subs(f,[x1 x2],xk);
gk0=gk;
gk=subs(fi,[x1 x2],xk);
%BFGS校正公式,找到修正矩阵
yk=gk'-gk0';
sk=xk'-xk0';
% Bk=Bk+(yk*yk')/(sk'*yk); %修正公式
Bk=Bk+(yk*yk')/(sk'*yk)-(Bk*sk*sk'*Bk)/(sk'*Bk*sk); %修正公式
k=k+1;
disp(Bk);
xk
fk
gk
Bk
end
disp('结果如下:')
best_x=xk;%最优点
best_fx=fk;%最优值
count=k-1;
end