【问题标题】:Optimization in R - Efficient Computation of Objective and GradientR 中的优化 - 目标和梯度的高效计算
【发布时间】:2016-03-25 17:13:14
【问题描述】:

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

f_objf_gradf_common 分别是目标、梯度和普通计算的函数。优化在向量x 上。下面的代码找到多项式y^3 - 3*y^2 + 6*y + 1 的根,其中yc(x[1], x[2]) 的函数。请注意,函数f_commonf_objf_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")

更新

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

谢谢。

【问题讨论】:

  • 你想要什么>?该代码有效。如果你想最小化 f_common 的调用,你不应该调用它,而是在函数中硬编码 y。
  • 硬编码两个函数中的公共计算相当于调用 f_common(就执行时间而言)。我正在寻找一种消除冗余计算的方法。使用我的代码,如果优化例程是在 x 点计算f_obj 并在该点找到它的梯度,则需要调用 f_common 两次,但我们只需要计算一次 y
  • 也许你可以使用像memoise这样的包来缓存f_common的结果。

标签: r optimization


【解决方案1】:

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

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")

有关此解决方案的几点说明值得补充。

1) 首先,使用

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

【讨论】:

  • 我们确定在调用具有 x 的梯度函数之后总是调用具有相同 x 的目标函数吗?例如,如果 grad(x2) 在计算 obj(x1) 之后立即计算,那么它会导致问题。除非了解 optim 函数中的所有过程,否则看起来很冒险。
  • 我确实对此做了几项检查:在 obj 和 grad 函数中使用 print(y) 并在 Optim 中使用 trace 选项。结果是这种方法遵循与在 OP 中计算 y 两次完全相同的优化路径。此外,重要的是要认识到,除了已经计算了目标函数的位置之外,optim 不计算梯度很重要,就是这种情况。
猜你喜欢
  • 1970-01-01
  • 2023-02-10
  • 2017-03-22
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 2020-09-15
相关资源
最近更新 更多