Like the Kalman Filter, the Unscented Kalman Filter is an unsupervised algorithm for tracking a single target in a continuous state space. The difference is that while the Kalman Filter restricts dynamics to affine functions, the Unscented Kalman Filter is designed to operate under arbitrary dynamics.
The advantages of the Unscented Kalman Filter implemented here are:
Ability to handle non-affine state transition and observation functions
Ability to handle not-quite-Gaussian noise models
Same computational complexity as the standard Kalman Filter
The disadvantages are:
No method for learning parameters
Lack of theoretical guarantees on performance
Inability to handle extremely non-Gaussian noise
Basic Usage¶
Like KalmanFilter
, two methods are provided in
UnscentedKalmanFilter
for tracking targets:
UnscentedKalmanFilter.filter()
and UnscentedKalmanFilter.smooth()
.
At this point no algorithms have been implemented for inferring parameters, so
they must be specified by hand at instantiation.
In order to apply these algorithms, one must specify a subset of the following,
Variable Name
Mathematical Notation
Default
transition_functions[t]
f_t
state plus noise
observation_functions[t]
g_t
state plus noise
transition_covariance
Q
identity
observation_covariance
R
identity
initial_state_mean
\mu_0
zero
initial_state_covariance
\Sigma_0
identity
If parameters are left unspecified, they will be replaced by their defaults.
One also has the option of simply specifying n_dim_state
or
n_dim_obs
if the size of the state or observation space cannot be
inferred directly.
The state transition function and observation function have replaced the
transition matrix/offset and observation matrix/offset from the original
KalmanFilter
, respectively. Both must take in the current state and
some Gaussian-sampled noise and return the next state/current observation. For
example, if noise were multiplicative instead of additive, the following would
be valid:
>>> def f(current_state, transition_noise):
... return current_state * transition_noise
...
>>> def g(current_state, observation_noise):
... return current_state * observation_noise
Once defined, the UnscentedKalmanFilter
can be used to extract
estimated state and covariance matrices over the hidden state:
>>> from pykalman import UnscentedKalmanFilter
>>> import numpy as np
>>> def f(state, noise):
... return state + np.sin(noise)
...
>>> def g(state, noise):
... return state + np.cos(noise)
...
>>> ukf = UnscentedKalmanFilter(f, g, observation_covariance=0.1)
>>> ukf.smooth([0, 1, 2])[0]
array([[-0.94034641],
[ 0.05002316],
[ 1.04502498]])
Methods for online estimation are also included:
>>> means, covariances = ukf.filter([0,1])
>>> next_mean, next_covariance = ukf.filter_update(means[-1], covariances[-1], [2])
If the UnscentedKalmanFilter
is instantiated with an array of
functions for transition_functions
or observation_functions
,
then the function is assumed to vary with time. Currently there is no support
for time-varying covariance matrices.
Which Unscented Kalman Filter is for Me?¶
Though only UnscentedKalmanFilter
was mentioned in the previous
section, there exists another class specifically designed for the case when
noise is additive, AdditiveUnscentedKalmanFilter
. While more
restrictive, this class offers reduced computational complexity
(O(Tn^3) vs. O(T(2n+m)^3) for state space with dimensionality
n, observation space with dimensionality m) and better
numerical stability. When at all possible, the
AdditiveUnscentedKalmanFilter
should be preferred to its counterpart.
To reflect the restriction on how noise is integrated, the
AdditiveUnscentedKalmanFilter
uses state transition and observation
functions with slightly different arguments:
def f(current_state):
...
def g(current_state):
...
Notice that the transition/observation noise is no longer an argument. Its effect will be taken care of at later points in the algorithm without any need for your explicit input.
Finally, users should note that the UnscentedKalmanFilter
can
potentially suffer from collapse of the covariance matrix to zero.
Algorithmically, this means that the UnscentedKalmanFilter is one hundred
percent sure of the state and that no noise is left in the system. In order to
avoid this, one must ensure that even for small amounts of noise,
transition_functions
and observation_functions
output different
values for the same current state.
Choosing Parameters¶
The majority of advice on choosing parameters in Kalman Filter section apply to the Unscented Kalman Filter except that there is no method for learning parameters and the following code snippet defines the probabilistic model the Unscented Kalman Filter (approximately) solves,
from scipy.stats import norm
import numpy as np
states = np.zeros((n_timesteps, n_dim_state))
measurements = np.zeros((n_timesteps, n_dim_obs))
for t in range(n_timesteps-1):
if t == 0:
states[t] = norm.rvs(initial_state_mean, np.sqrt(initial_state_covariance))
measurements[t] = (
observation_function(
states[t],
norm.rvs(0, np.sqrt(observation_covariance))
)
)
states[t+1] = (
transition_function(
states[t],
norm.rvs(0, np.sqrt(transition_covariance))
)
)
measurements[t+1] = (
observation_function(
states[t+1],
norm.rvs(0, np.sqrt(observation_covariance))
)
)
Missing Measurements¶
The UnscentedKalmanFilter
and AdditiveUnscentedKalmanFilter
have the same support for missing measurements that the original
KalmanFilter
class supports. Usage is precisely the same.
Mathematical Formulation¶
The mathematical formulation of the model the Unscented Kalman Filter is based on is unsurprisingly similar to that of the standard Kalman Filter. In this section, we will again adopt the notation x_t to describe the (unknown) state at time step t and z_t to denote the (known) observation. The parameters of the Unscented Kalman Filter are as follows,
Parameter Name
Notation
transition_functions
f
observation_functions
g
transition_covariance
Q
observation_covariance
R
initial_state_mean
\mu_0
initial_state_covariance
\Sigma_0
To estimate x_t using the above and z_t, we must describe how
these parameters effect x_t and z_t. The two models used, as
implemented by AdditiveUnscentedKalmanFilter
and
UnscentedKalmanFilter
respectively are as follows,
In the case of the additive noise model,
x_0 & \sim \text{Gaussian}(\mu_0, \Sigma_0) \\ x_{t+1} & = f_t(x_t) + \epsilon_{t+1}^{1} \\ z_{t} & = g_t(x_t) + \epsilon_{t}^2 \\ \epsilon_t^1 & \sim \text{Gaussian}(0, Q) \\ \epsilon_{t}^2 & \sim \text{Gaussian}(0, R)
The general model is nearly the same, except with the following modifications,
x_{t+1} & = f_t(x_t, \epsilon_{t+1}^1) \\ z_{t} & = g_t(x_t, \epsilon_{t}^2)
In the standard Kalman Filter case, we could be certain that the probability distribution over x_t is always a Gaussian distribution, even after observing z_t. In the above scenarios that is no longer the case, but we make the approximation that it is. If f_t and g_t are almost linear, then the Unscented Kalman Filter will be a good approximation.