我需要使用我的渐变函数计算 Hessian 数字(由公式编程,不是数字)。像numDeriv
或rootSolve
这样的包使用不满足我需要的数字渐变来计算粗体。我需要在optim
包中执行内部(没有我可以调用的单独方法),但是处理我的优化任务的唯一方法在nlopt
包中很好地实现并传递了它为了获得粗麻布,optim
的最佳值对于我的程序来说太贵了。
所以我需要一些使用非数值梯度计算Hessian的函数(参见例如这些公式https://neos-guide.org/content/difference-approximations)。我不能做这样的功能,因为我不明白如何选择参数h
(增量),我的功能非常敏感。我可以在R中找到这样的函数,还是从optim
包以某种方式检索它?或者有人至少可以解释如何为h
选择最小化值的错误,那么我会自己发布这个函数吗?
答案 0 :(得分:3)
如果我理解正确,你应该使用numDeriv::jacobian()
,它采用向量值函数并计算矩阵(每个元素相对于每个输入的导数),并将其应用于分析梯度函数。 jacobian()
确实使用数值近似(Richardson外推,确切地说),但我没有看到任何其他方法可以从黑盒渐变函数到Hessian?
您需要指定(或使用默认值)数字“delta”函数(默认为1e-4)。另一方面,optim()
用于计算Hessian的内部代码也使用有限差异:请参阅here和here ...
下面我定义一个函数,它的渐变函数和它的Hessian;此代码显示jacobian(grad(x))
与Hessian相同(对于特定的测试用例)。
library(numDeriv)
x1 <- c(1,1,1)
测试我没有弄乱渐变和Hessian函数:
all.equal(grad(f,x1),g(x1)) ## TRUE
all.equal(h(x1),hessian(f,x1)) ## TRUE
我的Hessian和渐变的雅可比行列式的数值等价:
all.equal(h(x1),jacobian(g,x1)) ## TRUE
测试功能:
f <- function(x) {
sin(x[1])*exp(x[2])*x[3]^2
}
g <- function(x) {
c(cos(x[1])*exp(x[2])*x[3]^2,
sin(x[1])*exp(x[2])*x[3]^2,
sin(x[1])*exp(x[2])*2*x[3])
}
h <- function(x) {
m <- matrix(NA,3,3)
m[lower.tri(m,diag=TRUE)] <-
c(-sin(x[1])*exp(x[2])*x[3]^2,
cos(x[1])*exp(x[2])*x[3]^2,
cos(x[1])*exp(x[2])*2*x[3],
# col 2
sin(x[1])*exp(x[2])*x[3]^2,
sin(x[1])*exp(x[3])*2*x[3],
# col 3
sin(x[1])*exp(x[2])*2)
m <- Matrix::forceSymmetric(m,"L")
m <- unname(as.matrix(m))
return(m)
}