目标函数和约束条件中至少有一个是非线性时,该优化问题即为非线性规划问题。
非线性规划的一般形式如下:
{ m i n f ( x ) g i ( x ) ≥ 0 i = 1 , 2 , ⋅ ⋅ ⋅ , n \begin{cases} min f(x) \\ g_i(x)\geq 0 & i=1,2,···,n \end{cases} {minf(x)gi(x)≥0i=1,2,⋅⋅⋅,n
多元函数的泰勒(Taylor)展开式:
f ( x ) = f ( x k ) + [ ▽ f ( x k ) ] T [ x − x k ] + 1 2 [ x − x k ] T ▽ 2 f ( x k ) [ x − x k ] + O ( ∣ ∣ x − x ∗ ∣ ∣ ) f(x) = f(x_k)+[\bigtriangledown f(x_k)]^T [x-x_k] + \frac{1}{2} [x-x_k]^T \bigtriangledown^2 f(x_k) [x-x_k] + O(||x-x^*||) f(x)=f(xk)+[▽f(xk)]T[x−xk]+21[x−xk]T▽2f(xk)[x−xk]+O(∣∣x−x∗∣∣)
若n元法函数 f ( x ) f(x) f(x)在 x 0 {x}^0 x0的某一邻域有连续二阶偏导,则可二阶泰勒展开 ▽ f ( x k ) \bigtriangledown f(x_k) ▽f(xk)向量是函数一阶偏导的集合即梯度, ▽ 2 f ( x k ) \bigtriangledown^2 f(x_k) ▽2f(xk)是矩阵是函数二阶偏导的集合即海瑟矩阵。
f ( x ) f(x) f(x)是定义在集合
无约束非线性规划判断 x ∗ x^* x∗为极值点的必要条件是:R是n维欧式空间 E n E_n En上的某一开集, f ( x ) f(x) f(x)在R上有连续一阶偏导或 ▽ f ( x ∗ ) = 0 \bigtriangledown f(x^*)=0 ▽f(x∗)=0;充分条件是: ▽ f ( x ∗ ) = 0 \bigtriangledown f(x^*)=0 ▽f(x∗)=0,若 ▽ 2 f ( x k ) \bigtriangledown^2 f(x_k) ▽2f(xk)为正定矩阵则为严格局部极小点,若 ▽ 2 f ( x k ) \bigtriangledown^2 f(x_k) ▽2f(xk)为负定矩阵则为严格局部极大点。
若 x ∗ ∈ R x^*\in R x∗∈R,且对R内任意一点 x x x都有 f ( x ∗ ) ≤ f ( x ) f(x^*) \leq f(x) f(x∗)≤f(x),则 x ∗ x^* x∗为全局最优解;若 f ( x ∗ ) ≤ f ( x ) f(x^*) \leq f(x) f(x∗)≤f(x)只在某一邻域内成立,则 x ∗ x^* x∗为局部最优解。
若 f ( x ) f(x) f(x)是定义在凸集R上,如果 f ( x ) f(x) f(x)具有连续一阶导数,则 f ( x ) f(x) f(x)是凸函数的充要条件是 f ( x 2 ) > f ( x 1 ) + [ ▽ f ( x 1 ) ] T [ x 2 − x 1 ] f(x_2) > f(x_1)+[\bigtriangledown f(x_1)]^T [x_2-x_1] f(x2)>f(x1)+[▽f(x1)]T[x2−x1]对任意 x 1 , x 2 ∈ R x_1,x_2 \in R x1,x2∈R都成立;如果 f ( x ) f(x) f(x)具有连续二阶导数,则凸函数的充要条件为海瑟矩阵半正定。(如果是正定的,则是严格凸函数。半负定,则是凹函数)
有限个凸函数的非负线性组合仍为凸函数。
凸函数的局部最优解就是全局最优解。
在微积分里面,对多元函数的参数求一阶偏导数,把一阶偏导数的集合以向量的形式写出来,就是梯度。几何意义上讲,梯度方向就是函数变化增加最快的方向。或者说,沿着梯度向量的方向,更加容易找到函数的最大值。
在机器学习算法中,在最小化损失函数时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数,和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。
x k + 1 = x k − α k ▽ f ( x k ) x_{k+1}=x_k - {\alpha}_k\bigtriangledown f(x_k) xk+1=xk−αk▽f(xk)
α k {\alpha}_k αk为步长, − ▽ f ( x k ) -\bigtriangledown f(x_k) −▽f(xk)为负梯度方向即下降最快的方向, x k + 1 x_{k+1} xk+1为下一位置, x k x_k xk为当前位置。
clear
syms x y
fun=x^2+2*y^2-4*x-2*x*y;
x_syms=[sym(x) sym(y)];
x0=[1 1];
%最速下降
[xmin1,minf1]=mygrad1(@opfun5,fun,x0,x_syms,0.0001);
[xmin1,minf1]=mygrad1([],fun,x0,x_syms,0.0001);
%基本牛顿
[xmin2,minf2]=mynewton21(@opfun5,fun,x0,x_syms,'nt',0.0001);
[xmin2,minf2]=mynewton21([],fun,x0,x_syms,'nt',0.0001);
%阻尼牛顿
[xmin3,minf3]=mynewton21(@opfun5,fun,x0,x_syms,'zn',0.0001);
[xmin3,minf3]=mynewton21([],fun,x0,x_syms,'zn',0.0001);
%牛顿-梯度
[xmin4,minf4]=mynewton21(@opfun5,fun,x0,x_syms,'nt',0.0001);
[xmin4,minf4]=mynewton21([],fun,x0,x_syms,'nt',0.0001);
%修正-牛顿
[xmin5,minf5]=mynewton21(@opfun5,fun,x0,x_syms,'xz',0.0001);
[xmin5,minf5]=mynewton21([],fun,x0,x_syms,'xz',0.0001);
function y=opfun5(x)
y=x(1)^2+2*x(2)^2-4*x(1)-2*x(1)*x(2);
function [xmin,minf]=mygrad1(fun,phi,x0,x_syms,esp) %梯度法求极值,x_syms为变量
syms lamda
if nargin<6
esp=1e-6;
end
z=myjacobian1(phi,x_syms);
k=0;
while k<5000 %迭代次数
f=eval(subs(z,x_syms,x0));
if norm(f)<=esp
xmin=x0;
if ~isempty(fun)
minf=fun(xmin);
else
minf=eval(subs(phi,x_syms,xmin));
end
break
end
if ~isempty(fun)
x3=mysearch1(fun,phi,x0,x_syms,-f,'d');%一维搜索求步长
else
x3=mysearch1([],phi,x0,x_syms,-f,'d');
end
xk=x0-x3*f;
x0=xk;
k=k+1;
end
function [xmin,minf]=mynewton21(fun,phi,x0,x_syms,type,esp) %牛顿法求多元函数极值
syms lamda
if nargin<7
esp=1e-6;
end
z=myjacobian1(phi,x_syms);
H=hessian(phi,x_syms);
n=length(x0);
if strcmp(type,'xz')
tau=input('请输入τ= ');
if isempty(tau)
tau=0.1;
end
end
k=0;
while k<5000
f=eval(subs(z,x_syms,x0));
h=eval(subs(H,x_syms,x0));
s=-inv(h)*f';
if norm(f)<=esp
xmin=x0;
if ~isempty(fun)
minf=fun(xmin);
else
minf=eval(subs(phi,x_syms,xmin));
end
break
end
if strcmp(type,'nt') %牛顿法
xk=x0+s';
elseif strcmp(type,'zn') %阻尼牛顿法
if ~isempty(fun)
x3=mysearch1(fun,phi,x0,x_syms,s','d'); %一维搜索求步长,第20行~第31行语句可以用这句代替
else
x3=mysearch1([],phi,x0,x_syms,s','d');
end
xk=x0+x3*s';
elseif strcmp(type,'ng') %牛顿-梯度法
if f*s<0
if ~isempty(fun)
x3=mysearch1(fun,phi,x0,x_syms,s','d'); %一维搜索求步长,第20行~第31行语句可以用这句代替
else
x3=mysearch1([],phi,x0,x_syms,s','d');
end
% x3=mysearch1(fun,phi,x0,x_syms,xsyms,s','d');
xk=x0+x3*s';
else
if ~isempty(fun)
x3=mysearch1(fun,phi,x0,x_syms,-f,'d'); %一维搜索求步长,第20行~第31行语句可以用这句代替
else
x3=mysearch1([],phi,x0,x_syms,-f,'d');
end
%x3=mysearch1(fun,phi,x0,x_syms,xsyms,-f,'d');
xk=x0-x3*f;
end
elseif strcmp(type,'xz') %修正牛顿法
miuk=(norm(f))^(1+tau);
%ak=h+miuk*eye(n);
%s=-ak\f'; %计算搜索方向
s=-(inv(h+miuk*eye(n)))'*f';
if ~isempty(fun)
x3=mysearch1(fun,phi,x0,x_syms,s','d'); %一维搜索求步长,第20行~第31行语句可以用这句代替
else
x3=mysearch1(fun,phi,x0,x_syms,s','d');
end
% x3=mysearch1(fun,phi,x0,x_syms,xsyms,s','d');
xk=x0+x3*s';
end
x0=xk;
k=k+1;
end
function [y,x]=mysearch1(fun,phi,x0,x_syms,d0,type) %不精确搜索求步长,d0为方向,x_syms为变量
if isempty(d0)
z=myjacobian1(phi,x_syms);
g=subs(z,x_syms,x0);
d0=-g;
end
switch type
case 'd' %直接法
z=myjacobian1(phi,x_syms);
a=0;b=inf;lamda=1;y=lamda;m=0;c1=0.1;c2=0.5;
if ~isempty(fun)
f=fun(x0);
else
f=eval(subs(phi,x_syms,x0));
end
g=subs(z,x_syms,x0);
t=g*d0';
while 1
if m>20
break
end
x1=x0+lamda*d0;
if ~isempty(fun)
f1=fun(x1);
else
f1=eval(subs(phi,x_syms,x1));
end
%f1=fun(x1);
g1=subs(z,x_syms,x1);
t1=g1*d0';
a1=f-f1;
a2=-c1*lamda*t;
a3=c2*t;
if (a1>=a2)&&(t1>=a3)
y=lamda;
x=x1;
break;
elseif (a1>=a2)&&t1<a3
a=lamda;
lamda=min(2*lamda,(lamda+b)/2);
elseif a1<a2
b=lamda;
lamda=(lamda+a)/2;
end
m=m+1;
end
case 'a' %Armijo规则
z=myjacobian1(phi,x_syms);
m=0;maxm=20;beta=0.5;sigma=0.2;
y1=0;
while m<=maxm
if ~isempty(fun)
x1=fun(x0+beta^m*d0);
else
x1=eval(subs(phi,x_syms,x0+beta^m*d0));
end
%x1=fun(x0+beta^m*d0);
if ~isempty(fun)
x2=fun(x0)+sigma*beta^m*sbs(z,x_syms,x0)*d0';
else
x2=eval(subs(phi,x_syms,x0))+sigma*beta^m*sbs(z,x_syms,x0)*d0';
end
% x2=fun(x0)+sigma*beta^m*sbs(z,x_syms,x0)*d0';
if x1<=x2
y1=m;
break;
end
m=m+1;
end
y=beta^y1;
x=x0+y*d0;
case 'equ' %解方程求步长
syms al x
x1=x0+al*d0;
phi1=subs(phi,x_syms,x1);
phi=(subs(phi1,al,'x'));
ds=diff(phi);
x2=solve(ds); %解方程求步长
for i=1:length(x2)
if isreal(x2(i))
y1=mymin(phi,x2(i),'min');
if y1==1
y=eval(x2(i));
break
end
end
end
if exist('y','var')==1
x=x0+y*d0;
else
y=[];x=[];
end
case 's' %一维搜索法
syms al x
x1=x0+al*d0;
phi1=(subs(phi,x_syms,x1));
phi=subs(phi1,al,'x');
y=goldcut1(phi,1);
x=x0+y*d0;
end
function y=myjacobian1(fun,x_syms) %求复函数的导数,x_syms应为变量
if nargin==1
syms x
x_syms=sym(x);
end
if ~isempty(fun)
r=size(fun,1);
n=length(x_syms);
for i=1:r
for j=1:n
y(i,j)=jacobian(fun(i,:),x_syms(j));
end
end
else
y=[];
end
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44037272/article/details/109164186