x = lsqnonlin(fun,x0)
x = lsqnonlin(fun,x0,lb,ub)
x = lsqnonlin(fun,x0,lb,ub,options)
x = lsqnonlin(problem)
[x,resnorm] = lsqnonlin(___)
[x,resnorm,residual,exitflag,output] = lsqnonlin(___)
[x,resnorm,residual,exitflag,output,lambda,jacobian] = lsqnonlin(___)
非线性最小二乘法
解决非线性最小二乘形式的曲线拟合问题,解x
具有可选的下限lb
和上限ub
x, lb 和 ub 可以是矢量或矩阵。
lsqnonlin不用计算f(x)
2范数的平方,而是需要用户定义函数来计算矢量值函数
fun
fun
为函数句柄或函数名,求其平方和的最小值。功能,其总和的平方被最小化,指定为功能句柄或函数名。fun
接受一个数组x,返回数组F,于x评估目标函数。该函数fun
可以被指定为一个文件中的函数句柄:
x = lsqnonlin(@myfun,x0)
其中myfun 是一个MATLAB函数,形如:
function F = myfun(x)
F = ... % Compute function values at x
fun
也可以是匿名函数的函数句柄
x = lsqnonlin(@(x)sin(x.*x),x0);
如果用户定义的x和F是数组,将被转换为带线性索引的矢量。
注意:
平方和不应该明确形成。相反,你的函数应该返回函数值的向量。
如果雅可比矩阵可以计算,并且雅可比的选项是“开”,设置为
options = optimoptions('lsqnonlin','SpecifyObjectiveGradient',true)
则函数fun
必须返回第二输出参数,即在x
处的雅可比矩阵J
的值。
通过检查nargout
的值,当fun
被调用且仅具有一个输出参数(在优化算法只需要F,但不J的值的情况下)时,该函数可避免计算J
。
function [F,J] = myfun(x)
F = ... % Objective function values at x
if nargout > 1 % Two output arguments
J = ... % Jacobian of the function evaluated at x
end
如果fun
返回m
个分量的数组,并且x
具有n
个元素,其中n
是x0
的元素数,雅可比J
是一个m*n
矩阵,其中J(i,j)
为F
关于x(j)
的偏导数。(雅可比J
是F
梯度的转置。)
x0
x0
为初始点,为实向量或实数组。求解器使用x0
元素的数量和x0
的大小来确定fun
接受变量的数量和大小。
lb
lb
为下界,为实向量或实数组。如果x0
元素的数目等于lb
元素的数量,那么对于所有的i
,有
x(i) >= lb(i)
如果x0
元素的数目大于lb
元素的数量,那么对于1 <= i <= numel(lb)
,有
x(i) >= lb(i)
如果x0
元素的数目小于lb
元素的数量,解算器发出警告。
ub
lb
为上界。具体解释与 3.3 lb
类似。
options
优化选项,为optimoptions
的输出或optimset
返回的结构体。
一些选项适用于所有的算法,其他选项与特定算法相关。
有些选项是optimoptions
不显示的。这些选项在以下表中用斜体字表示。
有“信任区域反射” trust-region-reflective
(默认)和“列文伯格 - 马夸尔特” levenberg-marquardt
两个选择。
该算法选项的指定有使用偏好。这只是一个偏好,因为某些条件必须满足使用的每个算法。对于信任区域反射算法,方程式的非线性系统不能被欠定,即方程的数目(通过fun
返回的F的元素数)必须至少达到x
的长度。列文伯格 - 马夸特算法不处理边界约束。
比较用户提供的导数(目标或约束的梯度)和有限差分导数。选项是假(默认)或真。
对于optimset
,名字是DerivativeCheck
,值是“on
”或“off
”。
显示关于函数最小化或解决的诊断信息。选项为“off
”(默认)或“on
”。
有限差分梯度的最大变化量(正标量)。默认值为0。
有限差分梯度的最小变化量(正标量)。默认值为0。
显示级别:
off'
或 ‘none
’ :不显示输出iter
’ :在每次迭代中显示输出,并给出了默认退出消息。iter-detailed
’ :在每次迭代中显示输出,并给出了技术退出消息final
’ (默认) :只显示最终输出,并给出了默认退出消息final-detailed
’:只显示最终输出,并给出了技术退出消息有限差分的标量或向量步长因子。当设置FiniteDifferenceStepSize
为向量v
时,正向有限差增量是
delta = v.*sign′(x).*max(abs(x),TypicalX), 当 sign′(x) = sign(x) except sign′(0) = 1
中心有限差分为
delta = v.*max(abs(x),TypicalX)
标量FiniteDifferenceStepSize
扩展为矢量。前向有限差的默认值为sqrt(eps)
,中心有限差分的默认值为eps^(1/3)
。
对于optimset
,名字是FinDiffRelStep
。
有限差分,用来估计梯度,要么是 ‘forward
’ (默认),或 ‘central
’(中心)。 'central
'需要两倍多的函数评价,更准确。
估计这两种类型的有限差分时,该算法应注意遵守边界。因此,例如,它可能需要一个反向的差分,而不是正向的,以避免在一个点的边界外评估。
对于optimset
,名字是FinDiffType
。
函数值上的终止公差是正标量。默认值为1e-6。
对于optimset
,名字是TolFun
。
检查函数值是否有效。’on
’ 在函数返回值为complex
、Inf
或NaN
时显示错误。默认 ‘off
’ 不显示错误。
允许的函数计算的最大数,是一个正整数,默认值是100* numberOfVariables
。
对于optimset
,名字是MaxFunEvals
。
允许的最大迭代次数,一个正整数,默认值是400。
对于optimset
,名字是MAXITER
。
一阶最优终止公差(正标量),默认值为1e-6。
在内部,'levenberg-marquardt'
算法采用1e-4倍的FunctionTolerance
作为最优公差(停止准则),并且不使用OptimalityTolerance
。
对于optimset
,名字是TolFun
。
指定一个或多个用户定义的函数,在每次迭代优化函数调用。传递一个函数手柄或手柄功能的单元数组。默认值值是无([])。
从预定义的绘制函数或自己编写中选择,绘制算法执行过程中的各项度量。传递名字,函数句柄,或单元数组的名或函数句柄。对于自定义绘制功能,传递函数句柄。默认值是无([]):
'optimplotx'
绘制当前点。
'optimplotfunccount'
绘制函数计数。
'optimplotfval'
绘制函数值。
'optimplotresnorm'
绘制残差的范数。
'optimplotstepsize'
绘制步长。
'optimplotfirstorderopt'
绘制一阶最优度量。
对于optimset
,名字是PlotFcns
。
如果为假(默认值),求解器使用有限差分近似雅可比矩阵。如果为是,对目标函数,求解器使用一个用户定义的雅可比(在fun
定义),或雅可比信息(使用JacobMult
时)。
对于optimset
,名字是Jacobian
,值为'on'
或 'off'
。
对x
的终止公差,正标量。默认值为1e-6。
对于optimset
,名字是TolX
。
典型的x值。TypicalX中元素的数目等于起始点x0中元素的数目。默认值是ones(numberofvariables,1)
。解算器的用TypicalX来为梯度估计缩放有限差分。
When true, the solver estimates gradients in parallel. Disable by setting to the default, false. See Parallel Computing.
为真时,求解器用并行方式估计梯度。通过设置为默认值false,可以禁用。
雅可比相乘函数,指定为函数句柄。对于大规模的结构问题,这个函数无需实际构成J
,计算雅可比矩阵乘积 J*Y, J'*Y, or J'*(J*Y)
。
当Jinfo
包含用于计算J*Y (或 J'*Y, 或 J'*(J*Y))
的矩阵时,函数的形式为W = jmfun(Jinfo,Y,flag)
第一个参数Jinfo
必须与由目标函数fun
返回的第二个参数相同,例如,[F,Jinfo] = fun(x)
。
Y
是具有和J
相同的行数,因为在矩阵相乘时有维数要求。flag
确定用何种乘积来计算:
如果flag=0,则W = J'*(J*Y)
。
如果flag>0,则W = J*Y
。
如果flag<0,则W = J'*Y
。
在每种情况下,J没有明确地形成。该解算器使用Jinfo
计算预条件。
注意:
'SpecifyObjectiveGradient'
必须设置为真,使求解器将Jinfo
从fun
传递到jmfun
。
对于optimset
, 名字是JacobMult
。
用雅可比稀疏矩阵计算有限差分。当fun(i)
取决于 x(j)
,设置JacobPattern(i,j) = 1
;否则,设置JacobPattern(i,j) = 0
.换句话说,当 ∂fun(i)/∂x(j) ≠ 0
时,JacobPattern(i,j) = 1
。
当不方便计算fun
中的雅可比矩阵J
时,使用JacobPattern
,但你可以决定(比如,通过检查)什么时候fun(i)
取决于 x(j)
。当你给出JacobPattern
时,求解器可以通过稀疏有限差分近似J
。
如果结构是未知的,不要设置JacobPattern
。默认JacobPattern
是一个密集的矩阵。然后求解器计算在每个迭代时计算一个完整的有限差分近似。这对于大的问题是昂贵的,所以它用来确定稀疏结构通常效果更好。
PCG(预条件共轭梯度)迭代的最大值,正标量。默认值是max(1,numberOfVariables/2)
。
PCG预处理器的上限带宽,一个非负整数。默认PrecondBandWidth
是Inf
,这意味着使用直接分解(Cholesky)而不是使用共轭梯度(CG)。直接因式分解在计算上比CG更昂贵,但对解产生质量更好的步长。设置PrecondBandWidth
为0对对角线预处理(上限带宽为0)。对于一些问题,中间带宽减少了PCG迭代次数。
确定迭代步长是如何计算的。默认值,'factorization'
,花费的时间比'cg'
慢但更准确的步长。
在PCG迭代的终止公差,正标量。默认值是0.1。
列文伯格 - 马夸尔特参数的初始值,正标量。默认值为1e-2。
'jacobian'
有时可以改善一个小规模问题的收敛性;默认值为'none'
。
problem
问题结构,指定为具有以下字段的结构:
Field Name | Entry |
---|---|
objective | 目标函数 |
x0 | x的初始值 |
lb | 下限向量 |
ub | 上限向量 |
solver | ‘lsqnonlin’ |
options | optimoptions创建的选项 |
在问题结构中,你必须至少提供objective, x0, solver, and options
字段。
获得问题结构的最简单的方法是从优化应用程序导出问题。
x
解,返回实向量或者实数组。 x
的大小是与x0
的大小相同。通常,当exitflag
为正时,x
是问题的局部解。
renorm
残差的平方范数,返回非负实数。'resnorm'
是残差在x
的平方2-范数: sum(fun(x).^2)
。
residual
解的目标函数的值,返回一个数组。一般情况下,residual = fun(x)
。
exitflag
求解器退出的原因,返回一个整数。
值 | 退出原因 |
---|---|
1 | 函数收敛至一个解x |
2 | x的变化量小于规定公差 |
3 | 残差的变化量小于规定公差 |
4 | 搜索方向的幅度小于规定公差 |
0 | 迭代次数超出options.MaxIterations 或函数评估次数超出options.MaxFunctionEvaluations |
-1 | 输出函数终止算法 |
-2 | 问题不可行:边界 lb 和 ub 不一致 |
output
关于优化过程的信息,返回含字段的结构:
字段 | 具体意义 |
---|---|
firstorderopt | 一阶最优度量 |
iterations | 迭代次数 |
funcCount | 函数评估次数 |
cgiterations | PCG迭代的次数 (仅适用于trust-region-reflective 算法) |
stepsize | x的最终位移 |
algorithm | 使用的算法 |
message | 退出消息 |
lambda
解的拉格朗日乘数,返回含字段的结构:
字段 | 具体意义 |
---|---|
lower | 下限 lb |
upper | 上限 ub |
jacobian
解的雅可比矩阵,返回作为一个实矩阵。jacobian(i,j)
是在解x
处fun(i)
关于 x(j)
的偏微分。
Levenberg-Marquardt
算法不处理边界约束。
trust-region-reflective
算法不能解决欠定系统。它要求方程的数量,即F的行数,大于等于变量的数量。在未确定的情况下,lsqnonlin
使用Levenberg-Marquardt
算法。
综上,有边界约束的欠定系统问题,不能通过lsqnonlin
解决。
lsqnonlin
可以用Levenberg-Marquardt
算法直接求解复值的问题。然而,这种算法不接受约束的限制。为具有结合 约束的复杂问题,将变量分割为实部和虚部,再使用trust-region-reflective
算法。
计算预处理器之前,预处理器的计算使用了部分trust-region-reflective
的方法的J'J
(其中J是雅可比矩阵)的预条件共轭梯度。因此,J
的一排有许多非零项,导致相当密集的乘积J'J
,可能会对大问题产生昂贵的解决过程。
如果x的元素没有上(或下)限,lsqnonlin
更喜欢将ub
(或Ib
)的相应元素设置为inf
(或-inf
),而不是任意的非常大的正(或负)数。
在解决中小规模的问题时,你可以使用在lsqnonlin
,lsqcurvefit
和fsolve
中的trust-region reflective
算法,不用计算fun
中的雅可比矩阵或提供雅可比稀疏模式。(这也适用于使用fmincon
或fminunc
而不计算Hessian或供给的Hessian稀疏图案。)多小才能叫小中规模?没有绝对的答案,因为它依赖于你的计算机系统配置的虚拟内存。
假设你的问题有m个方程和n个未知数。如果命令J = sparse(ones(m,n))
导致你的机器上出现内存不足错误,那么这是肯定过大的问题。如果没有在一个错误发生,问题仍然可能过大。你只能通过运行它,看看MATLAB运行时系统上虚拟内存可用的总量。