【问题标题】:optimization - Passing objective and gradient function arguments as list优化 - 将目标和梯度函数参数作为列表传递
【发布时间】:2022-02-20 13:27:12
【问题描述】:

我有一个函数可以同时评估梯度和输出。我想针对目标函数对其进行优化。如何将目标和梯度作为列表传递给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-的答案中被模糊了)。通常,优化子例程将独立地调用每个函数,可能使用不同的参数。您不能假设对 fn 的每次调用都可以与对 gr 的一次调用完全匹配。
  • 注意,感谢您的意见。
  • 晚了,但我会考虑是否值得memoizing 函数(我认为有一个memoise 包)

标签: r optimization


【解决方案1】:

定义一个无参数函数,它可以在调用时以合适的名称传递这两个函数……

> 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

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

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

【讨论】:

    猜你喜欢
    • 2019-09-27
    • 1970-01-01
    • 2022-01-06
    • 2020-03-14
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    相关资源
    最近更新 更多