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.