我需要针对目标函数优化一组变量 . 我有函数的分析梯度,并希望在优化例程中使用它 . 目标和梯度有一些共同的计算,我想以最有效的方式定义函数 . 以下示例演示了此问题 .
设 f_obj
, f_grad
和 f_common
分别是目标,梯度和公共计算的函数 . 优化在矢量 x
上 . 以下代码查找多项式 y^3 - 3*y^2 + 6*y + 1
的根,其中 y
是 c(x[1], x[2])
的函数 . 请注意,函数 f_common
在 f_obj
和 f_grad
中都被调用 . 在我的实际问题中,常见的计算要长得多,所以我正在寻找一种方法来定义 f_obj
和 f_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
提供了输入目标函数及其梯度作为列表的工具 . 有没有办法以类似的方式定义其他优化器( optim
, optimx
, nlminb
等)?
谢谢 .
1 回答
将公共函数的值存储在全局变量中,以使其可用于后续函数调用,如下所示:
关于此解决方案,值得添加一些注意事项 .
1)首先,使用<< - 运算符,严格来说并不是指定一个全局变量,而是指定给函数的父作用域中的一个(即调用它的作用域) . 通常,这通常是全球范围的 . 这在这里工作正常,是更好的方法 . 也可以使用assign()函数显式使用全局范围,但这里不需要它 .
2)还应注意,通常不建议使用全局变量,因为如果在其他地方使用相同的变量名,它们可能会产生意外的副作用 . 为了避免任何可能的副作用,我建议使用一个变量名,例如global.f_common,它永远不会在别处使用,也没有副作用的危险 . 我只是在示例中使用名称y来与原始问题中的命名法一致 . 这是极少数情况下,在其功能之外给出可变范围可能是合理的,因为很难以另一种方式实现所需的行为 . 请确保谨慎使用,并使用上面建议的唯一名称(例如global.f_common) .