我对Nelder-Mead算法(1)的特定实现有疑问,该算法以一种不寻常的方式处理盒子约束。我找不到任何论文(25篇论文),教科书(在其中搜索4篇)或互联网上找不到任何东西。
我有一个典型的优化问题:min f(x)
,带有框约束-0.25 <= x_i <= 250
预期的方法将使用惩罚函数,并确保x超出范围时f(x)
的所有实例都是“无吸引力的”。
算法的工作原理不同:所讨论的实现不会碰到f(x)
。相反,它使用反双曲正切atanh(f)
扭曲了参数空间。现在,单纯形算法可以在无边界的空间中自由操作,并且可以选择任意一点。为了获取x处的解,f(x)
之前,算法会切换回正常空间。
乍一看,我发现这个主意很巧妙。这样我们避免了惩罚函数的缺点。但是现在我有疑问。扭曲的空间会影响终止行为。一个终止标准是单纯形的大小。通过使用atanh(x)
扩展参数空间,我们还可以扩展单纯形的大小。
对该算法的实验还表明,它无法按预期工作。我还不了解这是怎么发生的,但是我确实得到了超出范围的结果。我可以说返回的本地极小值几乎有一半超出范围。
作为示例,请看一下逐步改变框约束宽度时的nmkb()优化Rosenbrook函数:
rosbkext <- function(x) {
# Extended Rosenbrock function
n <- length(x)
sum (100*(x[1:(n-1)]^2 - x[2:n])^2 + (x[1:(n-1)] - 1)^2)
}
np <- 6 #12
for (box in c(2, 4, 12, 24, 32, 64, 128)) {
set.seed(123)
p0 <- rnorm(np)
p0[p0 > +2] <- +2 - 1E-8
p0[p0 < -2] <- -2 + 1E-8
ctrl <- list(maxfeval = 5E4, tol = 1E-8)
o <- nmkb(fn = rosbkext, par = p0, lower = -box, upper = +box, control = ctrl)
print(o$message)
cat("f(", format(o$par, digits = 2), ") =", format(o$value, digits=3), "\n")
}
输出表明它声称收敛,但在三种情况下没有收敛。并针对(-2,2)和(-12,12)的边界执行此操作。我可能会接受,但随后它也会在(-128,128)处失败。我还对不受约束的dfoptim :: nmk()进行了尝试。那里没有麻烦。它完美收敛。
[1] "Successful convergence"
f( -0.99 0.98 0.97 0.95 0.90 0.81 ) = 3.97
[1] "Successful convergence"
f( 1 1 1 1 1 1 ) = 4.42e-09
[1] "Successful convergence"
f( -0.99 0.98 0.97 0.95 0.90 0.81 ) = 3.97
[1] "Successful convergence"
f( 1 1 1 1 1 1 ) = 1.3e-08
[1] "Successful convergence"
f( 1 1 1 1 1 1 ) = 4.22e-09
[1] "Successful convergence"
f( 1 1 1 1 1 1 ) = 8.22e-09
[1] "Successful convergence"
f( -0.99 0.98 0.97 0.95 0.90 0.81 ) = 3.97
为什么约束算法比无约束算法收敛困难?
脚注(1):我指的是R中optimx程序包中使用的Nelder-Mead实现。此程序包使用nmkb函数调用另一个程序包dfoptim。
答案 0 :(得分:1)
(这个问题与optimx
无关,nmkb()
只是提供无约束优化的R包的包装。)
有问题的函数是 dfoptim 包中的hjkb()
,用于无梯度优化例程。将有界区域变换为无界空间的方法是一种常见的方法,可以应用许多不同的变换函数,有时取决于边界的类型和/或目标函数的类型。它也可以用于将无界的集成域转换为有界的域。
如果最优值位于边界处,则该方法存在问题,因为最优点将被发送到(几乎)无穷大,并且最终无法到达。例程无法收敛或解决方案不准确。
如果您认为算法无法正常工作,则应写信给该软件包的作者,这很重要-要添加一个或两个示例来说明您认为是错误或不正确的解决方案。没有明确的代码示例,这里没有人可以为您提供帮助。
(1)那些变换定义了有界和无界区域之间的双射映象,这种方法背后的理论是显而易见的。您可能会在有关多元微积分的书中读到有关可能的转换的信息。
(2)具有超出范围的惩罚的方法有其自身的缺点,例如目标函数在边界处将不平滑,并且BFGS方法可能不再适用。
(3)您可以在同一 dfoptim 包中通过函数nmkb()
尝试Hooke-Jeeves算法。它会比较慢,但是会使用不同的方法来处理边界,不涉及任何转换。
编辑(在与上文的Erwin Kalvelagen讨论之后)
似乎存在局部最小值(某些坐标为负)。
如果将下限设置为0,则无论如何(1,1,1,1,1,1)
都会找到全局最小值.jsonl.gz
。
注意:起始值必须可行,即所有坐标都必须大于0。