R中的优化 - 目标和梯度的高效计算

use*_*195 5 optimization r

我需要针对目标函数优化一组变量。我有函数的解析梯度,并想在优化程序中使用它。目标和梯度有一些常见的计算,我想以最有效的方式定义函数。下面的例子演示了这个问题。

f_obj,f_gradf_common分别是目标、梯度和普通计算的函数。优化是在向量上x。下面的代码找到多项式的根y^3 - 3*y^2 + 6*y + 1,其中y是 的函数c(x[1], x[2])。请注意,该函数f_commonf_obj和中都被调用f_grad。在我的实际问题中,公共计算要长得多,所以我正在寻找一种定义方法f_objf_grad以便f_common最小化调用次数。

f_common <- function(x) x[1]^3*x[2]^3 - x[2]

f_obj <- function(x) {
  y <- f_common(x)
  return ( (y^3 - 3*y^2 + 6*y + 1)^2 )
}

f_grad <- function(x) {
  y <- f_common(x)
  return ( 2 * (y^3 - 3*y^2 + 6*y + 1) * (3*y^2 - 6*y + 6)* c(3*x[1]^2*x[2]^3, 3*x[1]^3*x[2]^2 - 1) )
}

optim(par = c(100,100), fn = f_obj, gr = f_grad, method = "BFGS")
Run Code Online (Sandbox Code Playgroud)

更新

我发现该包nloptr提供了将目标函数及其梯度作为列表输入的工具。有没有办法以类似的方式定义其他优化器((optim、)optimxnlminb(等)?

谢谢。

dww*_*dww 3

将公共函数的值存储在全局变量中,以供后续函数调用使用,如下所示:

f_common <- function(x) x[1]^3*x[2]^3 - x[2]

f_obj <- function(x) {
  y <<- f_common(x)   # <<- operator stores in parent scope
  return ( (y^3 - 3*y^2 + 6*y + 1)^2 )
}

f_grad <- function(x) {
  return ( 2 * (y^3 - 3*y^2 + 6*y + 1) * (3*y^2 - 6*y + 6)* c(3*x[1]^2*x[2]^3, 3*x[1]^3*x[2]^2 - 1) )
}

y<<-0

optim(par = c(100,100), fn = f_obj, gr = f_grad, method = "BFGS")
Run Code Online (Sandbox Code Playgroud)

关于此解决方案,有几点值得补充。

1) 首先,使用 <<- 运算符,严格来说并不分配给全局变量,而是分配给函数的父作用域(即调用它的作用域)中的变量。通常,这通常是全局范围的。这在这里效果很好,并且是更好的方法。也可以使用 allocate() 函数显式使用全局范围,但这里不需要这样做。

2) 还应该注意的是,通常不建议使用全局变量,因为如果在其他地方使用相同的变量名,它们可能会产生意想不到的副作用。为了避免任何可能的副作用,我建议使用诸如 global.f_common 之类的变量名称,该名称永远不会在其他地方使用,并且没有副作用的危险。我只是在示例中使用名称 y 来与原始问题中的术语保持一致。这是极少数情况下,在其函数之外赋予变量作用域可能是合理的,因为很难以其他方式实现所需的行为。只需确保谨慎使用并使用上面建议的唯一名称(例如 global.f_common)即可。