R函数stats::arima
调用C_ARIMA_transPars
来转换自回归系数并将它们保持在平稳区域。
需要这种变换的导数来获得参数估计的标准误差。它们是通过C_ARIMA_Gradtrans
获得的。
在我正在使用的AR(2)模型的情况下,后者函数返回的导数看起来不准确。如下所示,它们与通过数值方法(基于包numDeriv
)获得的值以及基于AR(2)模型易于获得的解析表达式获得的值不同。
AR(2)模型的示例:
生成并转换AR系数:
require("numDeriv")
# random values for the AR coefficients
ARcoefs <- rnorm(2)
# transformation of AR coefficients
tp1 <- .Call(stats:::C_ARIMA_transPars, ARcoefs, c(2L,0L,0L,0L,0L,0L,0L), TRUE)[[1]]
# for the AR(2) model, the above reduces to:
tp2 <- tanh(ARcoefs)
tp2[1] <- tp2[1] - tp2[2] * tp2[1]
all.equal(tp1, tp2)
# [1] TRUE
关于参数的转换的衍生物:
# based on package "stats"
g1 <- .Call(stats:::C_ARIMA_Gradtrans, ARcoefs, c(2L,0L,0L,0L,0L,0L,0L))
# based on package "numDeriv" (numerical derivatives)
fnc <- function(x, i) .Call(stats:::C_ARIMA_transPars,
x, c(2L,0L,0L,0L,0L,0L,0L), TRUE)[[1]][i]
g2 <- matrix(0, nrow=2, ncol=2)
g2[,1] <- numDeriv::grad(func=fnc, x=ARcoefs, i=1)
g2[,2] <- numDeriv::grad(func=fnc, x=ARcoefs, i=2)
# based on analytical derivatives
g3 <- matrix(0, nrow=2, ncol=2)
tmp <- 1/cosh(ARcoefs)^2
g3[1,1] <- tmp[1] - tanh(ARcoefs[2]) * tmp[1]
g3[2,2] <- tmp[2]
g3[2,1] <- -tanh(ARcoefs[1]) * tmp[2]
第二种和第三种方法相互匹配,但与使用C_ARIMA_Gradtrans
获得的结果不同。
all.equal(g2, g3)
# [1] TRUE
# output for ARcoefs = c(0.7, -0.4)
all.equal(g2, g1)
# [1] "Mean relative difference: 0.0004672373"
# output for ARcoefs = c(0.7, -0.4)
all.equal(g3, g1)
# [1] "Mean relative difference: 0.0004672373"
查看source code,找出涉及哪种方法或操作(数值或分析衍生物)并非直截了当。
奇怪的是,没有使用cosh(它是转换中使用的tanh的衍生物的一部分)。此外,使用定义为eps
的变量1e-3
,但这不会出现在分析导数中。也许cosh是由其他(不太准确)的手段计算的?
有没有理由解释上面显示的不太准确的结果?
答案 0 :(得分:1)
(应该是评论,但写作格式化的答案......)
看起来这个块实际上是用1e-3的epsilon计算有限差分(如上所述):
for (int i = 0; i < mp; i++) w1[i] = raw[i];
partrans(mp, w1, w2); /* transform raw (w1) to w2 */
for (int i = 0; i < mp; i++) {
w1[i] += eps;
partrans(mp, w1, w3); /* w3 = trans(w1+eps) */
for (int j = 0; j < mp; j++) /* calc derivative */
A[i + j*n] = (w3[j] - w2[j])/eps;
w1[i] -= eps; /* restore value of w1 */
}
我想知道你可以用于AR(2)的简单解析表达式是否会因高阶AR模型而变得过于笨重?
我建议下一个调试步骤(不容易,除非你已经为它设置)将编译ARIMA_Gradtrans
的独立版本,其值为eps
看看在这种情况下是否有帮助...
或者将numDeriv::grad()
与method="simple", method.args=list(eps=1e-3)
一起使用,看看它是否与ARIMA_Gradtrans
结果相符。
按照上面的代码:
g2A <- t(jacobian(fnc,ARcoefs))
g2B <- t(jacobian(fnc,ARcoefs,
method="simple",method.args=list(eps=1e-3))
all.equal(g1,g2A) ## as before
## [1] "Mean relative difference: 0.000467239"
all.equal(g1,g2B)
## [1] TRUE
all.equal(g2B,g3)
## [1] "Mean relative difference: 0.000467239"
all.equal(g2A,g3)
## [1] TRUE
接下来的问题是5e-4的相对差异对你的应用是否真正重要......