KFAS
##
## KFASによる状態空間モデル
##
library(KFAS)
library(ggplot2)
library(gridExtra)
font <- "IPAexGothic" # フォントは適宜指定してください
options(digits = 3)
# (1) KFASによる季節調整モデル
# 松浦(2016)のデータを使用
data.file <- "data-season.txt"
if (file.exists(data.file)) {
data <- read.csv(data.file)
} else {
data.url <- "https://raw.githubusercontent.com/iwanami-datascience/vol1/master/matsuura/example2/input/data-season.txt"
data <- read.csv(url(data.url))
}
Y <- data$Y
kfas.mod1 <- SSModel(Y ~ SSMtrend(degree = 1, Q = NA,
a1 = 20) +
SSMseasonal(period = 4,
sea.type = "dummy",
Q = NA), H = NA)
# 係数行列
kfas.mod1$Z
kfas.mod1$T
# パラメータを最尤推定
kfas.fit1 <- fitSSM(kfas.mod1, inits = rep(0, 3))
# 観測ノイズの分散
kfas.fit1$model$H
# システムノイズの分散
kfas.fit1$model$Q
# 尤度
logLik(kfas.fit1$model)
# カルマンフィルタを適用
kfas.fil1 <- KFS(kfas.fit1$model, filtering = "state",
smoothing = c("state"))
# 状態の1期先予測
head(kfas.fil1$a, 3)
# 平滑化した状態の値
head(kfas.fil1$alphahat, 3)
# 予測
kfas.fct1 <- predict(kfas.fit1$model, n.ahead = 8,
interval = "prediction", level = 0.95,
type = "response", nsim = 1000)
obs.exp <- kfas.fct1[, 1]
lower <- kfas.fct1[, 2]
upper <- kfas.fct1[, 3]
# グラフ
df1 <- data.frame(Time = c(rep(seq_along(Y), 2),
length(Y) + seq_along(obs.exp)),
Value = c(Y, kfas.fil1$alphahat[, 1], obs.exp),
Lower = c(rep(NA, length(Y) * 2), lower),
Upper = c(rep(NA, length(Y) * 2), upper),
Type = factor(c(rep("観測値", length(Y)),
rep("平滑化した値", length(Y)),
rep("予測値", length(obs.exp))),
levels = c("観測値", "平滑化した値",
"予測値")))
p1 <- ggplot(df1) +
geom_line(aes(x = Time, y = Value, color = Type, alpha = Type)) +
scale_color_manual(values = c("black", "gray10", "gray60")) +
scale_size_manual(values = c(0.5, 1.5, 1.5)) +
scale_alpha_manual(values = c(1, 0.6, 0.6)) +
geom_ribbon(aes(x = Time, ymin = Lower, ymax = Upper),
fill = "gray50", alpha = 0.5) +
labs(title = "A", x = "時間(四半期)", y = "販売個数(千個)") +
theme_classic(base_family = font) +
theme(legend.title = element_blank(),
legend.justification = c(0, 1),
legend.position = c(0.1, 1))
print(p1)
# AR(3)モデル
mod.ar <- SSModel(Y ~ 0 +
SSMarima(ar = rep(0, 3), Q = NA),
H = 0)
update.ar <- function(pars, mod) {
a <- artransform(pars[1:3])
sigma2 <- exp(pars[4])
mod <- SSModel(Y ~ 0 +
SSMarima(ar = a, Q = sigma2),
H = 0)
return(mod)
}
fit.ar <- fitSSM(mod.ar, inits = rep(1, 4),
updatefn = update.ar,
method = "L-BFGS-B")
# 結果
print(fit.ar$model$T, digits = 3)
print(fit.ar$model$Q, digits = 3)
# (2) ポアソン分布のモデル
# 久保(2012)のデータを使用
# 1次元の空間データを時系列と見なして解析する
if (file.exists(data.file)) {
data.file <- "Y.RData"
load(data.file)
} else {
data.url <- "http://hosho.ees.hokudai.ac.jp/~kubo/stat/iwanamibook/fig/spatial/Y.RData"
load(url(data.url))
}
df2 <- data.frame(Time = seq_along(Y), Y = Y)
p2 <- ggplot(df2) +
geom_line(aes(x = Time, y = Y)) +
theme_classic(base_family = font)
print(p2)
# ローカルレベルモデル
kfas.mod2 <- SSModel(Y ~ SSMtrend(degree = 1, Q = NA),
distribution = "poisson")
kfas.fit2 <- fitSSM(kfas.mod2, inits = c(0),
method = "BFGS")
# ノイズ分散
kfas.fit2$model$Q
kfas.fit2$model$H
# 観測値の予測
kfas.fil2 <- KFS(kfas.fit2$model, smoothing = "mean")
fitted(kfas.fil2)
# 平滑化した値
kfas.pre2 <- predict(kfas.fil2$model, interval = "confidence",
level = 0.95, type = "response")
df2 <- data.frame(Time = rep(seq_along(Y), 2),
Y = c(Y, kfas.pre2[, "fit"]),
Type = factor(rep(c("観測値", "平滑化した値"),
each = length(Y)),
levels = c("観測値", "平滑化した値")))
df2.ci <- data.frame(Time = seq_along(Y),
Lower = kfas.pre2[, "lwr"],
Upper = kfas.pre2[, "upr"])
p2 <- ggplot(df2) +
geom_line(aes(x = Time, y = Y, color = Type,
size = Type, alpha = Type)) +
scale_color_manual(values = c("black", "gray20")) +
scale_size_manual(values = c(0.5, 1.5)) +
scale_alpha_manual(values = c(1, 0.6)) +
geom_ribbon(data = df2.ci,
aes(x = Time, ymin = Lower, ymax = Upper),
fill = "gray50", alpha = 0.5) +
labs(title = "A") +
theme_classic(base_family = font) +
theme(legend.title = element_blank(),
legend.text = element_text(size = 8),
legend.justification = c(1, 1),
legend.position = c(1, 1.07),
legend.background = element_rect(fill = "transparent"))
print(p2)
# 2階差分のモデル
kfas.mod2.2 <- SSModel(Y ~ SSMtrend(degree = 2,
Q = list(0, NA)),
distribution = "poisson")
kfas.fit2.2 <- fitSSM(kfas.mod2.2, inits = c(0),
method = "BFGS")
# システムノイズの分散
kfas.fit2.2$model$Q
# 観測値の予測
kfas.flt22 <- KFS(kfas.fit2.2$model, smoothing = "mean")
fitted(kfas.flt2.2)
kfas.pre22 <- predict(kfas.flt22$model, interval = "confidence",
level = 0.95, type = "response")
df22 <- data.frame(Time = rep(seq_along(Y), 2),
Y = c(Y, kfas.pre22[, "fit"]),
Type = factor(rep(c("観測値", "平滑化した値"),
each = length(Y)),
levels = c("観測値", "平滑化した値")))
df22.ci <- data.frame(Time = seq_along(Y),
Lower = kfas.pre22[, "lwr"],
Upper = kfas.pre22[, "upr"])
p22 <- ggplot(df22) +
geom_line(aes(x = Time, y = Y, color = Type, size = Type)) +
scale_color_manual(values = c("black", "gray50")) +
geom_ribbon(data = df22.ci,
aes(x = Time, ymin = Lower, ymax = Upper),
fill = "gray50", alpha = 0.5) +
scale_size_manual(values = c(0.5, 1)) +
theme_classic(base_family = font) +
theme(legend.title = element_blank())
print(p22)