mlysy / kalmantv

High-Performance Kalman Filtering and Smoothing in Python
12 stars 1 forks source link

kalmantv: High-Performance Kalman Filtering and Smoothing in Python

Mohan Wu, Martin Lysy


Description

kalmantv provides a simple Python interface to the time-varying Kalman filtering and smoothing algorithms. The underlying model is

x_n = Qn (x{n-1} -lambda_n) + lambda_n + R_n^{1/2} eps_n

y_n = d_n + W x_n + Sigma_n^{1/2} eta_n,

where eps_n and eta_n are independent vectors of iid standard normals of size n_state and n_meas, respectively. The Kalman filtering and smoothing algorithms are efficient ways of calculating

Various low-level backends are provided in the following modules:

Installation

For the PyPi version, simply do pip install .. For the latest (stable) development version:

git clone https://github.com/mlysy/kalmantv
cd kalmantv
pip install .

Unit Testing

The unit tests are done against the pykalman library to ensure the same results. From inside the root folder of the kalmantv source code:

pip install .[tests]
tox

Documentation

The HTML documentation can be compiled from the kalmantv root folder:

pip install .[docs]
cd docs
make html

This will create the documentation in docs/build.

Usage

The following example illustrates how to run one step of the Kalman filtering algorithm. This is done using the filter() method of the KalmanTV class in the kalmantv.cython module. The same class is defined in kalmantv.eigen and kalmantv.numba modules with exactly the same methods and signatures.

Starting with E[x{n-1} | y{0:n-1}] and var(x{n-1} | y{0:n-1}) obtained at time n-1, the goal is to compute E[x{n-1} | y{0:n-1}] and var(x{n-1} | y{0:n-1}) at the next time step n.

import numpy as np
from kalmantv.cython import KalmanTV
n_meas = 2 # Set the size of the measurement
n_state = 4 # Set the size of the state

# Initialize mean and variance at tim n-1
mu_state_past = np.random.rand(n_state)                # E[x_{n-1} | y_{0:n-1}]
var_state_past = np.random.rand(n_state, n_state)      # var(x_{n-1} | y_{0:n-1})
var_state_past = var_state_past.dot(var_state_past.T)  # ensure symmetric positive definiteness
var_state_past = np.asfortranarray(var_state_past)     # convert to Fortran order

# Parameters to the Kalman Filter
mu_state = np.random.rand(n_state)               # lambda_n
wgt_state = np.random.rand(n_state, n_state).T   # Q_n
var_state = np.random.rand(n_state, n_state)     # R_n
var_state = var_state.dot(var_state.T).T
x_meas = np.random.rand(n_meas)                  # y_n
mu_meas = np.random.rand(n_meas)                 # d_n
wgt_meas = np.random.rand(n_state, n_meas).T     # W_n
var_meas = np.random.rand(n_meas, n_meas)        # Sigma_n
var_meas = var_meas.dot(var_meas.T).T

# Initialize the KalmanTV class
ktv = KalmanTV(n_meas, n_state)

# Allocate memory for storing the output
mu_state_pred = np.empty(n_state)                         # E[x_n | y_{0:n-1}]
var_state_pred = np.empty((n_state, n_state), order='F')  # var(x_n | y_{0:n-1})
mu_state_filt = np.empty(n_state)                         # E[x_n | y_{0:n}]
var_state_filt = np.empty((n_state, n_state), order='F')  # var(x_n | y_{0:n})

# Run the filtering algorithm
ktv.filter(mu_state_pred, var_state_pred,
           mu_state_filt, var_state_filt,
           mu_state_past, var_state_past,
           mu_state, wgt_state, var_state,
           x_meas, mu_meas, wgt_meas, var_meas)

A similar interface for Kalman smoothing and smoothed sampling is provided by the methods KalmanTV.smooth_mv() and KalmanTV.smooth_sim(). Please see documentation for details.