优化 - 将目标函数和梯度函数作为列表传递的参数

5
我有一个同时评估梯度和输出的函数。我想针对目标函数进行优化。我该如何将目标函数和梯度作为列表传递给optimx?下面的示例说明了问题:
假设我想找到多项式x^4-3*x^2+2*x+3的最小非负根。它的梯度是4*x^3 - 6*x + 2。我使用optimx中的nlminb方法,如下所示。
optimx(par = 100, method = "nlminb", fn = function(x) x^4 - 3*x^2 + 2*x + 3, 
                                     gr=function(x) 4*x^3 - 6*x + 2, lower = 0)

这很好用,我得到了以下输出:
       p1 value fevals gevals niter convcode kkt1 kkt2 xtimes
nlminb  1     3     27     24    23        0 TRUE TRUE      0

现在假设我定义了一个名为fngr的函数,它返回目标值和梯度值的列表:

fngr <- function(x) {
  fn <- x^4 - 3*x^2 + 2*x + 3
  gr <- 4*x^3 - 6*x + 2
  return (list(fn = fn, gr = gr))
}

我尝试按如下方式调用optimx:

do.call(optimx, c(list(par = 100, lower = 0, method="nlminb"), fngr))

这导致以下错误返回:
Error in optimx.check(par, optcfg$ufn, optcfg$ugr, optcfg$uhess, lower,  : 
  Function provided is not returning a scalar number

当我想将目标和梯度作为列表传递时,定义fngr和调用optimx的正确方式是什么?

谢谢。


我认为你无法真正摆脱分别定义 fn 和 gr(即使在 @42-'s 的答案中这一点被混淆了)。通常情况下,优化子程序将独立调用每个函数,可能使用不同的参数。你不能假设每次调用 fn 都能与一次调用 gr 完全匹配。 - Hong Ooi
收到,感谢您的输入。 - user3294195
2
虽然有点晚了,但我认为值得考虑是否要对函数进行记忆化处理(有一个memoise包,我想)。 - Ben Bolker
1个回答

3

定义一个无参数函数,当调用时可以返回两个具有合适名称的函数:

> fngr <- function() {
+   fn <- function(x) {x^4 - 3*x^2 + 2*x + 3}
+   gr <- function(x) {4*x^3 - 6*x + 2}
+   return (list(fn = fn, gr = gr))
+ }
> do.call(optimx, c(list(par = 100, lower = 0, method="nlminb"), fngr() ))
                                    notice the need to call it ------^^
       p1 value fevals gevals niter convcode kkt1 kkt2 xtimes
nlminb  1     3     27     24    23        0 TRUE TRUE  0.002

五年后再看这篇文章,我完全能理解读者的困惑。@user3294195 的方式更加常规,而这种方法并不是在R中传递函数对象的典型方式。
该方法的工作原理是:`fngr` 函数返回一个由两个未求值表达式组成的列表,而不是直接返回函数。当形成 `fngr` 函数参数的配对列表中每个项目的 RHS 被遇到时,表达式会使用最可访问的 `x` 值进行求值。这可以通过更简单的测试更清楚地说明:
fnc <- function( x = x, y = x^2){print(x);print(y)}
fnc(x=2:11)
 [1]  2  3  4  5  6  7  8  9 10 11
 [1]   4   9  16  25  36  49  64  81 100 121

在调用 fnc(x=2:11) 之前,globalenv() 中存在一个 x 向量,其值不等于 2:11。因此该函数没有“看到”该值,而是在调用中分配给形式参数 x 的值,并在解释器尝试计算形式参数中的表达式 x^2 时可用。请注意保留 HTML 标记。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接