首页 文章

R - 有效计算物镜和梯度的优化

提问于
浏览
4

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

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

UPDATE

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

谢谢 .

1 回答

  • 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)首先,使用<< - 运算符,严格来说并不是指定一个全局变量,而是指定给函数的父作用域中的一个(即调用它的作用域) . 通常,这通常是全球范围的 . 这在这里工作正常,是更好的方法 . 也可以使用assign()函数显式使用全局范围,但这里不需要它 .

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

相关问题