1

更新:对于访问此页面的其他任何人,值得看看这个 SO 问题和答案,因为我怀疑那里的解决方案与我在这里遇到的问题有关。

这个问题与我在julia-users mailing list上提出的问题重复,但我还没有在那里得到回复(诚然只有 4 天),所以我想我会在这里问。

我从 Julia 调用 NLopt API,尽管我认为我的问题与 Julia 语言无关。

我正在尝试使用 COBYLA 解决优化问题,但在许多情况下我未能触发停止标准。我的问题相当复杂,但我可以用一个更简单的例子重现问题行为。

具体来说,我尝试x1^2 + x2^2 + 1使用 COBYLA 最小化,并将两者都ftol_rel设置ftol_abs0.5. 我的目标函数包括一个将当前值打印到控制台的语句,因此我可以观察收敛情况。收敛期间打印到控制台的最后五个值是:

1.161
1.074
1.004
1.017
1.038

我的理解是,这些步骤中的任何一个都应该触发停止标准。所有步骤都小于0.5,所以应该触发ftol_abs。此外,每个值大约是1,并且0.5*1 = 0.5,因此所有步骤也应该触发ftol_rel。事实上,收敛例程中的最后 8 个步骤也是如此。

NLopt 已经存在了一段时间,所以我猜问题在于我对如何ftol_absftol_rel工作的理解,而不是一个错误。

谁能解释为什么没有更早地触发停止标准?

如果它有任何用处,可以使用以下 Julia 代码片段来重现我刚才所说的所有内容:

using NLopt
function objective_function(param::Vector{Float64}, grad::Vector{Float64})
    obj_func_value = param[1]^2 + param[2]^2 + 1.0
    println("Objective func value = " * string(obj_func_value))
    println("Parameter value = " * string(param))
    return(obj_func_value)
end
opt1 = Opt(:LN_COBYLA, 2)
lower_bounds!(opt1, [-10.0, -10.0])
upper_bounds!(opt1, [10.0, 10.0])
ftol_rel!(opt1, 0.5)
ftol_abs!(opt1, 0.5)
min_objective!(opt1, objective_function)
(fObjOpt, paramOpt, flag) = optimize(opt1, [9.0, 9.0])
4

1 回答 1

1

大概,ftol_rel并且ftol_abs应该提供数字保证的错误。较早的值足够接近,但算法可能无法保证。例如,评估点的梯度或 Hessian 可能提供这样的数值保证。所以,它继续前进了一点。

可以肯定的是,最好查看优化算法源。如果我管理这个,我会将它添加到这个答案中。

更新:COBYLA 算法使用几个评估点在数值上逼近梯度(向量导数)。如前所述,这用于对可能的错误进行建模。仅对于仅限于某些良好系列的函数(例如,具有一定度数的多项式),才能真正在数学上保证错误。

带回家留言:没关系。不是错误,而是算法可以做到的最好的。让它有那些额外的迭代。

于 2016-01-13T18:16:37.477 回答