Chapter 4 Stan Functions
State space functionality for Stan is provided as a set of user-defined functions.
Add the following line to the Stan model file in which depends on these functions.
functions {
#include ssm.stan
// other functions ...
}
To actually include the functions in the model, you need to use the function stanc_builder
, instead of stan
or stanc
:
model <- stanc_builder("yourmodel.stan", isystem = "path/to/ssm/")
stan(model_code = model$model_code)
4.1 Utility Functions
4.1.1 to_symmetric_matrix
Parameters:
x
An \(n \times n\) matrix.
Return Value: An
\(n \times n\) symmetric matrix: \(0.5 (x + x')\).
Ensure a matrix is symmetrix.
matrix to_symmetric_matrix(matrix x) {
return 0.5 * (x + x ');
}
4.1.2 to_matrix_colwise
Parameters:
vector
v An \(n \times m\) vector.int
m Number of rows in the vectorint
n Number of columns in the vector
Return Value: matrix
A \(m \times n\) matrix containting the elements from v
Convert vector to a matrix (column-major).
matrix to_matrix_colwise(vector v, int m, int n) {
matrix[m, n] res;
for (j in 1:n) {
for (i in 1:m) {
res[i, j] = v[(j - 1) * m + m];
}
}
return res;
}
4.1.3 to_matrix_rowwise
Parameters:
vector
v An \(n \times m\) vector.int
m Number of rows in the matrix.int
n Number of columns in the matrix.
Return Value: matrix
A \(m \times n\) matrix containting the elements from v
Convert vector to a matrix (row-major).
matrix to_matrix_rowwise(vector v, int m, int n) {
matrix[m, n] res;
for (i in 1:n) {
for (j in 1:m) {
res[i, j] = v[(i - 1) * n + n];
}
}
return res;
}
4.1.4 to_vector_colwise
Parameters:
matrix
x An \(n \times m\) matrix.
Return Value: vector
with \(n m\) elements.
Convert a matrix to a vector (column-major)
vector to_vector_colwise(matrix x) {
vector[num_elements(x)] res;
int n;
int m;
n = rows(x);
m = cols(x);
for (i in 1:n) {
for (j in 1:m) {
res[n * (j - 1) + i] = x[i, j];
}
}
return res;
}
4.1.5 to_vector_rowwise
Parameters:
matrix
x An \(n \times m\) matrix.
Return Value: vector
with \(n m\) elements.
Convert a matrix to a vector (row-major)
vector to_vector_rowwise(matrix x) {
vector[num_elements(x)] res;
int n;
int m;
n = rows(x);
m = cols(x);
for (i in 1:rows(x)) {
for (j in 1:cols(x)) {
res[(i - 1) * m + j] = x[i, j];
}
}
return res;
}
4.1.6 symmat_size
Parameters:
matrix
x An \(m \times m\) matrix.
Return Value: int
The number of unique elements
Calculate the number of unique elements in a symmetric matrix
The number of unique elements in an \(m \times m\) matrix is \((m \times (m + 1)) / 2\).
int symmat_size(int n) {
int sz;
// This calculates it iteratively because Stan gives a warning
// with integer division.
sz = 0;
for (i in 1:n) {
sz = sz + i;
}
return sz;
}
4.1.7 find_symmat_dim
Parameters:
int
n The number of unique elements in a symmetric matrix.
Return Value: int
The dimension of the associated symmetric matrix.
Given vector with \(n\) elements containing the \(m (m + 1) / 2\) elements of a symmetric matrix, return \(m\).
int find_symmat_dim(int n) {
// This could be solved by finding the positive root of $m = m (m + 1)/2 but
// Stan doesn't support all the functions necessary to do this.
int i;
int remainder;
i = 0;
while (n > 0) {
i = i + 1;
remainder = remainder - i;
}
return i;
}
4.1.8 vector_to_symmat
Parameters:
vector
x The vector with the unique elementsint
n The dimensions of the returned matrix: \(n \times n\).
Return Value: matrix
An \(n \times n\) symmetric matrix.
Convert a vector to a symmetric matrix
matrix vector_to_symmat(vector x, int n) {
matrix[n, n] m;
int k;
k = 1;
for (j in 1:n) {
for (i in 1:j) {
m[i, j] = x[k];
if (i != j) {
m[j, i] = m[i, j];
}
k = k + 1;
}
}
return m;
}
4.1.9 symmat_to_vector
Parameters:
vector
x An \(n \times n\) matrix.
Return Value: vector
A \(n (n + 1) / 2\) vector with the unique elements in \(x\).
Convert an \(n \times n\) symmetric matrix to a length \(n (n + 1) / 2\) vector containing its unique elements.
vector symmat_to_vector(matrix x) {
vector[symmat_size(rows(x))] v;
int k;
k = 1;
// if x is m x n symmetric, then this will return
// only parts of an m x m matrix.
for (j in 1:rows(x)) {
for (i in 1:j) {
v[k] = x[i, j];
k = k + 1;
}
}
return v;
}
4.2 Filtering
Functions used in filtering and log-likelihood calculations.
4.2.1 ssm_filter_update_a
Parameters:
vector
a An \(m \times 1\) vector with the prected state, \(\vec{a}_t\).vector
c An \(m \times 1\) vector with the system intercept, \(\vec{c}_t\)matrix
T An \(m \times m\) matrix with the transition matrix, \(\mat{T}_t\).vector
v A \(p \times 1\) vector with the forecast error, \(\vec{v}_t\).matrix
K An \(m \times p\) matrix with the Kalman gain, \(\mat{K}_t\).
Return Value: vector
A \(m \times 1\) vector with the predicted state at \(t + 1\), \(\vec{a}_{t + 1}\).
Update the expected value of the predicted state, \(\vec{a}_{t + 1} = \E(\vec{\alpha}_{t + 1} | \vec{y}_{1:t})\),
The predicted state \(\vec{a}_{t + 1}\) is, \[ \vec{a}_{t + 1} = \mat{T}_t \vec{a}_t + \mat{K}_t \vec{v}_t + \vec{c}_t . \]
vector ssm_filter_update_a(vector a, vector c, matrix T, vector v, matrix K) {
vector[num_elements(a)] a_new;
a_new = T * a + K * v + c;
return a_new;
}
4.2.2 ssm_filter_update_P
Parameters:
matrix
P An \(m \times m\) vector with the variance of the prected state, \(\mat{P}_t\).matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\).matrix
T An \(m \times m\) matrix with the transition matrix, \(\mat{T}_t\).matrix
RQR A \(m \times m\) matrix with the system covariance matrix, \(\mat{R}_t \mat{Q}_t \mat{R}_t'\).matrix
K An \(m \times p\) matrix with the Kalman gain, \(\mat{K}_t\).
Return Value: matrix
An \(m \times 1\) vector with the predicted state at \(t + 1\), \(\vec{a}_{t + 1}\).
Update the expected value of the predicted state, \(\mat{P}_{t + 1} = \Var(\alpha_{t + 1} | \vec{y}_{1:t})\),
The predicted state variance \(\mat{P}_{t + 1}\) is, \[ \mat{P}_{t + 1} = \mat{T}_t \mat{P}_t (\mat{T}_t - \mat{K}_t \mat{Z}_t)' + \mat{R}_t \mat{Q}_t \mat{R}_t' . \]
matrix ssm_filter_update_P(matrix P, matrix Z, matrix T,
matrix RQR, matrix K) {
matrix[rows(P), cols(P)] P_new;
P_new = to_symmetric_matrix(T * P * (T - K * Z)' + RQR);
return P_new;
}
4.2.3 ssm_filter_update_v
Parameters:
matrix
P An \(m \times m\) vector with the variance of the prected state, \(\mat{P}_t\).matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\).matrix
T An \(m \times m\) matrix with the transition matrix, \(\mat{T}_t\).matrix
RQR An \(m \times m\) matrix with the system covariance matrix, \(\mat{R}_t \mat{Q}_t \mat{R}_t'\).matrix
K An \(m \times p\) matrix with the Kalman gain, \(\mat{K}_t\).
Return Value: vector
An \(m \times 1\) vector with the predicted state at \(t + 1\), \(\vec{a}_{t + 1}\).
Update the forcast error, \(\vec{v}_t = \vec{y}_t - \E(\vec{y}_t | \vec{y_{1:(t - 1)}})\)
The forecast error \(\vec{v}_t\) is \[ \vec{v}_t =\vec{y}_t - \mat{Z}_t \vec{a}_t - \vec{d}_t . \]
vector ssm_filter_update_v(vector y, vector a, vector d, matrix Z) {
vector[num_elements(y)] v;
v = y - Z * a - d;
return v;
}
4.2.4 ssm_filter_update_F
Parameters:
matrix
P An \(m \times m\) vector with the variance of the prected state, \(\mat{P}_t\).matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\).matrix
H A \(p \times p\) matrix with the observation covariance matrix, \(\mat{H}_t\).
Return Value: matrix
A \(p \times p\) vector with \(\mat{F}_t\).
Update the variance of the forcast error, \(\mat{F}_t = \Var(\vec{y}_t - \E(\vec{y}_t | \vec{y_{1:(t - 1)}}))\)
The variance of the forecast error \(\mat{F}_t\) is \[ \mat{F}_t = \mat{Z}_t \mat{P}_t \mat{Z}_t + \mat{H}_t . \]
matrix ssm_filter_update_F(matrix P, matrix Z, matrix H) {
matrix[rows(H), cols(H)] F;
F = quad_form(P, Z') + H;
return F;
}
4.2.5 ssm_filter_update_Finv
Parameters:
matrix
P An \(m \times m\) vector with the variance of the prected state, \(\mat{P}_t\).matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\).matrix
H A \(p \times p\) matrix with the observation covariance matrix, \(\mat{H}_t\).
Return Value: matrix
A \(p \times p\) vector with \(\mat{F}^{-1}_t\).
Update the precision of the forcast error, \(\mat{F}^{-1}_t = \Var(\vec{y}_t - \E(\vec{y}_t | \vec{y_{1:(t - 1)}}))^{-1}\)
This is the inverse of \(\mat{F}_t\).
matrix ssm_filter_update_Finv(matrix P, matrix Z, matrix H) {
matrix[rows(H), cols(H)] Finv;
Finv = inverse(ssm_filter_update_F(P, Z, H));
return Finv;
}
4.2.6 ssm_filter_update_K
Parameters:
matrix
P An \(m \times m\) vector with the variance of the prected state, \(P_t\).matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\).matrix
T An \(m \times m\) matrix with the transition matrix, \(\mat{T}_t\).matrix
Finv A \(p \times p\) matrix
Return Value: matrix
An \(m \times p\) matrix with the Kalman gain, \(\mat{K}_t\).
Update the Kalman gain, \(\mat{K}_t\).
The Kalman gain is \[ \mat{K}_t = \mat{T}_t \mat{P}_t \mat{Z}_t' \mat{F}^{-1}_t . \]
matrix ssm_filter_update_K(matrix P, matrix Z, matrix T, matrix Finv) {
matrix[cols(Z), rows(Z)] K;
K = T * P * Z' * Finv;
return K;
}
4.2.7 ssm_filter_update_L
Parameters:
matrix
Z A \(p \times m\) matrix with the design matrix, \(\mat{Z}_t\)matrix
T An \(m \times m\) matrix with the transition matrix, \(\mat{T}_t\).matrix
K An \(m \times p\) matrix with the Kalman gain, \(\mat{K}_t\).
Return Value: matrix
An \(m \times m\) matrix, \(\mat{L}_t\).
Update \(L_t\)
\[ \mat{L}_t = \mat{T}_t - \mat{K}_t \mat{Z}_t . \]
matrix ssm_filter_update_L(matrix Z, matrix T, matrix K) {
matrix[rows(T), cols(T)] L;
L = T - K * Z;
return L;
}
4.2.8 ssm_filter_update_ll
Parameters:
vector
v A \(p \times 1\) matrix with the forecast error, \(\vec{v}_t\).matrix
Finv A \(p \times p\) matrix with variance of the forecast error, \(\mat{F}^{-1}_t\).
Return Value: real
An \(m \times m\) matrix, \(L_t\).
Calculate the log-likelihood for a period
The log-likehood of a single observation in a state-space model is \[ \ell_t = - \frac{1}{2} p \log(2 \pi) - \frac{1}{2} \left(\log|\mat{F}_t| + \vec{v}_t' \mat{F}^{-1}_t \vec{v}_t \right) \]
real ssm_filter_update_ll(vector v, matrix Finv) {
real ll;
int p;
p = num_elements(v);
// det(A^{-1}) = 1 / det(A) -> log det(A^{-1}) = - log det(A)
ll = (- 0.5 *
(p * log(2 * pi())
- log_determinant(Finv)
+ quad_form(Finv, v)
));
return ll;
}
4.3 Filtering
4.3.1 ssm_filter_idx
Parameters:
int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: int[,]
A \(6 \times 3\) integer array containing the indexes of the return values of the Kalman filter.
Indexes of the return values of the Kalman filter functions: ssm_filter
.
ssm_filter_idx
returns a \(6 \times 3\) integer array with the (length, start index, stop index) of (\(\ell_t\), \(\vec{v}\), \(\vec{F}^-1\), \(\mat{K}\), \(\vec{a}\), \(\mat{P}\)).
value | length | start | stop |
---|---|---|---|
\(\ell_t\) | \(1\) | \(1\) | \(1\) |
\(\vec{v}\) | \(p\) | \(2\) | \(1 + p\) |
\(\mat{F}^{-1}\) | \(p (p + 1) / 2\) | \(2 + p\) | \(1 + p + p (p + 1) / 2\) |
\(\mat{K}\) | \(mp\) | \(2 + p + p (p + 1) / 2\) | \(1 + p + p (p + 1) / 2 + mp\) |
\(\vec{a}_t\) | \(m\) | \(2 + p + p (p + 1) / 2 + mp\) | \(1 + p + p (p + 1) / 2 + mp + m\) |
\(\mat{P}^t\) | \(m (m + 1) / 2\) | \(2 + p + p (p + 1) / 2 + mp + m\) | \(1 + p + p (p + 1) / 2 + mp + m (m + 1) / 2\) |
int[,] ssm_filter_idx(int m, int p) {
int sz[6, 3];
// loglike
sz[1, 1] = 1;
// v
sz[2, 1] = p;
// Finv
sz[3, 1] = symmat_size(p);
// K
sz[4, 1] = m * p;
// a
sz[5, 1] = m;
// P
sz[6, 1] = symmat_size(m);
// Fill in start and stop points
sz[1, 2] = 1;
sz[1, 3] = sz[1, 2] + sz[1, 1] - 1;
for (i in 2:6) {
sz[i, 2] = sz[i - 1, 3] + 1;
sz[i, 3] = sz[i, 2] + sz[i, 1] - 1;
}
return sz;
}
4.3.2 ssm_filter_size
Parameters:
int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: int
The number of elements in the vector.
Number of elements in vector containing filter results
int ssm_filter_size(int m, int p) {
int sz;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
sz = idx[6, 3];
return sz;
}
4.3.3 ssm_filter_get_loglik
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: real
The log-likelihood \(\ell_t\)
Get the log-likehood from the results of ssm_filter
.
real ssm_filter_get_loglik(vector x, int m, int p) {
real y;
y = x[1];
return y;
}
4.3.4 ssm_filter_get_v
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: vector
A \(p \times 1\) vector with the forecast error, \(\vec{v}_t\).
Get the forecast error from the results of ssm_filter
.
vector ssm_filter_get_v(vector x, int m, int p) {
vector[p] y;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
y = segment(x, idx[2, 2], idx[2, 3]);
return y;
}
4.3.5 ssm_filter_get_Finv
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: matrix
A \(p \times p\) matrix with the forecast precision, \(\mat{F}^{-1}_t\).
Get the forecast precision from the results of ssm_filter
.
matrix ssm_filter_get_Finv(vector x, int m, int p) {
matrix[p, p] y;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
y = vector_to_symmat(segment(x, idx[3, 2], idx[3, 3]), p);
return y;
}
4.3.6 ssm_filter_get_K
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: matrix
A \(m \times p\) matrix with the Kalman gain, \(\mat{F}^{-1}_t\).
Get the Kalman gain from the results of ssm_filter
.
matrix ssm_filter_get_K(vector x, int m, int p) {
matrix[m, p] y;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
y = to_matrix_colwise(segment(x, idx[4, 2], idx[4, 3]), m, p);
return y;
}
4.3.7 ssm_filter_get_a
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: vector
An \(m \times 1\) vector with the expected value of the predicted state, \(\E(\vec{\alpha}_t | \vec{y}_{1:(t-1)}) = \vec{a}_t\).
Get the expected value of the predicted state from the results of ssm_filter
.
vector ssm_filter_get_a(vector x, int m, int p) {
vector[m] y;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
y = segment(x, idx[5, 2], idx[5, 3]);
return y;
}
4.3.8 ssm_filter_get_P
Parameters:
vector
A vector with results fromssm_filter
.int
m The number of statesint
p The size of the observation vector \(\vec{y}_t\).
Return Value: matrix
An \(m \times m\) matrix with the variance of the predicted state, \(\Var(\vec{\alpha}_t | \vec{y}_{1:(t-1)}) = \mat{P}_t\).
Get the variance of the predicted state from the results of ssm_filter
.
matrix ssm_filter_get_P(vector x, int m, int p) {
matrix[m, m] y;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
y = vector_to_symmat(segment(x, idx[6, 2], idx[6, 3]), m);
return y;
}
4.3.9 ssm_filter
Parameters:
vector[]
y Observations, \(\vec{y}_t\). An array of size \(n\) of \(p \times 1\) vectors.vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: vector[]
Array of size \(n\) of \((1 + p + p (p + 1) / 2 + mp + m + m (m + 1) / 2) \times 1\) vectors in the format described in ssm_filter_idx
.
Kalman filter
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
ssm_filter
runs a forward filter on the state space model and calculates,
- log-likelihood for each observation, \(\ell_t\).
- Forecast error, \(\vec{v}_t = \vec{y}_t - \E(\vec{y}_t | \vec{y}_{1:(t -1)})\).
- Forecast precision, \(\mat{F}^{-1}_t\).
- Kalman gain, \(\mat{K}_t\).
- Predicted states, \(\vec{a}_t = \E(\vec{\alpha}_t | \vec{y}_{1:(t -1)})\).
- Variance of the predicted states, \(\mat{P}_t = \Var(\vec{\alpha}_t | \vec{y}_{1:(t -1)})\).
The results of Kalman filter for a given are returned as a \(1 + p + p (p + 1) / 2 + m p + m (m + 1) / 2\) vector for each time period, where \[ (\ell_t, \vec{v}_t', \VEC(\mat{F}^{-1}_t)', \VEC(\mat{K}_t)', \vec{a}_t', \VEC(\mat{P}_t)' )'. \]
vector[] ssm_filter(vector[] y,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
// returned data
vector[ssm_filter_size(dims(Z)[3], dims(Z)[2])] res[size(y)];
int q;
int n;
int p;
int m;
// sizes
n = size(y); // number of obs
p = dims(Z)[2]; // obs size
m = dims(Z)[3]; // number of states
q = dims(Q)[2]; // number of state disturbances
//print("Sizes: n = ", m, ", p = ", n, ", m = ", m, ", q = ", q);
{
// system matrices for current iteration
vector[p] d_t;
matrix[p, m] Z_t;
matrix[p, p] H_t;
vector[m] c_t;
matrix[m, m] T_t;
matrix[m, q] R_t;
matrix[q, q] Q_t;
matrix[m, m] RQR;
// result matricees for each iteration
vector[m] a;
matrix[m, m] P;
vector[p] v;
matrix[p, p] Finv;
matrix[m, p] K;
real ll;
int idx[6, 3];
idx = ssm_filter_idx(m, p);
d_t = d[1];
Z_t = Z[1];
H_t = H[1];
c_t = c[1];
T_t = T[1];
R_t = R[1];
Q_t = Q[1];
RQR = quad_form(Q_t, R_t);
a = a1;
P = P1;
for (t in 1:n) {
if (t > 1) {
if (size(d) > 1) {
d_t = d[t];
}
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(H) > 1) {
H_t = H[t];
}
if (size(c) > 1) {
c_t = c[t];
}
if (size(T) > 1) {
T_t = T[t];
}
if (size(R) > 1) {
R_t = R[t];
}
if (size(Q) > 1) {
Q_t = Q[t];
}
if (size(R) > 1 && size(Q) > 1) {
RQR = quad_form(Q_t, R_t);
}
}
// updating
v = ssm_filter_update_v(y[t], a, d_t, Z_t);
Finv = ssm_filter_update_Finv(P, Z_t, H_t);
K = ssm_filter_update_K(P, T_t, Z_t, Finv);
ll = ssm_filter_update_ll(v, Finv);
// saving
res[t, 1] = ll;
res[t, idx[2, 2]:idx[2, 3]] = v;
res[t, idx[3, 2]:idx[3, 3]] = symmat_to_vector(Finv);
res[t, idx[4, 2]:idx[4, 3]] = to_vector(K);
res[t, idx[5, 2]:idx[5, 3]] = a;
res[t, idx[6, 2]:idx[6, 3]] = symmat_to_vector(P);
// predict a_{t + 1}, P_{t + 1}
if (t < n) {
a = ssm_filter_update_a(a, c_t, T_t, v, K);
P = ssm_filter_update_P(P, Z_t, T_t, RQR, K);
}
}
}
return res;
}
4.3.10 ssm_filter_states
Parameters:
int
m Number of states
Return Value: int
The size of the vector
Length of the vectors returned by ssm_filter_states
int ssm_filter_states_size(int m) {
int sz;
sz = m + symmat_size(m);
return sz;
}
4.3.11 ssm_filter_states_get_a
Parameters:
vector
x A vector returned byssm_filter_states
int
m Number of states
Return Value: matrix
An \(m \times 1\) vector with the filtered expected value of the state, \(\vec{a}_{t|t} = \E(\vec{\alpha}_t | \vec{y}_{1:t})\).
Extract \(a_{t|t}\) from the results of ssm_filter_states
vector ssm_filter_states_get_a(vector x, int m) {
vector[m] a;
a = x[ :m];
return a;
}
4.3.12 ssm_filter_states_get_P
Parameters:
vector
x A vector returned byssm_filter_states
int
m Number of states
Return Value: matrix
An \(m \times m\) matrix with the filtered variance of the state, \(\mat{P}_{t|t} = \Var(\vec{\alpha}_t | \vec{y}_{1:t})\).
Extract \(P_{t|t}\) from the results of ssm_filter_states
matrix ssm_filter_states_get_P(vector x, int m) {
matrix[m, m] P;
P = vector_to_symmat(x[(m + 1): ], m);
return P;
}
4.3.13 ssm_filter_states
Parameters:
vector[]
filter Results fromssm_filter
matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.
Return Value: Array
of size \(n\) of vectors.
Calculate filtered expected values and variances of the states
The filtering function ssm_filter
returns the mean and variance of the predicted states, \(\vec{a}_t = \E(\vec{\alpha}_t | \vec{y}_{1:(t -1)})\) and \(\mat{P}_t = \Var(\vec{\alpha}_t | \vec{y}_{1:(t -1)})\).
The vectors returned by ssm_filter_states
are of length \(m + m ^ 2\), with \[
\vec{v}_t = (\vec{a}_{t|t}', \VEC(\vec{P}_{t|t})' )'
\] Use the functions ssm_filter_states_get_a
and ssm_filter_states_get_P
to extract elements from the results.
For Z
the array can have a size of 1, if it is not time-varying, or a size of \(n - 1\) if it is time varying.
vector[] ssm_filter_states(vector[] filter, matrix[] Z) {
vector[ssm_filter_states_size(dims(Z)[3])] res[size(filter)];
int n;
int m;
int p;
n = size(filter);
m = dims(Z)[3];
p = dims(Z)[2];
{
// system matrices for current iteration
matrix[p, m] Z_t;
// filter matrices
vector[m] aa; // filtered values of the state, a_{t|t}
matrix[m, m] PP; // filtered values of the variance of the state, P_{t|t}
vector[p] v;
matrix[p, p] Finv;
vector[m] a;
matrix[m, m] P;
Z_t = Z[1];
for (t in 1:n) {
if (t > 1) {
if (size(Z) > 1) {
Z_t = Z[t];
}
}
// extract values from the filter
v = ssm_filter_get_v(filter[t], m, p);
Finv = ssm_filter_get_Finv(filter[t], m, p);
a = ssm_filter_get_a(filter[t], m, p);
P = ssm_filter_get_P(filter[t], m, p);
// calcualte filtered values
aa = a + P * Z_t ' * Finv * v;
PP = to_symmetric_matrix(P - P * quad_form(Finv, Z_t) * P);
// saving
res[t, :m] = aa;
res[t, (m + 1): ] = symmat_to_vector(PP);
}
}
return res;
}
4.4 Log-likelihood
4.4.1 ssm_lpdf
Parameters:
vector[]
y Observations, \(\vec{y}_t\). An array of size \(n\) of \(p \times 1\) vectors.vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: real
The log-likelihood, \(p(\vec{y}_{1:n} | \vec{d}, \mat{Z}, \mat{H}, \vec{c}, \mat{T}, \mat{R}, \mat{Q})\), marginalized over the latent states.
Log-likelihood of a Linear Gaussian State Space Model
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
The log-likelihood of a linear Gaussian state space model is, If the the system matrices and initial conditions are known, the log likelihood is \[ \begin{aligned}[t] \log L(\mat{Y}_n) &= \log p(\vec{y}_1, \dots, \vec{y}_n) = \sum_{t = 1}^n \log p(\vec{y}_t | \mat{Y}_{t - 1}) \\ &= - \frac{np}{2} \log 2 \pi - \frac{1}{2} \sum_{t = 1}^n \left( \log \left| \mat{F}_t \right| + \vec{v}\T \mat{F}_t^{-1} \vec{v}_t \right) \end{aligned} , \] where \(\mat{F}_t\) and \(\mat{V}_t\) come from a forward pass of the Kalman filter.
real ssm_lpdf(vector[] y,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
real ll;
int n;
int m;
int p;
int q;
n = size(y); // number of obs
m = dims(Z)[2];
p = dims(Z)[3];
q = dims(Q)[2];
{
// system matrices for current iteration
vector[p] d_t;
matrix[p, m] Z_t;
matrix[p, p] H_t;
vector[m] c_t;
matrix[m, m] T_t;
matrix[m, q] R_t;
matrix[q, q] Q_t;
matrix[m, m] RQR;
// result matricees for each iteration
vector[n] ll_obs;
vector[m] a;
matrix[m, m] P;
vector[p] v;
matrix[p, p] Finv;
matrix[m, p] K;
d_t = d[1];
Z_t = Z[1];
H_t = H[1];
c_t = c[1];
T_t = T[1];
R_t = R[1];
Q_t = Q[1];
RQR = quad_form(Q_t, R_t);
a = a1;
P = P1;
for (t in 1:n) {
if (t > 1) {
if (size(d) > 1) {
d_t = d[t];
}
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(H) > 1) {
H_t = H[t];
}
if (size(c) > 1) {
c_t = c[t];
}
if (size(T) > 1) {
T_t = T[t];
}
if (size(R) > 1) {
R_t = R[t];
}
if (size(Q) > 1) {
Q_t = Q[t];
}
if (size(R) > 1 && size(Q) > 1) {
RQR = quad_form(Q_t, R_t);
}
}
v = ssm_filter_update_v(y[t], a, d_t, Z_t);
Finv = ssm_filter_update_Finv(P, Z_t, H_t);
K = ssm_filter_update_K(P, Z_t, T_t, Finv);
ll_obs[t] = ssm_filter_update_ll(v, Finv);
// don't save a, P for last iteration
if (t < n) {
a = ssm_filter_update_a(a, c_t, T_t, v, K);
P = ssm_filter_update_P(P, Z_t, T_t, RQR, K);
}
}
ll = sum(ll_obs);
}
return ll;
}
4.5 Time-Invariant Kalman Filter
4.5.1 ssm_check_matrix_equal
Parameters:
matrix
A An \(m \times n\) matrix.matrix
B An \(m \times n\) matrix.real
The relative tolerance for convergence.
Return Value: int
If converged, then 1, else 0.
Check if two matrices are approximately equal
The matrices \(A\) and \(B\) are considered approximately equal if \[ \max(A - B) / \max(A) < \epsilon, \] where \(\epsilon\) is the tolerance.
int ssm_check_matrix_equal(matrix A, matrix B, real tol) {
real eps;
eps = max(to_vector(A - B)) / max(to_vector(A));
if (eps < tol) {
return 1;
} else {
return 0;
}
}
4.5.2 ssm_constant_lpdf
Parameters:
vector[]
y Observations, \(\vec{y}_t\). An array of size \(n\) of \(p \times 1\) vectors.vector
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: real
The log-likelihood, \(p(\vec{y}_{1:n} | \vec{d}, \mat{Z}, \mat{H}, \vec{c}, \mat{T}, \mat{R}, \mat{Q})\), marginalized over the latent states.
Log-likelihood of a Time-Invariant Linear Gaussian State Space Model
Unlike ssm_filter
, this function requires the system matrices (d
, Z
, H
, c
, T
, R
, Q
) to all be time invariant (constant). When the state space model is time-invariant, then the Kalman recursion for \(\mat{P}_t\) converges. This function takes advantage of this feature and stops updating \(\mat{P}_t\) after it converges to a steady state.
real ssm_constant_lpdf(vector[] y,
vector d, matrix Z, matrix H,
vector c, matrix T, matrix R, matrix Q,
vector a1, matrix P1) {
real ll;
int n;
int m;
int p;
n = size(y); // number of obs
m = cols(Z);
p = rows(Z);
{
vector[n] ll_obs;
vector[m] a;
matrix[m, m] P;
vector[p] v;
matrix[p, p] Finv;
matrix[m, p] K;
matrix[m, m] RQR;
// indicator for if the filter has converged
// This only works for time-invariant state space models
int converged;
matrix[m, m] P_old;
real tol;
converged = 0;
tol = 1e-7;
RQR = quad_form(Q, R);
a = a1;
P = P1;
for (t in 1:n) {
v = ssm_filter_update_v(y[t], a, d, Z);
if (converged < 1) {
Finv = ssm_filter_update_Finv(P, Z, H);
K = ssm_filter_update_K(P, Z, T, Finv);
}
ll_obs[t] = ssm_filter_update_ll(v, Finv);
// don't save a, P for last iteration
if (t < n) {
a = ssm_filter_update_a(a, c, T, v, K);
// check for convergence
// should only check for convergence if there are no missing values
if (converged < 1) {
P_old = P;
P = ssm_filter_update_P(P, Z, T, RQR, K);
converged = ssm_check_matrix_equal(P, P_old, tol);
}
}
}
ll = sum(ll_obs);
}
return ll;
}
4.6 Common Smoother Functions
4.6.1 ssm_smooth_update_r
Parameters:
vector
r An \(m \times 1\) vector with \(\vec{r}_{t-1}\)matrix
Z A \(p \times m\) vector with \(\mat{Z}_{t}\)vector
v A \(p \times 1\) vector of the forecast errors, \(\vec{v}_t\).matrix
Finv A \(p \times p\) matrix of the forecast precision, \(\mat{F}^{-1}_t\).matrix
L An \(m \times m\) matrix with \(\mat{L}_t\).
Return Value: matrix
An \(m \times 1\) vector with \(\vec{r}_t\).
Update \(\vec{r}_t\) in smoothing recursions
In smoothing recursions, the vector \(\vec{r}_t\) is updated with, \[ \vec{r}_{t - 1} = \mat{Z}' \mat{F}^{-1}_t \vec{v}_t + \mat{L}' \vec{r}_{t} . \]
See (Durbin and Koopman 2012, 91)
vector ssm_smooth_update_r(vector r, matrix Z, vector v, matrix Finv,
matrix L) {
vector[num_elements(r)] r_new;
r_new = Z ' * Finv * v + L ' * r;
return r_new;
}
4.6.2 ssm_smooth_update_N
Parameters:
vector
N An \(m \times 1\) vector with \(\vec{N}_{t-1}\)matrix
Z A \(p \times m\) vector with \(\mat{Z}_{t}\)matrix
Finv A \(p \times p\) matrix of the forecast precision, \(\mat{F}^{-1}_t\).matrix
L An \(m \times m\) matrix with \(\mat{L}_t\).
Return Value: matrix
An \(m \times m\) matrix with \(\vec{N}_t\).
Update \(\mat{N}_t\) in smoothing recursions
In smoothing recursions, the matrix \(\vec{N}_t\) is updated with, \[ \mat{N}_{t - 1} = \mat{Z}_t' \mat{F}^{-1}_t \mat{Z}_t + \mat{L}_t' \mat{N}_t \mat{L}_t . \]
See (Durbin and Koopman 2012, 91)
matrix ssm_smooth_update_N(matrix N, matrix Z, matrix Finv, matrix L) {
matrix[rows(N), cols(N)] N_new;
N_new = quad_form(Finv, Z) + quad_form(N, L);
return N_new;
}
4.6.3 ssm_smooth_state_size
Parameters:
int
m The number of states.
Return Value: int
The size of the vectors is \(m + m (m + 1) / 2\).
The number of elements in vectors returned by ssm_smooth_state
int ssm_smooth_state_size(int m) {
int sz;
sz = m + symmat_size(m);
return sz;
}
4.6.4 ssm_smooth_state_get_mean
Parameters:
vector
x A vector returned byssm_smooth_state
int
q The number of state disturbances, \(\vec{\eta}_t\).
Return Value: vector
An \(m \times 1\) vector with \(\hat{\vec{\eta}}_t\).
Extract \(\hat{\vec{\alpha}}_t\) from vectors returned by ssm_smooth_state
vector ssm_smooth_state_get_mean(vector x, int m) {
vector[m] alpha;
alpha = x[ :m];
return alpha;
}
4.6.5 ssm_smooth_state_get_var
Parameters:
vector
x A vector returned byssm_smooth_state
int
m The number of states
Return Value: matrix
An \(m \times m\) matrix with \(\mat{V}_t\).
Extract \(mat{V}_t\) from vectors returned by ssm_smooth_state
matrix ssm_smooth_state_get_var(vector x, int m) {
matrix[m, m] V;
V = vector_to_symmat(x[(m + 1): ], m);
return V;
}
4.6.6 ssm_smooth_state
Parameters:
vector[]
filter Results ofssm_filter
matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.
Return Value: vector[]
An array of vectors constaining \(\hat{\vec{\alpha}}_t\) and \(\mat{V}_t = \Var(\vec{\alpha}_t | \vec{y}_{1:n})\).
The state smoother
This calculates the mean and variance of the states, \(\vec{\alpha}_t\), given the entire sequence, \(\vec{y}_{1:n}\).
in the format described below.
For Z
and T
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for Z
) or \(n - 1\) (for T
) if it is time varying.
The vectors returned by this function have \(m + m ^ 2\) elements in this format, \[
(\hat{\vec{\alpha}}_t', \VEC(\mat{V}_t)' )'.
\] Use the ssm_smooth_state_get_mean
and ssm_smooth_state_get_var
to extract components from the returned vectors.
value | length | start | end |
---|---|---|---|
\(\hat{\vec{\alpha}}_t\) | \(m\) | \(1\) | \(m\) |
\(\mat{V}_t\) | \(m (m + 1) / 2\) | \(m + 1\) | \(m + m (m + 1) / 2\) |
See Durbin and Koopman (2012), Eq 4.44 and eq 4.69.
vector[] ssm_smooth_state(vector[] filter, matrix[] Z, matrix[] T) {
vector[ssm_smooth_state_size(dims(Z)[3])] res[size(filter)];
int n;
int m;
int p;
n = size(filter);
m = dims(Z)[3];
p = dims(Z)[2];
{
// system matrices for current iteration
matrix[p, m] Z_t;
matrix[m, m] T_t;
// smoother results
vector[m] r;
matrix[m, m] N;
matrix[m, m] L;
vector[m] alpha;
matrix[m, m] V;
// filter results
vector[p] v;
matrix[m, p] K;
matrix[p, p] Finv;
vector[m] a;
matrix[m, m] P;
if (size(Z) == 1) {
Z_t = Z[1];
}
if (size(T) == 1) {
T_t = T[1];
}
// initialize smoother
// r and N go from n, n - 1, ..., 1, 0.
// r_n and N_n
r = rep_vector(0.0, m);
N = rep_matrix(0.0, m, m);
// move backwards in time: t, ..., 1
for (i in 0:(n - 1)) {
int t;
t = n - i;
// set time-varying system matrices
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(T) > 1) {
T_t = T[t];
}
// get filtered values
K = ssm_filter_get_K(filter[t], m, p);
v = ssm_filter_get_v(filter[t], m, p);
Finv = ssm_filter_get_Finv(filter[t], m, p);
a = ssm_filter_get_a(filter[t], m, p);
P = ssm_filter_get_P(filter[t], m, p);
// updating
// L_t
L = ssm_filter_update_L(Z_t, T_t, K);
// r_{t - 1} and N_{t - 1}
r = ssm_smooth_update_r(r, Z_t, v, Finv, L);
N = ssm_smooth_update_N(N, Z_t, Finv, L);
// hat(alpha)_{t} and V_t which use r and N from (t - 1)
alpha = a + P * r;
V = to_symmetric_matrix(P - P * N * P);
// saving
res[t, :m] = alpha;
res[t, (m + 1): ] = symmat_to_vector(V);
}
}
return res;
}
4.6.7 ssm_smooth_eps_size
Parameters:
int
p The length of the observation vectors, \(\vec{y}_t\).
Return Value: int
The size of the vectors is \(p + p (p + 1) / 2\).
The size of the vectors returned by ssm_smooth_eps
int ssm_smooth_eps_size(int p) {
int sz;
sz = p + symmat_size(p);
return sz;
}
4.6.8 ssm_smooth_eps_get_mean
Parameters:
x
A vector from the results ofssm_smooth_eps
.int
p The length of the observation vectors, \(\vec{y}_t\).
Return Value: vector
A \(p \times 1\) vector with \(\hat{\vec{\varepsilon}}_t\).
Extract \(\hat{\vec{\varepsilon}}_t\) from vectors returned by ssm_smooth_eps
vector ssm_smooth_eps_get_mean(vector x, int p) {
vector[p] eps;
eps = x[ :p];
return eps;
}
4.6.9 ssm_smooth_eps_get_var
Parameters:
vector
x A vector returned byssm_smooth_eps
int
p The length of the observation vectors, \(\vec{y}_t\).
Return Value: matrix
A \(p \times p\) matrix with \(\Var(\vec{\varepsilon}_t | \vec{y}_{1:n})\)
Extract \(\Var(\varepsilon_t|\vec{y}_{1:n})\) from vectors returned by ssm_smooth_eps
matrix ssm_smooth_eps_get_var(vector x, int p) {
matrix[p, p] eps_var;
eps_var = vector_to_symmat(x[(p + 1): ], p);
return eps_var;
}
4.6.10 ssm_smooth_eps
Parameters:
vector[]
filter Results ofssm_filter
matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.
Return Value: vector[]
An array of vectors constaining \(\hat{\vec{\varepsilon}}_t\) and \(\Var(\vec{\varepsilon}_t | \vec{y}_{1:n})\) in the format described below.
The observation disturbance smoother
This calculates the mean and variance of the observation disturbances, \(\vec{\varepsilon}_t\), given the entire sequence, \(\vec{y}_{1:n}\).
For Z,
H, T
, the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for Z
, H
) or \(n - 1\) (for T
), if it is time varying.
The vectors returned by this function have \(p + p (p + 1) / 2\) elements in this format, \[ (\hat{\vec{\varepsilon}}_t', \VEC(\Var(\vec{\varepsilon}_t | \vec{y}_{1:n}))' )' \]
value | length | start | end |
---|---|---|---|
\(\hat{\vec{\varepsilon}}_t\) | \(p\) | \(1\) | \(p\) |
\(\Var(\vec{\varepsilon}_t | \vec{y}_{1:n})\) | \(p (p + 1) / 2\) | \(p + 1\) | \(p + p (p + 1) / 2\) |
See (Durbin and Koopman 2012, Sec 4.5.3 (eq 4.69))
vector[] ssm_smooth_eps(vector[] filter, matrix[] Z, matrix[] H, matrix[] T) {
vector[ssm_smooth_eps_size(dims(Z)[2])] res[size(filter)];
int n;
int m;
int p;
n = size(filter);
m = dims(Z)[3];
p = dims(Z)[2];
{
// smoother values
vector[m] r;
matrix[m, m] N;
matrix[m, m] L;
vector[p] eps;
matrix[p, p] var_eps;
// filter results
vector[p] v;
matrix[m, p] K;
matrix[p, p] Finv;
// system matrices
matrix[p, m] Z_t;
matrix[p, p] H_t;
matrix[m, m] T_t;
// set matrices if time-invariant
if (size(Z) == 1) {
Z_t = Z[1];
}
if (size(H) == 1) {
H_t = H[1];
}
if (size(T) == 1) {
T_t = T[1];
}
// initialize smoother
// r and N go from n, n - 1, ..., 1, 0.
// r_n and N_n
r = rep_vector(0.0, m);
N = rep_matrix(0.0, m, m);
for (i in 1:n) {
int t;
// move backwards in time
t = n - i + 1;
// update time-varying system matrices
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(H) > 1) {
H_t = H[t];
}
if (size(T) > 1) {
T_t = T[t];
}
// get values from filter
K = ssm_filter_get_K(filter[t], m, p);
v = ssm_filter_get_v(filter[t], m, p);
Finv = ssm_filter_get_Finv(filter[t], m, p);
// updating
L = ssm_filter_update_L(Z_t, T_t, K);
// r_{t - 1} and N_{t - 1}
r = ssm_smooth_update_r(r, Z_t, v, Finv, L);
N = ssm_smooth_update_N(N, Z_t, Finv, L);
// eps_t and V(eps_t|y)
eps = H_t * (Finv * v - K ' * r);
var_eps = to_symmetric_matrix(H_t - H_t * (Finv + quad_form(N, K)) * H_t);
// saving
res[t, :p] = eps;
res[t, (p + 1): ] = symmat_to_vector(var_eps);
}
}
return res;
}
4.6.11 ssm_smooth_eta
Parameters:
int
p The length of the observation vectors, \(\vec{y}_t\).
Return Value: int
The size of the vectors is \(q + q (q + 1) / 2\).
The size of the vectors returned by ssm_smooth_eta
int ssm_smooth_eta_size(int q) {
int sz;
sz = q + symmat_size(q);
return sz;
}
4.6.12 ssm_smooth_eta_get_mean
Parameters:
vector
x A vector returned byssm_smooth_eta
int
q The number of state disturbances, \(\vec{\eta}_t\).
Return Value: vector
A \(q \times 1\) vector with \(\hat{\vec{\eta}}_t\).
Extract \(\hat{\vec{\varepsilon}}_t\) from vectors returned by ssm_smooth_eta
vector ssm_smooth_eta_get_mean(vector x, int q) {
vector[q] eta;
eta = x[ :q];
return eta;
}
4.6.13 ssm_smooth_eta_get_var
Parameters:
vector
x A vector returned byssm_smooth_eta
int
q The number of state disturbances, \(\vec{\eta}_t\).
Return Value: matrix
A \(q \times q\) matrix with \(\Var(\vec{\eta}_t | \vec{y}_{1:n})\).
Extract \(\Var(\eta_t|\vec{y}_{1:n})\) from vectors returned by ssm_smooth_eta
matrix ssm_smooth_eta_get_var(vector x, int q) {
matrix[q, q] eta_var;
eta_var = vector_to_symmat(x[(q + 1): ], q);
return eta_var;
}
4.6.14 ssm_smooth_eta
Parameters:
vector[]
filter Results ofssm_filter
matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.
Return Value: vector[]
An array of vectors constaining \(\hat{\vec{\eta}}_t\) and \(\Var(\vec{\eta}_t | \vec{y}_{1:n})\) in the format described below.
The state disturbance smoother
This calculates the mean and variance of the observation disturbances, \(\vec{\eta}_t\), given the entire sequence, \(\vec{y}_{1:n}\).
For Z
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for Z
) or \(n - 1\) (for T
, R
, Q
) if it is time varying.
The vectors returned by this function have \(q + q (q + 1) / 2\) elements in this format, \[
(\hat{\vec{\eta}}_t', \VEC(\Var(\vec{\eta}_t | \vec{y}_{1:n}))' ).
\] Use the ssm_smooth_eta_get_mean
and ssm_smooth_eta_get_var
to extract components from the returned vectors.
value | length | start | end |
---|---|---|---|
\(\hat{\vec{\eta}}_t\) | \(q\) | \(1\) | \(q\) |
\(\Var(\vec{\eta}_t | \vec{y}_{1:n})\) | \(q (q + 1) / 2\) | \(q + 1\) | \(q + q (q + 1) / 2\) |
See (Durbin and Koopman 2012, Sec 4.5.3 (eq 4.69))
vector[] ssm_smooth_eta(vector[] filter,
matrix[] Z, matrix[] T,
matrix[] R, matrix[] Q) {
vector[ssm_smooth_eta_size(dims(Q)[2])] res[size(filter)];
int n;
int m;
int p;
int q;
n = size(filter);
m = dims(Z)[3];
p = dims(Z)[2];
q = dims(Q)[2];
{
// smoother matrices
vector[m] r;
matrix[m, m] N;
matrix[m, m] L;
vector[q] eta;
matrix[q, q] var_eta;
// system matrices
matrix[p, m] Z_t;
matrix[m, m] T_t;
matrix[m, q] R_t;
matrix[q, q] Q_t;
// filter matrices
vector[p] v;
matrix[m, p] K;
matrix[p, p] Finv;
// set time-invariant matrices
if (size(Z) == 1) {
Z_t = Z[1];
}
if (size(T) == 1) {
T_t = T[1];
}
if (size(R) == 1) {
R_t = R[1];
}
if (size(Q) == 1) {
Q_t = Q[1];
}
// initialize smoother
r = rep_vector(0.0, m);
N = rep_matrix(0.0, m, m);
for (i in 0:(n - 1)) {
int t;
// move backwards in time
t = n - i;
// update time-varying system matrices
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(T) > 1) {
T_t = T[t];
}
if (size(R) > 1) {
R_t = R[t];
}
if (size(Q) > 1) {
Q_t = Q[t];
}
// get values from filter
K = ssm_filter_get_K(filter[t], m, p);
v = ssm_filter_get_v(filter[t], m, p);
Finv = ssm_filter_get_Finv(filter[t], m, p);
// update smoother
L = ssm_filter_update_L(Z_t, T_t, K);
r = ssm_smooth_update_r(r, Z_t, v, Finv, L);
N = ssm_smooth_update_N(N, Z_t, Finv, L);
eta = Q_t * R_t ' * r;
var_eta = to_symmetric_matrix(Q_t - Q_t * quad_form(N, R_t) * Q_t);
// saving
res[t, :q] = eta;
res[t, (q + 1): ] = symmat_to_vector(var_eta);
}
}
return res;
}
4.6.15 ssm_smooth_faststate
Parameters:
vector[]
filter The results ofssm_filter
matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.
Return Value: vector[]
An array of size \(n\) of \(m \times 1\) vectors containing \(\hat{\vec{\alpha}}_t\).
The fast state smoother
The fast state smoother calculates \(\hat{\vec{\alpha}}_t = \E(\vec{\alpha}_t | \vec{y}_{1:n})\). \[ \hat{\vec{\alpha}}_{t + 1} = \mat{T}_t \hat{\vec{\alpha}}_{t} + \mat{R}_t \mat{Q}_t \mat{R}'_t \vec{r}_t , \] where \(r_t\) is calcualted from the state disturbance smoother. The smoother is initialized at \(t = 1\) with \(\hat{\vec{\alpha}}_t = \vec{a}_1 + \mat{P}_1 \vec{r}_0\).
Unlike the normal state smoother, it does not calculate the variances of the smoothed state.
For Z
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for Z
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
See (Durbin and Koopman 2012, Sec 4.5.3 (eq 4.69))
vector[] ssm_smooth_faststate(vector[] filter,
vector[] c, matrix[] Z, matrix[] T,
matrix[] R, matrix[] Q) {
vector[dims(Z)[3]] alpha[size(filter)];
int n;
int m;
int p;
int q;
n = size(filter);
m = dims(Z)[3];
p = dims(Z)[2];
q = dims(Q)[2];
{
// smoother matrices
vector[m] r[n + 1];
matrix[m, m] L;
vector[m] a1;
matrix[m, m] P1;
// filter matrices
vector[p] v;
matrix[m, p] K;
matrix[p, p] Finv;
// system matrices
matrix[p, m] Z_t;
vector[m] c_t;
matrix[m, m] T_t;
matrix[p, q] R_t;
matrix[q, q] Q_t;
matrix[m, m] RQR;
// set time-invariant matrices
if (size(c) == 1) {
c_t = c[1];
}
if (size(Z) == 1) {
Z_t = Z[1];
}
if (size(T) == 1) {
T_t = T[1];
}
if (size(R) == 1) {
R_t = R[1];
}
if (size(Q) == 1) {
Q_t = Q[1];
}
if (size(Q) == 1 && size(R) == 1) {
RQR = quad_form(Q[1], R[1]');
}
// find smoothed state disturbances
// Since I don't need to calculate the
// variances of the smoothed disturbances,
// I reimplement the state distrurbance smoother here
// removing extraneous parts.
// r goes from t = n, ..., 1, 0.
// r_n
r[n + 1] = rep_vector(0.0, m);
for (i in 0:(n - 1)) {
int t;
// move backwards in time
t = n - i;
// update time varying system matrices
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(T) > 1) {
T_t = T[t];
}
// get filter values
K = ssm_filter_get_K(filter[t], m, p);
v = ssm_filter_get_v(filter[t], m, p);
Finv = ssm_filter_get_Finv(filter[t], m, p);
// updating smoother
L = ssm_filter_update_L(Z_t, T_t, K);
// r_{t - 1}
r[t] = ssm_smooth_update_r(r[t + 1], Z_t, v, Finv, L);
}
// calculate smoothed states
a1 = ssm_filter_get_a(filter[1], m, p);
P1 = ssm_filter_get_P(filter[1], m, p);
// r[1] = r_0
alpha[1] = a1 + P1 * r[1];
// 1:(n - 1) -> \alpha_{2}:\alpha_{n}
for (t in 1:(n - 1)) {
if (size(c) > 1) {
c_t = c[t];
}
if (size(T) > 1) {
T_t = T[t];
}
if (size(Q) > 1) {
Q_t = Q[t];
}
if (size(R) > 1) {
R_t = R[t];
}
if (size(Q) > 1 || size(R) > 1) {
RQR = quad_form(Q_t, R_t');
}
// `r[t + 1]` = $r_{t}$
// alpha_{t + 1} = c_t + T_t * \alpha_t + R_t Q_t R'_t r_t
alpha[t + 1] = c_t + T_t * alpha[t] + RQR * r[t + 1];
}
}
return alpha;
}
4.7 Simulators and Smoothing Simulators
4.7.1 ssm_sim_idx
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: int[,]
A 4 x 3 array of integers
Indexes of each component of ssm_sim_rng
results.
The returned array has columns (length, start location, and end location) for rows: \(\vec{y}_t\), \(\vec{\alpha}_t\), \(\vec{\varepsilon}_t\), and \(\vec{\eta}_t\) in the results of ssm_sim_rng
.
int[,] ssm_sim_idx(int m, int p, int q) {
int sz[4, 3];
// y
sz[1, 1] = p;
// a
sz[2, 1] = m;
// eps
sz[3, 1] = p;
// eta
sz[4, 1] = q;
// Fill in start and stop points
sz[1, 2] = 1;
sz[1, 3] = sz[1, 2] + sz[1, 1] - 1;
for (i in 2:4) {
sz[i, 2] = sz[i - 1, 3] + 1;
sz[i, 3] = sz[i, 2] + sz[i, 1] - 1;
}
return sz;
}
4.7.2 ssm_sim_size
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: int
The number of elements
The number of elements in vectors returned by ssm_sim_rng
results.
int ssm_sim_size(int m, int p, int q) {
int sz;
sz = ssm_sim_idx(m, p, q)[4, 3];
return sz;
}
4.7.3 ssm_sim_get_y
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: vector
vector A \(p \times 1\) vector with \(\vec{y}_t\).
Extract \(\vec{y}_t\) from vectors returned by ssm_sim_rng
.
vector ssm_sim_get_y(vector x, int m, int p, int q) {
vector[m] y;
int idx[4, 3];
idx = ssm_sim_idx(m, p, q);
y = x[idx[1, 2]:idx[1, 3]];
return y;
}
4.7.4 ssm_sim_get_a
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: vector
A \(m \times 1\) vector with \(\vec{\alpha}_t\).
Extract \(\vec{\alpha}_t\) from vectors returne by ssm_sim_rng
.
vector ssm_sim_get_a(vector x, int m, int p, int q) {
vector[m] a;
int idx[4, 3];
idx = ssm_sim_idx(m, p, q);
a = x[idx[2, 2]:idx[2, 3]];
return a;
}
4.7.5 ssm_sim_get_eps
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: vector
vector A \(p \times 1\) vector with \(\vec{\varepsilon}_t\).
Extract \(\vec{\varepsilon}_t\) from vectors returne by ssm_sim_rng
.
vector ssm_sim_get_eps(vector x, int m, int p, int q) {
vector[m] eps;
int idx[4, 3];
idx = ssm_sim_idx(m, p, q);
eps = x[idx[3, 2]:idx[3, 3]];
return eps;
}
4.7.6 ssm_sim_get_eta
Parameters:
int
m The number of statesint
p The length of the observation vectorint
q The number of state disturbances
Return Value: vector
vector A \(q \times 1\) vector with \(\vec{\eta}_t\).
Extract \(\vec{\eta}_t\) from vectors returne by ssm_sim_rng
.
vector ssm_sim_get_eta(vector x, int m, int p, int q) {
vector[m] eta;
int idx[4, 3];
idx = ssm_sim_idx(m, p, q);
eta = x[idx[4, 2]:idx[4, 3]];
return eta;
}
4.7.7 ssm_sim_rng
Parameters:
vector[]
y Observations, \(\vec{y}_t\). An array of size \(n\) of \(p \times 1\) vectors.vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: Array
of size \(n\) of vectors with Draw \(\vec{y}_t\), \(\vec{\alpha}_t\), \(\vec{\eta}_t\) and \(\vec{\varepsilon}_t\). See the description.
Simulate from a Linear Gaussian State Space model.
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
Draw \(\vec{y}_t\), \(\vec{\alpha}_t\), \(\vec{\eta}_t\) and \(\vec{\varepsilon}_t\) from the state space model, \[ \begin{aligned}[t] \vec{y}_t &= \vec{d}_t + \mat{Z}_t \vec{\alpha}_t + \vec{\varepsilon}_t, & \vec{\varepsilon}_t & \sim N(0, \mat{H}_t), \\ \vec{\alpha}_{t + 1} &= \vec{c}_t + \mat{T}_t \vec{\alpha}_t + \mat{R}_t \vec{\eta}_t, & \vec{\eta}_t & \sim N(0, \mat{Q}_t), \\ && \vec{\alpha}_1 &\sim N(\vec{a}_1, \mat{P}_1) . \end{aligned} \]
The returned vectors are of length \(2 p + m + q\), in the format, \[
(\vec{y}_t', \vec{\alpha}_t', \vec{\varepsilon}_t', \vec{\eta}_t') .
\] Note that \(\eta_n = \vec{0}_q\). Use the functions ssm_sim_get_y
, ssm_sim_get_a
, ssm_sim_get_eps
, and ssm_sim_get_eta
to extract values from the vector.
element | length | start | end |
---|---|---|---|
\(y_t\) | \(p\) | \(1\) | \(p\) |
\(\alpha\)_t | \(m\) | \(p + 1\) | \(p + m\) |
\(\varepsilon_t\) | \(p\) | \(p + m + 1\) | \(2 p + m\) |
\(\eta_t\) | \(q\) | \(2 p + m + 1\) | \(2 p + m + q\) |
It is preferrable to use ssm_sim_get_y
, ssm_sim_get_a
, ssm_sim_get_eps
, and ssm_sim_get_eta
to extract values from these vectors.
vector[] ssm_sim_rng(int n,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
vector[ssm_sim_size(dims(Z)[3], dims(Z)[2], dims(Q)[2])] ret[n];
int p;
int m;
int q;
p = dims(Z)[2];
m = dims(Z)[3];
q = dims(Q)[2];
{
// system matrices for current iteration
vector[p] d_t;
matrix[p, m] Z_t;
matrix[p, p] H_t;
vector[m] c_t;
matrix[m, m] T_t;
matrix[m, q] R_t;
matrix[q, q] Q_t;
matrix[m, m] RQR;
// outputs
vector[p] y;
vector[p] eps;
vector[m] a;
vector[q] eta;
// constants
vector[p] zero_p;
vector[q] zero_q;
vector[m] zero_m;
int idx[4, 3];
d_t = d[1];
Z_t = Z[1];
H_t = H[1];
c_t = c[1];
T_t = T[1];
R_t = R[1];
Q_t = Q[1];
idx = ssm_sim_idx(m, p, q);
zero_p = rep_vector(0.0, p);
zero_q = rep_vector(0.0, q);
zero_m = rep_vector(0.0, m);
a = multi_normal_rng(a1, P1);
for (t in 1:n) {
// set system matrices
if (t > 1) {
if (size(d) > 1) {
d_t = d[t];
}
if (size(Z) > 1) {
Z_t = Z[t];
}
if (size(H) > 1) {
H_t = H[t];
}
// system matrices are n - 1 length
if (t < n) {
if (size(c) > 1) {
c_t = c[t];
}
if (size(T) > 1) {
T_t = T[t];
}
if (size(R) > 1) {
R_t = R[t];
}
if (size(Q) > 1) {
Q_t = Q[t];
}
}
}
// draw forecast error
eps = multi_normal_rng(zero_p, H_t);
// draw observed value
y = d_t + Z_t * a + eps;
// since eta_t is for alpha_{t + 1}, we don't
// draw it for t == n
if (t == n) {
eta = zero_q;
} else {
eta = multi_normal_rng(zero_q, Q_t);
}
// save
ret[t, idx[1, 2]:idx[1, 3]] = y;
ret[t, idx[2, 2]:idx[2, 3]] = a;
ret[t, idx[3, 2]:idx[3, 3]] = eps;
ret[t, idx[4, 2]:idx[4, 3]] = eta;
// a_{t + 1}
if (t < n) {
a = c_t + T_t * a + R_t * eta;
}
}
}
return ret;
}
4.8 Simulation Smoothers
4.8.1 ssm_simsmo_state_rng
Parameters:
vector[]
alpha An of size \(n\) of \(m \times 1\) vectors containing the smoothed expected values of the states, \(\E(\vec{\alpha}_{1:n} | \vec{y}_{1:n})\). These are returned bysim_smooth_faststates
. Ifsim_smooth_state
was used, then the expected values need to first be extracted usingsim_smooth_state_get_mean
.vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: vector[]
Array of size \(n\) of \(m \times 1\) vectors containing a single draw from \((\vec{\alpha}_{1:n} | \vec{y}_{1:n})\).
State simulation smoother
Draw samples from the posterior distribution of the states, \(\tilde{\vec{\alpha}}_{1:n} \sim p(\vec{\alpha}_{1:n} | \vec{y}_{1:n})\).
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
This draws samples using mean-correction simulation smoother of (Durbin and Koopman 2002). See (Durbin and Koopman 2012, Sec 4.9).
vector[] ssm_simsmo_states_rng(vector[] alpha,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
vector[dims(Z)[2]] draws[size(alpha)];
int n;
int p;
int m;
int q;
n = size(alpha);
p = dims(Z)[2];
m = dims(Z)[3];
q = dims(Q)[2];
{
vector[ssm_filter_size(m, p)] filter[n];
vector[ssm_sim_size(m, p, q)] sims[n];
vector[p] y[n];
vector[m] alpha_hat_plus[n];
// simulate unconditional disturbances and observations
sims = ssm_sim_rng(n, d, Z, H, c, T, R, Q, a1, P1);
for (i in 1:n) {
y[i] = ssm_sim_get_y(sims[i], m, p, q);
}
// filter with simulated y's
filter = ssm_filter(y, d, Z, H, c, T, R, Q, a1, P1);
// mean correct epsilon samples
alpha_hat_plus = ssm_smooth_faststate(filter, c, Z, T, R, Q);
for (i in 1:n) {
draws[i] = (ssm_sim_get_a(sims[i], m, p, q)
- alpha_hat_plus[i]
+ alpha[i]);
}
}
return draws;
}
4.8.2 ssm_simsmo_eta_rng
Parameters:
vector[]
eta Values returned bysim_smooth_eta
vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: vector[]
Array of size \(n\) of \(q \times 1\) vectors containing a single draw from \((\vec{\eta}_{1:n} | \vec{y}_{1:n})\).
State disturbance simulation smoother
Draw samples from the posterior distribution of the observation disturbances, \(\tilde{\vec{\eta}}_{1:n} \sim p(\vec{\eta}_{1:n} | \vec{y}_{1:n})\).
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
This draws samples using mean-correction simulation smoother of (Durbin and Koopman 2002). See (Durbin and Koopman 2012, Sec 4.9).
vector[] ssm_simsmo_eta_rng(vector[] eta,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
vector[dims(Q)[2]] draws[size(eta)];
int n;
int p;
int m;
int q;
n = size(eta);
p = dims(Z)[2];
m = dims(Z)[3];
q = dims(Q)[2];
{
vector[ssm_filter_size(m, p)] filter[n];
vector[p] y[n];
vector[ssm_sim_size(m, p, q)] sims[n];
vector[ssm_smooth_eta_size(q)] etahat_plus[n];
// simulate unconditional disturbances and observations
sims = ssm_sim_rng(n, d, Z, H, c, T, R, Q, a1, P1);
for (i in 1:n) {
y[i] = ssm_sim_get_y(sims[i], m, p, q);
}
// filter simulated y's
filter = ssm_filter(y, d, Z, H, c, T, R, Q, a1, P1);
// mean correct eta samples
etahat_plus = ssm_smooth_eta(filter, Z, T, R, Q);
for (i in 1:n) {
draws[i] = (ssm_sim_get_eta(sims[i], m, p, q)
- ssm_smooth_eta_get_mean(etahat_plus[i], q)
+ ssm_smooth_eta_get_mean(eta[i], q));
}
}
return draws;
}
4.8.3 ssm_simsmo_eps_rng
Parameters:
vector[]
eps Values returned bysim_smooth_eps
vector[]
d Observation intercept, \(\vec{d}_t\). An array of \(p \times 1\) vectors.matrix[]
Z Design matrix, \(\mat{Z}_t\). An array of \(p \times m\) matrices.matrix[]
H Observation covariance matrix, \(\mat{H}_t\). An array of \(p \times p\) matrices.vector[]
c State intercept, \(\vec{c}_t\). An array of \(m \times 1\) vectors.matrix[]
T Transition matrix, \(\mat{T}_t\). An array of \(m \times m\) matrices.matrix[]
R State covariance selection matrix, \(\mat{R} _t\). An array of \(p \times q\) matrices.matrix[]
Q State covariance matrix, \(\mat{Q}_t\). An array of \(q \times q\) matrices.vector
a1 Expected value of the intial state, \(a_1 = \E(\alpha_1)\). An \(m \times 1\) matrix.matrix
P1 Variance of the initial state, \(P_1 = \Var(\alpha_1)\). An \(m \times m\) matrix.
Return Value: vector[]
Array of size \(n\) of \(p \times 1\) vectors containing a single draw from \((\vec{\varepsilon}_{1:n} | \vec{y}_{1:n})\).
Observation disturbance simulation smoother
Draw samples from the posterior distribution of the observation disturbances, \(\tilde{\vec{\varepsilon}}_{1:n} \sim p(\vec{\varepsilon}_{1:n} | \vec{y}_{1:n})\).
For d
, Z
, H
, c
, T
, R
, Q
the array can have a size of 1, if it is not time-varying, or a size of \(n\) (for d
, Z
, H
) or \(n - 1\) (for c
, T
, R
, Q
) if it is time varying.
This draws samples using mean-correction simulation smoother of (Durbin and Koopman 2002). See (Durbin and Koopman 2012, Sec 4.9).
vector[] ssm_simsmo_eps_rng(vector[] eps,
vector[] d, matrix[] Z, matrix[] H,
vector[] c, matrix[] T, matrix[] R, matrix[] Q,
vector a1, matrix P1) {
vector[dims(Z)[2]] draws[size(eps)];
int n;
int p;
int m;
int q;
n = size(eps);
p = dims(Z)[2];
m = dims(Z)[3];
q = dims(Q)[2];
{
vector[ssm_filter_size(m, p)] filter[n];
vector[p] y[n];
vector[ssm_sim_size(m, p, q)] sims[n];
vector[ssm_smooth_eta_size(p)] epshat_plus[n];
// simulate unconditional disturbances and observations
sims = ssm_sim_rng(n, d, Z, H, c, T, R, Q, a1, P1);
for (i in 1:n) {
y[i] = ssm_sim_get_y(sims[i], m, p, q);
}
// filter simulated y's
filter = ssm_filter(y, d, Z, H, c, T, R, Q, a1, P1);
// mean correct epsilon samples
epshat_plus = ssm_smooth_eps(filter, Z, H, T);
for (i in 1:n) {
draws[i] = (ssm_sim_get_eps(sims[i], m, p, q)
- ssm_smooth_eps_get_mean(epshat_plus[i], p)
+ ssm_smooth_eps_get_mean(eps[i], p));
}
}
return draws;
}
4.9 Stationary
4.9.1 pacf_to_acf
Parameters:
vector
x A vector of coefficients of a partial autocorrelation function
Return Value: vector
A vector of coefficients of an Autocorrelation function
Partial Autocorrelations to Autocorrelations
vector pacf_to_acf(vector x) {
matrix[num_elements(x), num_elements(x)] y;
int n;
n = num_elements(x);
y = rep_matrix(0.0, n, n);
for (k in 1:n) {
for (i in 1:(k - 1)) {
y[k, i] = y[k - 1, i] + x[k] * y[k - 1, k - i];
}
y[k, k] = x[k];
print(y);
}
return -y[n] ';
}
4.9.2 constrain_stationary
Parameters:
vector
x An unconstrained vector in \((-\infty, \infty)\)
Return Value: vector
A vector of coefficients for a stationary AR or inverible MA process.
Constrain vector of coefficients to the stationary and intertible region for AR or MA functions.
See R. H. Jones (1980), M. C. Jones (1987), Monahan (1984), Ansley and Kohn (1986), and the functions tools.constrain_stationary_univariate
and tools.unconstraine_stationary_univariate
in statsmodels.tsa.statespace.
vector constrain_stationary(vector x) {
vector[num_elements(x)] r;
int n;
n = num_elements(x);
// transform (-Inf, Inf) to (-1, 1)
for (i in 1:n) {
r[i] = x[i] / (sqrt(1.0 + pow(x[i], 2)));
}
// Transform PACF to ACF
return pacf_to_acf(r);
}
4.9.3 acf_to_pacf
Parameters:
vector
x Coeffcients of an autocorrelation function.
Return Value: vector
A vector of coefficients of the corresponding partial autocorrelation function.
Convert coefficients of an autocorrelation function to partial autocorrelations.
vector acf_to_pacf(vector x) {
matrix[num_elements(x), num_elements(x)] y;
vector[num_elements(x)] r;
int n;
n = num_elements(x);
y = rep_matrix(0.0, n, n);
y[n] = -x ';
for (j in 0:(n - 1)) {
int k;
k = n - j;
for (i in 1:(k - 1)) {
y[k - 1, i] = (y[k, i] - y[k, k] * y[k, k - i]) / (1 - pow(y[k, k], 2));
}
}
r = diagonal(y);
return r;
}
4.9.4 unconstrain_stationary
Parameters:
vector
x Coeffcients of an autocorrelation function.
Return Value: vector
Coefficients of the corresponding partial autocorrelation function.
Transform from stationary and invertible space to \((-\infty, \infty)\).
vector unconstrain_stationary(vector x) {
matrix[num_elements(x), num_elements(x)] y;
vector[num_elements(x)] r;
vector[num_elements(x)] z;
int n;
n = num_elements(x);
// Transform ACF to PACF
r = acf_to_pacf(x);
// Transform (-1, 1) to (-Inf, Inf)
for (i in 1:n) {
z[i] = r[i] / (sqrt(1.0 - pow(r[i], 2)));
}
return z;
}
4.9.5 kronecker_prod
Parameters:
matrix
A An \(m \times n\) matrixmatrix
B A \(p \times q\) matrix
Return Value: matrix
An \(mp \times nq\) matrix.
Kronecker product
The Kronecker product of a \(A\) and \(B\) is \[ A \otimes B = \begin{bmatrix} a_{11} B \cdots a_{1n} B \\ \vdots & \ddots & vdots \\ a_{m1} B & \cdots & a_{mn} B \end{bmatrix} . \]
matrix kronecker_prod(matrix A, matrix B) {
matrix[rows(A) * rows(B), cols(A) * cols(B)] C;
int m;
int n;
int p;
int q;
m = rows(A);
n = cols(A);
p = rows(B);
q = cols(B);
for (i in 1:m) {
for (j in 1:n) {
int row_start;
int row_end;
int col_start;
int col_end;
row_start = (i - 1) * p + 1;
row_end = (i - 1) * p + p;
col_start = (j - 1) * q + 1;
col_end = (j - 1) * q + 1;
C[row_start:row_end, col_start:col_end] = A[i, j] * B;
}
}
return C;
}
4.9.6 arima_stationary_cov
Parameters:
matrix
T The \(m \times m\) transition matrixmatrix
R The \(m \times q\) system disturbance selection matrix
Return Value: matrix
An \(m \times m\) matrix with the stationary covariance matrix.
Find the covariance of the stationary distribution of an ARMA model
The initial conditions are \(\alpha_1 \sim N(0, \sigma^2 Q_0)\), where \(Q_0\) is the solution to \[ (T \otimes T) \VEC(Q_0) = \VEC(R R') \] where \(\VEC(Q_0)\) and \(\VEC(R R')\) are the stacked columns of \(Q_0\) and \(R R'\)
See Durbin and Koopman (2012), Sec 5.6.2.
matrix arima_stationary_cov(matrix T, matrix R) {
matrix[rows(T), cols(T)] Q0;
matrix[rows(T) * rows(T), rows(T) * rows(T)] TT;
vector[rows(T) * rows(T)] RR;
int m;
int m2;
m = rows(T);
m2 = m * m;
RR = to_vector(tcrossprod(R));
TT = kronecker_prod(T, T);
Q0 = to_matrix_colwise((diag_matrix(rep_vector(1.0, m2)) - TT) \ RR, m, m);
return Q0;
}
References
Durbin, J., and S.J. Koopman. 2012. Time Series Analysis by State Space Methods: Second Edition. Oxford Statistical Science Series. OUP Oxford. http://books.google.com/books?id=fOq39Zh0olQC.
Durbin, J., and S. J. Koopman. 2002. “A Simple and Efficient Simulation Smoother for State Space Time Series Analysis.” Biometrika 89 (3). Biometrika Trust: 603–15. http://www.jstor.org/stable/4140605.
Jones, Richard H. 1980. “Maximum Likelihood Fitting of ARMA Models to Time Series with Missing Observations.” Technometrics 22 (3). [Taylor & Francis, Ltd., American Statistical Association, American Society for Quality]: 389–95. http://www.jstor.org/stable/1268324.
Jones, M. C. 1987. “Randomly Choosing Parameters from the Stationarity and Invertibility Region of Autoregressive-Moving Average Models.” Journal of the Royal Statistical Society. Series C (Applied Statistics) 36 (2). [Wiley, Royal Statistical Society]: 134–38. http://www.jstor.org/stable/2347544.
Monahan, John F. 1984. “A Note on Enforcing Stationarity in Autoregressive-Moving Average Models.” Biometrika 71 (2): 403–4. doi:10.1093/biomet/71.2.403.
Ansley, Craig F., and Robert Kohn. 1986. “A Note on Reparameterizing a Vector Autoregressive Moving Average Model to Enforce Stationarity.” Journal of Statistical Computation and Simulation 24 (2): 99–106. doi:10.1080/00949658608810893.