我应该在命令“Hessian”和“numericHessian”之间信任哪些结果?

时间:2014-04-04 21:00:28

标签: r standard-deviation hessian-matrix

我试图从我自己的数据中获取Hessian矩阵,我有两个结果 -

  • 使用库中的代码Hessian(numDeriv)
  • 使用库中的代码numericHessian(maxLik)

相对于numericHessian的结果,Hessian的结果非常小。

在这种情况下,我应该信任哪些结果?

具体来说,我使用的数据范围从350000到1100000,它们是9X2矩阵,总共有18个数据值。

我使用了一种标准偏差公式,“numericHessian”的结果从2到2矩阵的230到466不等,而“Hessian”的结果从-3.42e-18到1.34e-17不等。比前一个少得多。

您认为哪一种标准差的正确计算?

代码如下:

 data=read.table("C:/file.txt", header=T);
 data <- as.matrix(data);
 library(plyr)
 library(MASS)
 w1 = tail(data/(rowSums(data)),1)
 w2 = t(w1)
 f <- function(x){
 w1 = tail(x/(rowSums(x)),1)
 w2 = t(w1)
 r = ((w1%*%cov(cbind(x))%*%w2)^(1/2))
 return(r)
 }
 library(maxLik); 
 numericHessian(f, t0=rbind(data[1,1], data[1,2]))
 library(numDeriv);
 hessian(f, rbind(data[1,1], data[1,2]), method="Richardson")

file.txt如下:

  1                  2

 137                201

 122                342

 142                111

 171                126

 134                123

 823                876

 634                135

 541                214

 423                142

“numericHessian”的结果是:

          [,1]        [,2]
 [1,] 0.007105427 0.007105427
 [2,] 0.007105427 0.000000000

然后,“Hessian”的结果是:

          [,1]          [,2]
 [1,] -3.217880e-15 -1.957243e-16
 [2,] -1.957243e-16  1.334057e-16

非常感谢你。

1 个答案:

答案 0 :(得分:4)

你没有给reproducible example,但我还是会尝试。

library(bbmle)
 x <- 0:10
 y <- c(26, 17, 13, 12, 20, 5, 9, 8, 5, 4, 8)
 d <- data.frame(x,y)
 LL <- function(ymax=15, xhalf=6)
     -sum(stats::dpois(y, lambda=ymax/(1+x/xhalf), log=TRUE))
 fit <- mle2(LL)
 cc <- coef(fit)

以下是MLE中负对数似然函数的Hessian(二阶导数矩阵)的有限差分估计:反演这些矩阵给出了参数的方差 - 协方差矩阵的估计。

 library(numDeriv)
 hessian(LL,cc)
 ##               [,1]          [,2]
 ## [1,]  1.296717e-01 -1.185789e-15
 ## [2,] -1.185789e-15  4.922087e+00

 library(maxLik)
 numericHessian(LL, t0=cc)
 ##           [,1]     [,2]
 ## [1,] 0.1278977 0.000000
 ## [2,] 0.0000000 4.916956

因此,对于这个相对简单的示例,numDeriv::hessianmaxLik::numericHessian给出了非常相似的结果。因此,必须有一些你没有向我们展示过的东西,或者关于你问题的数字的特别之处。为了进一步发展,我们需要一个可重现的例子,请...

dat <- matrix(c(137,201,122,342,142,111,
                171,126,134,123,823,876,
                634,135,541,214,423,142),
        byrow=TRUE,ncol=2)
f <- function(x){
    w1 <- tail(x/(rowSums(x)),1)
    sqrt(w1%*%cov(cbind(x))%*%t(w1))
}
p <- t(dat[1,1:2,drop=FALSE])
f(p)  ## 45.25483
numDeriv::hessian(f,p)
##              [,1]          [,2]
## [1,] -3.217880e-15 -1.957243e-16
## [2,] -1.957243e-16  1.334057e-16
maxLik::numericHessian(f,t0=p)
##            [,1]        [,2]
## [1,] 0.007105427 0.007105427
## [2,] 0.007105427 0.000000000
好的,这些明显不同意。我不确定原因,但在这种特殊情况下,我们可以分析您正在做的事情,看看哪一个是正确的:

  • 由于您的输入矩阵是单列,x/rowSums(x)是1的向量,因此最后一个元素(w1 <- tail(...,1))只有1。
  • 所以你的表达式会减少到sqrt(cov(cbind(x)))。同样,由于x是一列矩阵,cov()只是方差,sqrt(cov(.))只是标准偏差,或矢量的范数。
  • 方差是任何元素与均值的偏差的二次函数,因此标准差在与均值的偏差上或多或少是线性的(零除外),因此我们期望二阶导数为零。所以看起来numDeriv::hessian正在给出正确答案

我们还可以通过提高eps的{​​{1}}来确认这一点:

numericHessian

底线是maxLik::numericHessian(f,t0=p,eps=1e-3) ## [,1] [,2] ## [1,] 0 0.000000e+00 ## [2,] 0 -7.105427e-09 使用更准确(但更慢)的方法,但如果您小心,可以从numDeriv获得合理的答案。