# fminunc
求无约束多变量函数的最小值
函数库: TyOptimization
# 语法
x,fval,exitflag,output,grad,hessian = fminunc(fun,x0)
_ = fminunc(fun,x0,options)
_ = fminunc(problem)
# 说明
非线性规划求解器。
求以下问题的最小值:
其中,f(x) 是返回标量的函数。
x 是向量。
x,fval,exitflag,output,grad,hessian = fminunc(fun,x0) 在点 x0 处开始并尝试求 fun 中描述的函数的局部最小值 x。点 x0 为向量。fminunc 返回以下值:示例
- x - 函数的局部最小值;
- fval - 目标函数 fun 在解 x 处的值;
- exitflag - 描述 fminunc 的退出条件的值;
- output - 提供优化过程信息的结构体;
- grad - fun 在解 x 处的梯度;
- hessian - fun 在解 x 处的 Hessian 矩阵。请参阅 fminunc Hessian 矩阵。
注意
传递额外参数说明如何将额外的参数传递给目标函数和非线性约束函数(如有必要)。fminunc 适用于无约束非线性问题。如果您的问题有约束,通常使用 fmincon。请参阅优化决策表。
_ = fminunc(fun,x0,options) 使用 options 中指定的优化选项最小化 fun。使用 optimoptions 可设置这些选项。示例
_ = fminunc(problem) 求 problem 的最小值,它是 problem 中所述的一个结构体。示例
# 示例
最小化多项式
最小化函数:
为此,编写用于计算目标的匿名函数 fun。
using TyOptimization
fun = x->3*x[1]^2 + 2*x[1]*x[2] + x[2]^2 - 4*x[1] + 5*x[2]
调用 fminunc 以在 [1,1] 附近处求 fun 的最小值。
x0 = [1,1]
x,fval = fminunc(fun,x0)
Local minimum found.
Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
x = -element Vector{Float64}:
2.250000566676826
-4.749999847965972
fval = -16.374999999998842
提供梯度
当您提供导数时,fminunc 可以执行得更快、也更可靠。
编写返回梯度和函数值的目标函数。使用包括梯度和 Hessian 矩阵 中所述的条件化形式。目标函数是 Rosenbrock 函数,
它有梯度
using TyOptimization
rosenbrockwithgrad = x->begin
f = 100*(x[2] - x[1]^2)^2 + (1-x[1])^2
g = [-400*(x[2]-x[1]^2)*x[1]-2*(1-x[1]);200*(x[2]-x[1]^2)]
return f,g
end
创建使用目标函数的梯度的选项。此外,将算法设置为 "trust-region"。
options = optimoptions(:fminunc,Algorithm="trust-region",SpecifyObjectiveGradient=true)
将初始点设置为 [-1,2]。然后调用 fminunc。
x0 = [-1,2]
fun = rosenbrockwithgrad
x, = fminunc(fun,x0,options)
Local minimum found.
Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
x = 2-element Vector{Float64}:
0.9999999956349372
0.9999999911786484
使用问题结构体
使用问题结构体而不是单独的参数来求解与提供梯度中相同的问题。
编写返回梯度和函数值的目标函数。使用包括梯度和 Hessian 矩阵 中所述的条件化形式。目标函数是 Rosenbrock 函数,
它有梯度
using TyOptimization
rosenbrockwithgrad = x->begin
f = 100*(x[2] - x[1]^2)^2 + (1-x[1])^2
g = [-400*(x[2]-x[1]^2)*x[1]-2*(1-x[1]);200*(x[2]-x[1]^2)]
return f,g
end
创建使用目标函数的梯度的选项。此外,将算法设置为 "trust-region"。
options = optimoptions(:fminunc,Algorithm="trust-region",SpecifyObjectiveGradient=true)
创建包括初始点 x0 = [-1,2] 的问题结构体。有关此结构体中的必填字段,请参见 problem。
x0 = [-1,2]
objective = rosenbrockwithgrad
solver = "fminunc"
problem = (;options,x0,objective,solver)
求解。
x, = fminunc(problem)
Local minimum found.
Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
x = 2-element Vector{Float64}:
0.9999999956349372
0.9999999911786484
# 输入参数
fun — 要计算最小值的函数函数句柄
要最小化的函数,指定为函数句柄或函数名称。fun 接受向量 x,并返回实数标量 f,即在 x 处计算的目标函数值。
将 fun 指定为文件的函数句柄:
x = fminunc(myfun,x0)
其中 myfun 是一个 Syslab 函数,例如
myfun = x-> begin
f = ... # 计算 x 处的函数值
return f
end
您还可以为匿名函数指定 fun 作为函数句柄:
x = fminunc(x->norm(x)^2,x0)
如果您可以计算 fun 的梯度且 SpecifyObjectiveGradient 选项设置为 true,设置如下
options = optimoptions(:fminunc,SpecifyObjectiveGradient=true)
则 fun 必须在第二个输出参数中返回梯度向量 g(x)。
如果您还可以计算 Hessian 矩阵,并通过 options = optimoptions(:fminunc,HessianFcn="objective") 将 HessianFcn 选项设置为 "objective",且将 Algorithm 选项设置为 "trust-region",则 fun 必须在第三个输出参数中返回 Hessian 值 H(x),即一个对称矩阵。fun 可以给出稀疏 Hessian 矩阵。有关详细信息,请参阅适用于 fminunc 信赖域或 fmincon 信赖域反射算法的 Hessian 矩阵。
trust-region 算法允许您提供 Hessian 矩阵乘法函数。此函数给出 Hessian 乘以向量的乘积结果,而不直接计算 Hessian 矩阵。这可以节省内存。请参阅 Hessian 矩阵乘法函数。
示例: fun = x->sin(x[1])*cos(x[2])
x0 — 初始点实数向量 | 实数数组
初始点,指定为实数向量或实数数组。求解器使用 x0 中的元素数量来确定 fun 接受的变量数量。
示例: x0 = [1,2,3,4]
options — 优化选项optimoptions 的输出
优化选项,指定为 optimoptions 的输出。
一些选项适用于所有算法,其他选项则与特定算法相关。有关详细信息,请参阅优化选项参考。
optimoptions 显示中缺少某些选项。这些选项在下表中以斜体显示。有关详细信息,请参阅查看优化选项。
| 所有算法 | |
| Algorithm | 选择 fminunc 算法。选项是 "quasi-newton"(默认值)或 "trust-region"。"trust-region" 算法要求您提供梯度(请参阅 fun 的说明),否则 fminunc 将使用 "quasi-newton" 算法。 |
| DerivativeCheck | 将用户提供的导数(目标的梯度)与有限差分导数进行比较。选项是 false(默认值)或 true。 |
| Diagnostics | 显示关于要最小化或求解的函数的诊断信息。选项是 false(默认值)或 true。 |
| DiffMaxChange | 有限差分梯度变量的最大变化(正标量)。默认值为 Inf。 |
| DiffMinChange | 有限差分梯度变量的最小变化(正标量)。默认值为 0。 |
| Display | 显示级别:
|
| FiniteDifferenceStepSize | 有限差分的标量或向量步长因子。当您将 FiniteDifferenceStepSize 设置为向量 v 时,前向有限差分 delta 是 delta = v.*sign′(x).*max.(abs.(x),TypicalX) 其中 sign′(x) = sign(x)(例外是 sign′(0) = 1)。中心有限差分是 delta = v.*max.(abs.(x),TypicalX) 标量 FiniteDifferenceStepSize 扩展为向量。默认值 Float64[] 为占位符。fminunc 在内部将使用 fill(sqrt(eps()),numberOfVariables) 或 fill(eps()^(1/3),numberOfVariables) 覆盖此默认值。正向有限差分使用 fill(sqrt(eps()),numberOfVariables);中心有限差分使用 fill(eps()^(1/3),numberOfVariables)。 仅当 DerivativeCheck 设置为 true 时,信赖域算法才使用 FiniteDifferenceStepSize。 |
| FiniteDifferenceType | 用于估计梯度的有限差分是 "forward"(默认值)或 "central"(中心化)。"central" 需要两倍的函数计算次数,但应更准确。仅当 DerivativeCheck 设置为 true 时,信赖域算法才使用 FiniteDifferenceType。 |
| FunValCheck | 检查目标函数值是否有效。默认设置 false 不执行检查。当目标函数返回的值是 complex、Inf 或 NaN 时,true 设置显示错误。 |
| MaxFunctionEvaluations | 允许的函数计算的最大次数,为正整数。默认值 -1 为占位符,fminunc 在内部将使用 100*numberOfVariables 覆盖该默认值。如果指定该项为 -10,则 fminunc 不会因为函数计算次数而停止。 |
| MaxIterations | 允许的迭代最大次数,为正整数。默认值为 400。如果指定该项为 -10,则 fminunc 不会因为迭代次数而终止。 |
| OptimalityTolerance | 一阶最优性的终止容差(正标量)。默认值为 1e-6。 |
| SpecifyObjectiveGradient | 用户定义的目标函数梯度。请参阅 fun 的说明,了解如何在 fun 中定义梯度。设置为 true,以使 fminunc 采用用户定义的目标函数梯度。默认值 false 会导致 fminunc 使用有限差分来估计梯度。您必须提供梯度,并将 SpecifyObjectiveGradient 设置为 true 才能使用信赖域算法。拟牛顿算法不需要此选项。 |
| StepTolerance | 关于正标量 x 的终止容差。默认值为 1e-6。 |
| TypicalX | 典型的 x 值。TypicalX 中的元素数等于变量数。默认值 Float64[] 为占位符,fminunc 在内部将使用 ones(numberofvariables) 覆盖此默认值。fminunc 使用 TypicalX 缩放有限差分来进行梯度估计。trust-region 算法仅对 DerivativeCheck 选项使用 TypicalX。 |
| trust-region 算法 | |
| FunctionTolerance | 关于函数值的终止容差,为正标量。默认值为 1e-6。 |
| HessianFcn | 如果设置为 ""(默认值),fminunc 使用有限差分逼近 Hessian 矩阵。如果设置为 "objective",fminunc 对目标函数使用用户定义的 Hessian 矩阵。Hessian 矩阵是目标函数的第三个输出(请参阅 fun)。 |
| HessianMultiplyFcn | Hessian 矩阵乘法函数,指定为函数句柄。对于大规模结构问题,此函数计算 Hessian 矩阵乘积 H*Y,而并不实际构造 H。函数的形式是 W = hmfun(Hinfo,Y),其中 Hinfo 包含用于计算 H*Y 的矩阵。上述第一个参数与目标函数 fun 返回的第三个参数相同,例如 f,g,Hinfo = fun(x)。Y 是矩阵,其行数与问题中的维数相同。矩阵 W = H*Y(尽管其中 H 未显式构造)。fminunc 使用 Hinfo 计算预条件子。注意要使用 HessianMultiplyFcn 选项,HessianFcn 必须设置为 ""。 |
| HessPattern | 用于有限差分的 Hessian 矩阵稀疏模式。如果存在 ∂2fun/∂x[i]∂x(j) ≠ 0,则设置 HessPattern[i,j] = 1。否则,设置 HessPattern[i,j] = 0。如果不方便在 fun 中计算 Hessian 矩阵 H,但您可以确定(例如,通过检查)fun 的梯度的第 i 个分量何时依赖 x[j],请使用 HessPattern。如果您提供 H 的稀疏结构作为 HessPattern 的值,fminunc 可以通过稀疏有限差分(梯度)逼近 H。这相当于提供非零元的位置。当结构未知时,不要设置 HessPattern。默认行为是将 HessPattern 视为由 1 组成的稠密矩阵。然后,fminunc 在每次迭代中计算满有限差分逼近。对于大型问题,这种计算可能成本高昂,因此通常最好确定稀疏结构。 |
| MaxPCGIter | PCG(预条件共轭梯度)迭代的最大次数,指定为正整数标量。默认值 -1 为占位符,fminunc 在内部将使用 max(1,div(numberOfVariables,2)) 覆盖此默认值。 |
| PrecondBandWidth | PCG 的预条件子上带宽,非负整数。默认情况下,fminunc 使用对角预条件处理(上带宽为 0)。对于某些问题,增加带宽会减少 PCG 迭代次数。将 PrecondBandWidth 设置为 -10 会使用直接分解 (Cholesky),而不是共轭梯度 (CG)。直接分解的计算成本较 CG 高,但所得的求解步质量更好。 |
| SubproblemAlgorithm | 确定迭代步的计算方式。与 "factorization" 相比,默认值 "cg" 采用的步执行速度更快,但不够准确。 |
| TolPCG | PCG 迭代的终止容差,正标量。默认值为 0.1。 |
| quasi-newton 算法 | |
| HessianApproximation | 指定 fminunc 计算 Hessian 矩阵的方法。选项包括:
|
| ObjectiveLimit | 容差(停止条件),标量。如果迭代中的目标函数值小于或等于 ObjectiveLimit,迭代将停止,因为问题可能是无界的。默认值为 -1e20。 |
示例: options = optimoptions(:fminunc,SpecifyObjectiveGradient=true)
problem — 问题结构体结构体
问题结构体,指定为含有以下字段的结构体:
| 字段名称 | 条目 |
|---|---|
| objective | 目标函数 |
| x0 | x 的初始点 |
| solver | "fminunc" |
| options | 用 optimoptions 创建的选项 |
# 输出参数
x — 解实数向量
解,以实数向量或实数数组形式返回。x 的大小与 x0 的大小相同。通常情况下,当 exitflag 为正时,x 是该问题的局部解。有关解质量的信息,请参阅求解成功后。
fval — 解处的目标函数值实数标量
解处的目标函数值,以实数形式返回。通常,fval = fun(x)。
exitflag — fminunc 停止的原因整数
fminunc 停止的原因,以整数形式返回。
| 所有算法: | |
| 1 | 梯度的模小于 OptimalityTolerance 容差。 |
| 2 | x 的变化小于 StepTolerance 容差。 |
| 3 | 目标函数值的变化小于 FunctionTolerance 容差。 |
| 5 | 目标函数的预测下降小于 FunctionTolerance 容差。 |
| 0 | 迭代次数超出 MaxIterations 或函数计算次数超过 MaxFunctionEvaluations。 |
| -3 | 当前迭代的目标函数低于 ObjectiveLimit。 |
output — 有关优化过程的信息结构体
| iterations | 执行的迭代次数 |
| funcCount | 函数计算次数 |
| firstorderopt | 一阶最优性的度量 |
| algorithm | 使用的优化算法 |
| cgiterations | PCG 迭代总数(仅适用于 "trust-region" 算法) |
| lssteplength | 相对于搜索方向的线搜索步的步长(仅适用于 "quasi-newton" 算法) |
| stepsize | x 中的最终位移 |
| message | 退出消息 |
grad — 解处的梯度实数向量
解处的梯度,以实数向量形式返回。grad 给出 fun 在 x 点处的梯度。
hessian — 逼近 Hessian 矩阵实矩阵
逼近 Hessian 矩阵,以实矩阵形式返回。有关 hessian 的含义,请参阅Hessian 矩阵输出。
如果 HessianApproximation 选项是 "lbfgs" 或 ("lbfgs",n),则返回的 hessian 是 0×0 Matrix{Float64}。
# 算法
拟牛顿算法
信赖域算法
# 参考文献
[1] Broyden, C. G. “The Convergence of a Class of Double-Rank Minimization Algorithms.” Journal Inst. Math. Applic., Vol. 6, 1970, pp. 76–90.
[2] Coleman, T. F. and Y. Li. “An Interior, Trust Region Approach for Nonlinear Minimization Subject to Bounds.” SIAM Journal on Optimization, Vol. 6, 1996, pp. 418–445.
[3] Coleman, T. F. and Y. Li. “On the Convergence of Reflective Newton Methods for Large-Scale Nonlinear Minimization Subject to Bounds.” Mathematical Programming, Vol. 67, Number 2, 1994, pp. 189–224.
[4] Davidon, W. C. “Variable Metric Method for Minimization.” A.E.C. Research and Development Report, ANL-5990, 1959.
[5] Fletcher, R. “A New Approach to Variable Metric Algorithms.” Computer Journal, Vol. 13, 1970, pp. 317–322.
[6] Fletcher, R. “Practical Methods of Optimization.” Vol. 1, Unconstrained Optimization, John Wiley and Sons, 1980.
[7] Fletcher, R. and M. J. D. Powell. “A Rapidly Convergent Descent Method for Minimization.” Computer Journal, Vol. 6, 1963, pp. 163–168.
[8] Goldfarb, D. “A Family of Variable Metric Updates Derived by Variational Means.” Mathematics of Computing, Vol. 24, 1970, pp. 23–26.
[9] Shanno, D. F. “Conditioning of Quasi-Newton Methods for Function Minimization.” Mathematics of Computing, Vol. 24, 1970, pp. 647–656.