# Kalman Filter State Covariance Matrix for Non Constant Process Noise Matrix in PyKalman

I'm experimenting with the pykalman Python library to learn about Kalman Filters. In the code below, I'm generating a random walk where each step is the last step multiplied by 1 plus some noise: 1 + std_dev. In the first block, the covariance matrix of the KF (using a 1D signal/state, so it's really just one variance) appears to converge to about 0.62. Even if I set grow_std_dev=True, causing the noise to grow significantly over time, the covariance matrix still converges to this value.

import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter

def generate_random_walk(seed=1, n_steps=100, grow_std_dev=False):
np.random.seed(seed)
rand_walk = [1]
std_devs = []

for n in range(n_steps):
if grow_std_dev:
std_dev = np.random.normal(0,0.01 * (1 + n))
else:
std_dev = np.random.normal(0,0.01)
val = rand_walk[-1] * (1 + std_dev)
std_devs.append(std_dev)
rand_walk.append(val)

return np.array(rand_walk), np.array(std_devs)

kf = KalmanFilter(transition_matrices = [1],
observation_matrices = [1],
initial_state_mean = 1,
initial_state_covariance = 1,
observation_covariance=1,
transition_covariance=1)

rand_walk, std_devs = generate_random_walk(0)
state_means, state_cov = kf.filter(rand_walk)

plt.plot(std_devs)
plt.show()
plt.plot(rand_walk_1)
plt.show()
plt.plot(state_cov.flatten())

The plots produced by the above code:

I read elsewhere that KFs can be used to perform recursive linear regression (I believe this is the correct term) between two variables by passing one variable for the observation_matrices argument and the other as the value to filter. So in the block below, I'm generating a second random walk with a different seed and passing that for observation_matrices rather than the fixed matrix of [1] as in the first block. Unlike the first example, this results in a covariance matrix that does not converge.

rand_walk_2, _ = generate_random_walk(1)

kf = KalmanFilter(transition_matrices = [1],
observation_matrices = rand_walk_2[:,None,None],
initial_state_mean = 1,
initial_state_covariance = 1,
observation_covariance=1,
transition_covariance=1)

state_means, state_cov = kf.filter(rand_walk_1)

plt.plot(rand_walk_2)
plt.show()
plt.plot(state_cov.flatten())

I'm really not as concerned with the second example other than to show that it's possible for the covariance matrix to not converge. In learning about Kalman Filters, my understanding was that part of the value is that the uncertainty of the estimate is quantified at each time step, i.e., that the covariance matrix is evolving with the state estimate. Again, by setting grow_std_dev=True, I would expect that the covariance matrix would need to change for the filter to make optimal predictions.

With that said, I'm wondering if I'm missing something about how KFs are supposed to work, missing an argument, or otherwise.

Any help is appreciated.

• Most KFs don’t have time varying noise covariance, and so the state covariance converges. Sometimes people forgo the full Kalyan filter and just use the converged filter. I’ll have to dig a bit further into your case to see what is happening, but that will be tomorrow.
– Peter K.
Dec 13, 2021 at 3:59

For classic Kalman Filter, where $${Q}_{k} = Q$$ and $${R}_{k} = R$$, namely the process noise covariance and the measurement noise covariance (I'm using Wikipedia - Kalman Filter notations) the Posterior Covariance $${P}_{k}$$ is a deterministic matrix independent of the measurements themselves.