Hi there! I'm new to pykalman and Kalman filters in general, so I may be doing something wrong. But I am pretty sure the covariance matrix should always be symmetric. If it's not, eigenvalues may be complex and things get weird. (I found this when computing the confidence ellipsoid for smoothed data)
The following code produces a non-symmetric initial covariance matrix; the asymmetry gets worse with larger n_iter
(try 10, 20, 30, 40, 50, 100) or larger numbers of samples. It looks like a float precision problem; I am OK with unreliable information at high iterations but this asymmetry throws a wrench in things.
I imagine we could fix this by making the matrix symmetric after each iteration. Interested in your thoughts.
import numpy as np
import numpy.ma as ma
import pykalman
dt = 1.
# define transition function F as in \bar x = F \cdot x
transition_matrix = np.array([
[1, dt, dt*dt/2., dt*dt*dt/6., 0, 0, 0, 0 ],
[0, 1, dt, dt*dt/2., 0, 0, 0, 0 ],
[0, 0, 1, dt, 0, 0, 0, 0 ],
[0, 0, 0, 1, 0, 0, 0, 0 ],
[0, 0, 0, 0, 1, dt, dt*dt/2., dt*dt*dt/6. ],
[0, 0, 0, 0, 0, 1, dt, dt*dt/2. ],
[0, 0, 0, 0, 0, 0, 1, dt ],
[0, 0, 0, 0, 0, 0, 0, 1 ]
])
# define matrix which transforms state into measurements;
# our state is x, y, dx/dt, and dy/dt
observation_matrix = np.array([
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
])
# not really sure what this means; maybe let EM figure it out?
transition_covariance = np.eye(8) * 10.
# This is our variance in position and velocity. If std-dev of position is 10 meters, then
#100 m^2 is the variance. But speed seems to be known a little (a lot?) better.
observation_covariance = np.diag([200., 200., 8., 8.])
kf = pykalman.KalmanFilter(
n_dim_state=8,
n_dim_obs=4,
transition_matrices=transition_matrix,
observation_matrices=observation_matrix,
transition_covariance=transition_covariance,
observation_covariance=observation_covariance,
em_vars=['transition_covariance', 'initial_state_mean', 'initial_state_covariance']
)
measurements = ma.MaskedArray([
[ 5.27477432255369727500e+05, 5.03764540228472929448e+06, 0.00000000000000000000e+00,
6.21999979019165039062e+00],
[ 5.27477414331637672149e+05, 5.03764949726117122918e+06, 0.00000000000000000000e+00,
6.09000015258789062500e+00],
[ 5.27477389067118521780e+05, 5.03765526935885101557e+06, 0.00000000000000000000e+00,
6.07000017166137695312e+00],
[ 5.27477358017556718551e+05, 5.03766236313823424280e+06, 0.00000000000000000000e+00,
6.03999996185302734375e+00],
[ 5.27477370752291753888e+05, 5.03766877081946097314e+06, 9.77669604515315898707e-02,
6.02920758903960862796e+00],
[ 5.27477440341255976819e+05, 5.03767462179020419717e+06, 9.97125696816208162421e-02,
6.14919170106664569886e+00],
[ 5.27477508913885336369e+05, 5.03768038927771802992e+06, 9.97125696816208162421e-02,
6.14919170106664569886e+00],
[ 5.27477562812059884891e+05, 5.03768492094157077372e+06, 9.84154968615613273686e-02,
6.06920229304862068886e+00],
[ 5.27477570536027313210e+05, 5.03768557030001003295e+06, 9.84154968615613273686e-02,
6.06920229304862068886e+00],
[ 5.27477570536027313210e+05, 5.03768557030001003295e+06, 9.82533588934719759322e-02,
6.05920337865912728148e+00]])
kf.initial_state_mean = np.array([
measurements[0, 0],
measurements[0, 2],
0.0,
0.,
measurements[0, 1],
measurements[0, 3],
0.,
0.,
])
kf.em(measurements, n_iter=50)
np.set_printoptions(precision=3, linewidth=120)
print kf.initial_state_covariance
array([[ 4.827e-01, -4.122e-02, -6.912e-03, 3.051e-03, -1.660e-02, 4.739e-03, -1.753e-03, 8.911e-04],
[ -3.962e-02, 9.683e-02, -5.243e-02, 1.129e-02, 1.396e-04, -4.835e-04, 1.561e-04, 3.462e-04],
[ -8.120e-03, -5.200e-02, 5.937e-02, -1.725e-02, 2.004e-03, 1.206e-03, -4.209e-03, 1.251e-03],
[ 3.233e-03, 1.148e-02, -1.782e-02, 8.169e-03, 5.355e-04, 3.772e-04, 8.248e-04, -4.479e-04],
[ 1.953e-02, -4.290e-03, 1.119e-03, -7.555e-04, 4.844e-01, -4.070e-02, -6.510e-03, 2.944e-03],
[ -1.334e-04, 5.095e-04, -1.539e-04, -3.632e-04, -3.899e-02, 9.679e-02, -5.233e-02, 1.127e-02],
[ -2.107e-03, -1.324e-03, 4.377e-03, -1.307e-03, -8.132e-03, -5.206e-02, 5.933e-02, -1.720e-02],
[ -4.134e-04, -3.451e-04, -8.956e-04, 4.622e-04, 3.401e-03, 1.153e-02, -1.781e-02, 8.157e-03]])