ts1101
1 Exponential smoothing & Kalman filter
- Time Update (“Predict”)
\[\hat{x}_k^- ~=~ \hat{x}_{k-1}\]
\[P_k^- ~=~ P_{k-1}+Q\]
- Measurement Update (“Correct”)
\[K_{k_{~~2×1}}=P_k^- \mathbf{}\left[\begin{array}{rrr} 1 ~\\ Z_t \end{array}\right] \mathbf{}\left[\begin{array}{rrr} \mathbf{}\left[\begin{array}{rrr} 1 & Z_t\end{array}\right] ~P_k^- ~ \mathbf{}\left[\begin{array}{rrr} 1 ~\\ Z_t \end{array}\right]_{2×1} +R \end{array}\right]^{-1}\]
\[\hat{x}_k ~=~ \hat{x}_k^-+K_k(x_k-\mathbf{}\left[\begin{array}{rrr} 1 & Z_t \end{array}\right]\hat{x}_k^-)\]
\[P_k ~=~ (I_{2×2} - K_k \mathbf{}\left[\begin{array}{rrr} 1 & Z_t \end{array}\right] )P_k^-\]
- Exponential smoonthing
\[y_t = \mathbf{}\left[\begin{array}{rrr} 1 & Z_t \end{array}\right] \hat{x}_k +R\]
library(tidyverse)
library(lubridate)
library(foreach)
library(forecast)
y = read.csv("/home/yuan/Desktop/meeting/處理後來店人數資料.csv")$x
date1 = foreach(i = 0:363, .combine = "c") %do% {
(ymd_h("2007-01-01-12") + hours(0:6) + days(i))
}
data1 = data.frame(data = y, date = date1, week = weekdays(date1), zt = 0, stringsAsFactors = F)
data1$zt[which(data1$week == "Saturday")] = 1
data1$zt[which(data1$week == "Sunday")] = 1KF <- function(alpha = 0.5, R = 0.5, lt = 1, pt = 1, P = matrix(c(1, 0, 0, 1),
nrow = 2, ncol = 2)) {
# xhat & P 要起始值, alpha & R 自設
# lt & pt state value
# zt regressor (0,1) 1*2548
# xk true data 1*2548
alpha = alpha
R = R
A = matrix(c(1, 0, 0, 1), nrow = 2, ncol = 2)
I = matrix(c(1, 0, 0, 1), nrow = 2, ncol = 2)
Q = matrix(c(alpha^2 * R, 0, 0, 0), nrow = 2, ncol = 2)
lt = lt
pt = pt
# zt regressor 1*2548
zt = matrix(data1$zt, nrow = 1, ncol = 2548)
# xk true value 1*2548
xk = matrix(data1$data, nrow = 1, ncol = 2548)
xhat_update = list()
P_update = list()
P = P
xhat = matrix(c(lt, pt), nrow = 2, ncol = 1)
for (i in 1:2548) {
# time update
xhat_minus = A %*% xhat
Pminus = A %*% P %*% t(A) + Q
H = matrix(c(1, zt[1, i]), nrow = 1, ncol = 2) # H 1*2 matrix
# measurement update
K = Pminus %*% t(H) %*% (H %*% Pminus %*% t(H) + R)^(-1)
xhat = xhat_minus + K %*% (xk[i] - H %*% xhat_minus)
P = (matrix(c(1, 0, 0, 1), nrow = 2, ncol = 2) - K %*% H) %*% Pminus
xhat_update[[i]] = xhat
# P_update[[i]] = P
}
return(xhat_update)
}1.1 R = 0.01, pt = 1, lt = 1, alpha = 0.5
a = KF(R = 0.01, pt = 1, lt = 1, alpha = 0.5)
test1 = unlist(sapply(a, "[[", 1)) + data1$zt * unlist(sapply(a, "[[", 2)) +
0.01
accuracy(test1, data1$data) ME RMSE MAE MPE MAPE
Test set 0.2822206 27.18353 18.88427 -9.999182 23.37479
1.2 R = 0.01, pt = 1, lt = 1, alpha = 0.9
a = KF(R = 0.01, pt = 1, lt = 1, alpha = 0.9)
test1 = unlist(sapply(a, "[[", 1)) + data1$zt * unlist(sapply(a, "[[", 2)) +
0.01
accuracy(test1, data1$data) ME RMSE MAE MPE MAPE
Test set 0.1443447 18.56933 12.66392 -6.616363 16.03923
matplot(data1$data, type = "l")
matplot(test1, type = "l", add = T, col = 2) RMSE MAE MAPE
Holt.Winter 32.18209 21.82968 19.20088
double.seasonal.HW 23.43904 16.81247 16.16967
kalman_filter 18.56933 12.66392 16.03923
2 Kalman Filter
- Time Update (“Predict”)
\[\hat{x}_k^- ~=~ \hat{x}_{k-1}\]
\[P_k^- ~=~ P_{k-1}+Q\]
- Measurement Update (“Correct”)
\[K_k ~=~ \frac{P_k^-}{P_k^-+R}\]
\[\hat{x}_k ~=~ \hat{x}_k^-+K_k(Z_k-\hat{x}_k^-)\]
\[P_k ~=~ (1-K_k)P_k^-\]
kalman_filter = function(n_iter = 100, R = 0.01, means = -0.37727, sd = 0.1) {
n_iter = n_iter
x = means # truth value
z = rnorm(x, sd, n = n_iter) # observations
Q = 1e-05 # process variance
xhat = c(rep(0, n_iter)) # a posteri estimate of x
P = c(rep(0, n_iter)) # a posteri error estimate
xhatminus = c(rep(0, n_iter)) # a priori estimate of x
Pminus = c(rep(0, n_iter)) # a priori error estimate
K = c(rep(0, n_iter)) # Kalman gain
R = R # estimate of measurement variance
# intial
xhat[1] = 0
P[1] = 1
for (k in 2:n_iter) {
# time update
xhatminus[k] = xhat[k - 1]
Pminus[k] = P[k - 1] + Q
# measurement update
K[k] = Pminus[k]/(Pminus[k] + R)
xhat[k] = xhatminus[k] + K[k] * (z[k] - xhatminus[k])
P[k] = (1 - K[k]) * Pminus[k]
}
matplot(z, ylim = c(means - 3 * sd, means + 3 * sd), pch = 3)
abline(a = means, b = 0, col = 2)
matplot(xhat, type = "l", add = T)
}
kalman_filter(n_iter = 50, R = 1e-04, means = -0.37727, sd = 0.1)