首页 > 解决方案 > Optim.jl 单变量有界优化在使用 Inf 作为边界时混淆输出

问题描述

以下是说明我的问题的独立示例。

using Optim

χI = 3
ψI = 0.5
ϕI(z) = z^-ψI
λ = 1.0532733
V0 = 0.8522423425
zE = 0.5986

wRD = 0.72166623555


objective1(z) = -(z * χI * ϕI(z + zE)  *  (λ-1) * V0 - z * ( wRD ))
objective2(z) = -1 * objective1(z)

lower = 0.01
upper = Inf

plot(0:0.01:0.1,objective1,title = "objective1")
png("/home/nico/Desktop/objective1.png")
plot(0:0.01:0.1,objective2, title = "objective2")
png("/home/nico/Desktop/objective2.png")

results1 = optimize(objective1,lower,upper)
results2 = optimize(objective2,lower,upper)

这些地块是

目标 1(z) 的图

Objective2(z) 的图

objective1(z)和在其他任何地方都返回和有限值,对于 some 有一个最佳objective2(z)值。NaNz = 0z > 0

但是的输出results1

Results of Optimization Algorithm
 * Algorithm: Brent's Method
 * Search Interval: [0.010000, Inf]
 * Minimizer: Inf
 * Minimum: NaN
 * Iterations: 1000
 * Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
 * Objective Function Calls: 1001

的输出results2

Results of Optimization Algorithm
 * Algorithm: Brent's Method
 * Search Interval: [0.010000, Inf]
 * Minimizer: Inf
 * Minimum: NaN
 * Iterations: 1000
 * Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
 * Objective Function Calls: 1001

我相信问题出在upper = Inf. 例如,如果我将其更改upper = 100为 ,则输出results1

Results of Optimization Algorithm
 * Algorithm: Brent's Method
 * Search Interval: [0.010000, 100.000000]
 * Minimizer: 1.000000e-02
 * Minimum: 5.470728e-03
 * Iterations: 55
 * Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): true
 * Objective Function Calls: 56

results2返回

Results of Optimization Algorithm
 * Algorithm: Brent's Method
 * Search Interval: [0.010000, 100.000000]
 * Minimizer: 1.000000e+02
 * Minimum: -7.080863e+01
 * Iterations: 36
 * Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): true
 * Objective Function Calls: 37

正如预期的那样。

标签: optimizationjulianumerical-methodsnonlinear-optimization

解决方案


正如您在问题中指出的那样 - 您使用有界优化算法,但您将无界间隔传递给它。

引用文档(https://julianlsolvers.github.io/Optim.jl/latest/#user/minimization/),这是精确的,该optimize函数用于在有界区间上最小化单变量函数

提供有关您遇到的问题的更多详细信息。该optimize方法搜索区间内的点。实现了两种算法:布伦特(默认)和黄金分割。他们首先检查的一点是:

new_minimizer = x_lower + golden_ratio*(x_upper-x_lower)

你会看到它new_minimizer会是Inf。所以优化程序甚至无法找到有效的内部点。然后你会看到你的函数返回NaN参数Inf

julia> objective1(Inf)
NaN

julia> objective2(Inf)
NaN

这个组合可以解释为什么找到的最小值Inf和目标NaN在产生的输出中。

第二点是你应该记住Float64数字的精度是有限的,所以你应该选择区间,以确保该方法实际上能够准确地评估其中的目标。例如,即使这失败了:

julia> optimize(objective1, 0.0001, 1.0e308)
Results of Optimization Algorithm
 * Algorithm: Brent's Method
 * Search Interval: [0.000100, 100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336.000000]
 * Minimizer: 1.000005e+308
 * Minimum: -Inf
 * Iterations: 1000
 * Convergence: max(|x - x_upper|, |x - x_lower|) <= 2*(1.5e-08*|x|+2.2e-16): false
 * Objective Function Calls: 1001

原因是objective1对于非常大的参数(因为它具有有限的精度)实际上开始以数值不稳定的方式表现,请参阅:

julia> objective1(1.0e307)
7.2166623555e306

julia> objective1(1.0e308)
-Inf

最后一点是它实际上Optimize告诉你出了点问题,你不应该依赖结果:

julia> results1.converged
false

julia> results2.converged
false

对于问题的初始说明(带有Inf)。


推荐阅读