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

use*_*195 5 optimization r

我有一个同时评估梯度和输出的函数。我想根据目标函数对其进行优化。如何将目标和梯度作为列表传递给optimx?下面的例子说明了这个问题:

假设我想找到多项式 的最小非负根x^4 - 3*x^2 + 2*x + 3。其梯度为4*x^3 - 6*x + 2. 我用的方法nlminboptimx,如下图。

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)
Run Code Online (Sandbox Code Playgroud)

这工作正常,我得到以下输出:

       p1 value fevals gevals niter convcode kkt1 kkt2 xtimes
nlminb  1     3     27     24    23        0 TRUE TRUE      0
Run Code Online (Sandbox Code Playgroud)

现在假设我定义了函数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))
}
Run Code Online (Sandbox Code Playgroud)

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

do.call(optimx, c(list(par = 100, lower = 0, method="nlminb"), fngr))
Run Code Online (Sandbox Code Playgroud)

这返回了以下错误:

Error in optimx.check(par, optcfg$ufn, optcfg$ugr, optcfg$uhess, lower,  : 
  Function provided is not returning a scalar number
Run Code Online (Sandbox Code Playgroud)

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

谢谢。

42-*_*42- 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
Run Code Online (Sandbox Code Playgroud)

5年后再看这个,我完全能理解当时的困惑。@ 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
Run Code Online (Sandbox Code Playgroud)

在调用之前:中fnc(x=2:11)恰好有一个x向量globalenv()不是 == 2:11。因此,该函数没有“看到”该值,而是看到在调用中分配给形式的值,然后当解释器尝试评估形式中的x表达式时,该值可用。x^2