如何用AR(1)转换方程估计卡尔曼滤波器?

sqougxex  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(90)

我使用R中的KFAS包来估计卡尔曼滤波器的状态空间模型。我的测量和跃迁方程是:
y_t = Z_t * x_t + \eps_t(测量)
x_t = T_t * x_{t-1} + R_t * \eta_t(跃迁),
其中\eps_t ~ N(0,H_t)和\eta_t ~ N(0,Q_t)。
所以,我想估计方差H_t和Q_t,还有T_t,AR(1)系数。代码如下:

library(KFAS)

set.seed(100)

eps <- rt(200, 4, 1)
meas <- as.matrix((arima.sim(n=200, list(ar=0.6), innov = rnorm(200)*sqrt(0.5)) + eps), 
ncol=1)

Zt <- 1
Ht <- matrix(NA)
Tt <- matrix(NA)
Rt <- 1
Qt <- matrix(NA)

ss_model <- SSModel(meas ~ -1 + SSMcustom(Z = Zt, T = Tt, R = Rt, 
                                             Q = Qt), H = Ht)
fit <- fitSSM(ss_model, inits = c(0,0.6,0), method = 'L-BFGS-B')

但它返回:* “在is.SSModel(do.call(updatefn,args = c(list(inits,model),update_args))中出错,:系统矩阵(不包括Z)包含NA或无穷大值,协方差矩阵包含大于1 e +07”* 的值
正如包的文件中所记录的那样,方差的NA定义工作得很好。然而,这似乎不能对AR系数进行。有人知道我该怎么做吗?
注意,我知道SSMarima函数,它简化了ARIMA模型的转换方程的定义。虽然我可以估计AR(1)系数。和Q_t,我仍然无法估计\eps_t方差(H_t)。此外,我正在将我的卡尔曼滤波器代码从EViews迁移到R,所以我需要学习SSMcustom用于其他更复杂的模型。
谢谢你,谢谢

i7uaboj4

i7uaboj41#

看起来你在例子中遗漏了一些东西,因为你的错误消息来自函数fitSSM。如果你想使用fitSSM来估计一般的状态空间模型,你需要提供自己的模型更新函数。默认行为只能处理协方差矩阵H和Q中的NA。fitSSM的主要目标是从简单的东西开始。对于复杂的模型和/或大数据,我建议您使用自己编写的目标函数(在logLik方法的帮助下)和您最喜欢的数值优化例程手动获得最佳性能。大概是这样的:

library(KFAS)

set.seed(100)

eps <- rt(200, 4, 1)
meas <- as.matrix((arima.sim(n=200, list(ar=0.6), innov = rnorm(200)*sqrt(0.5)) + eps), 
ncol=1)

Zt <- 1
Ht <- matrix(NA)
Tt <- matrix(NA)
Rt <- 1
Qt <- matrix(NA)

ss_model <- SSModel(meas ~ -1 + SSMcustom(Z = Zt, T = Tt, R = Rt, 
                                             Q = Qt), H = Ht)

objf <- function(pars, model, estimate = TRUE) {
  model$H[1] <- pars[1]
  model$T[1] <- pars[2]
  model$Q[1] <- pars[3]
  if (estimate) {
  -logLik(model)
  } else {
    model
  }
}

opt <- optim(c(1, 0.5, 1), objf, method = "L-BFGS-B", 
  lower = c(0, -0.99, 0), upper = c(100, 0.99, 100), model = ss_model)

ss_model_opt <- objf(opt$par, ss_model, estimate = FALSE)

fitSSM

updatefn <- function(pars, model) {
  model$H[1] <- pars[1]
  model$T[1] <- pars[2]
  model$Q[1] <- pars[3]
  model
}

fit <- fitSSM(ss_model, c(1, 0.5, 1), updatefn, method = "L-BFGS-B", 
  lower = c(0, -0.99, 0), upper = c(100, 0.99, 100))

identical(ss_model_opt, fit$model)

相关问题