← Back to Model Library

Kalman Filter Model

Optimal Estimation for Dynamic Systems

Overview

The Kalman Filter is an optimal recursive estimation algorithm that uses a series of noisy measurements observed over time to produce estimates of unknown variables. It is particularly powerful for dynamic systems where the true state cannot be directly observed but can be inferred from noisy measurements. The Kalman Filter operates in a two-step process: prediction and update, making it highly suitable for real-time applications like navigation, control systems, and, importantly, time series forecasting where data is often noisy and incomplete.

Architecture & Components

The Kalman Filter is based on a **state-space model**, which describes a system in terms of its internal state variables. It assumes that the system's state at time $t$ can be derived from its state at $t-1$ and that observations are noisy measurements of this state. The filter operates in two phases:

  1. Prediction (Time Update):

    In this phase, the filter estimates the current state and its uncertainty based on the previous state estimate and a model of the system's dynamics. It projects the state forward in time.

    $ \hat{x}_t^- = F_t \hat{x}_{t-1} + B_t u_t $
    $ P_t^- = F_t P_{t-1} F_t^T + Q_t $

    Where:
    • $\hat{x}_t^-$: Predicted state estimate at time $t$.
    • $F_t$: State transition model (matrix) applied to the previous state.
    • $\hat{x}_{t-1}$: Previous state estimate.
    • $B_t$: Control-input model (matrix) applied to control vector $u_t$.
    • $u_t$: Control vector (optional external input).
    • $P_t^-$: Predicted (a priori) estimate covariance.
    • $Q_t$: Covariance of the process noise (uncertainty in the system model).
  2. Update (Measurement Update):

    In this phase, the filter refines its state estimate using the current noisy measurement. It calculates a "Kalman Gain" that determines how much weight to give to the new measurement versus the prediction.

    $ K_t = P_t^- H_t^T (H_t P_t^- H_t^T + R_t)^{-1} $
    $ \hat{x}_t = \hat{x}_t^- + K_t (z_t - H_t \hat{x}_t^-) $
    $ P_t = (I - K_t H_t) P_t^- $

    Where:
    • $K_t$: Kalman Gain.
    • $H_t$: Observation model (matrix) relating state to measurement.
    • $R_t$: Covariance of the observation noise (uncertainty in the measurement).
    • $z_t$: Actual measurement at time $t$.
    • $\hat{x}_t$: Updated (a posteriori) state estimate.
    • $P_t$: Updated (a posteriori) estimate covariance.
    • $I$: Identity matrix.

The filter assumes linear system dynamics and Gaussian noise. Extensions like the Extended Kalman Filter (EKF) and Unscented Kalman Filter (UKF) handle non-linear systems.

Kalman Filter Architecture Diagram

Conceptual diagram of the Kalman Filter's prediction and update cycle.

When to Use Kalman Filter

The Kalman Filter is particularly useful for time series forecasting and state estimation when:

  • Data is noisy or incomplete: It can provide optimal estimates by fusing noisy measurements with a system model, and it can handle missing data points.
  • The system's underlying state is unobservable: It infers the true state from indirect measurements.
  • Real-time estimation and prediction are required: Its recursive nature makes it efficient for online processing.
  • The system dynamics can be approximated as linear (or linearized for EKF/UKF): It performs optimally under these conditions.
  • You need uncertainty quantification: It provides a covariance matrix for the state estimate, quantifying its uncertainty.
  • Applications involve tracking, navigation, control, or signal processing.

Pros and Cons

Pros

  • Optimal Estimator: Provides the minimum mean squared error estimate for linear Gaussian systems.
  • Handles Noise & Missing Data: Effectively filters noise and can estimate states even with missing observations.
  • Adaptive: Can adapt to changing system dynamics over time.
  • Real-time Capability: Recursive nature makes it suitable for online processing and sequential data.
  • Uncertainty Quantification: Provides covariance of the state estimate, offering a measure of confidence.

Cons

  • Assumes Linearity & Gaussian Noise: Standard Kalman Filter is limited to linear systems with Gaussian noise. EKF/UKF extend this but add complexity.
  • Requires System Model: Needs accurate knowledge of the state transition and observation models (matrices $F, H, Q, R$). Mis-specification can lead to poor performance.
  • Computational Cost: Can be high for systems with many state variables (large state vector).
  • Parameter Tuning: Process noise ($Q$) and observation noise ($R$) covariances often need careful tuning.
  • Less Flexible for Complex Non-Linearities: While EKF/UKF exist, highly non-linear systems might still be challenging.

Example Implementation

Here's an example of implementing a Kalman Filter in Python using the `pykalman` library. We'll simulate a simple system with a hidden state (e.g., true value) and noisy observations, then use the Kalman Filter to estimate the true state and predict future values.

Python Example (using `pykalman` library)

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

# 1. Generate synthetic data: A true underlying state with noisy observations
np.random.seed(42)
n_timesteps = 100

# True state (e.g., position and velocity)
true_states = np.zeros((n_timesteps, 2)) # [position, velocity]
true_states =  # Initial position 0, initial velocity 1

# Simulate state evolution: position += velocity, velocity is constant with noise
# x_t = F * x_{t-1} + process_noise
F = np.array([[1, 1], ]) # State transition matrix
Q = np.array([[0.1, 0], [0, 0.01]]) # Process noise covariance

for t in range(1, n_timesteps):
    process_noise = np.random.multivariate_normal(, Q)
    true_states[t] = np.dot(F, true_states[t-1]) + process_noise

# Simulate noisy observations (only observe position)
# z_t = H * x_t + observation_noise
H = np.array([]) # Observation matrix (observe only position)
R = np.array([[0.5]]) # Observation noise covariance (scalar for univariate observation)

observations = np.zeros((n_timesteps, 1))
for t in range(n_timesteps):
    observation_noise = np.random.normal(0, np.sqrt(R))
    observations[t] = np.dot(H, true_states[t]) + observation_noise

# Introduce some missing values for demonstration
# observations[10:20] = np.nan
# observations[50:60] = np.nan

# 2. Initialize Kalman Filter
kf = KalmanFilter(
    transition_matrices=F,
    observation_matrices=H,
    initial_state_mean=true_states, # Initial guess for state
    initial_state_covariance=np.eye(2), # Initial uncertainty
    transition_covariance=Q, # Process noise covariance
    observation_covariance=R, # Observation noise covariance
    em_vars=['transition_covariance', 'observation_covariance', 'initial_state_mean', 'initial_state_covariance'] # Variables to estimate using EM
)

# 3. Fit the Kalman Filter (using EM algorithm to estimate parameters from data)
# This step is optional if F, H, Q, R are already known accurately
kf = kf.em(observations, n_iter=10)

# 4. Apply the Kalman Filter to estimate states
# filter_update returns filtered state means and covariances
state_means, state_covariances = kf.filter(observations)

# 5. Make predictions (forecasts)
# predict_update predicts future states given the last filtered state
forecast_horizon = 20
last_state_mean = state_means[-1]
last_state_covariance = state_covariances[-1]

# Predict future states
predicted_state_means, predicted_state_covariances = kf.predict(
    last_state_mean, last_state_covariance, n_timesteps=forecast_horizon
)

# Extract forecasted observations (position) from predicted states
forecasted_observations = np.dot(predicted_state_means, H.T)

# 6. Plotting Results
plt.figure(figsize=(14, 7))

# Plot true state (position)
plt.plot(np.arange(n_timesteps), true_states[:, 0], 'k-', label='True State (Position)')

# Plot noisy observations
plt.plot(np.arange(n_timesteps), observations[:, 0], 'rx', label='Noisy Observations', alpha=0.6)

# Plot filtered state (estimated position)
plt.plot(np.arange(n_timesteps), state_means[:, 0], 'b-', label='Filtered State (Estimated Position)')
plt.fill_between(np.arange(n_timesteps),
                 state_means[:, 0] - np.sqrt(state_covariances[:, 0, 0]),
                 state_means[:, 0] + np.sqrt(state_covariances[:, 0, 0]),
                 color='blue', alpha=0.2, label='Filtered 1-sigma CI')

# Plot forecasted observations
forecast_time_idx = np.arange(n_timesteps, n_timesteps + forecast_horizon)
plt.plot(forecast_time_idx, forecasted_observations[:, 0], 'g--', label='Forecasted Observations')
plt.fill_between(forecast_time_idx,
                 forecasted_observations[:, 0] - np.sqrt(predicted_state_covariances[:, 0, 0]),
                 forecasted_observations[:, 0] + np.sqrt(predicted_state_covariances[:, 0, 0]),
                 color='green', alpha=0.2, label='Forecasted 1-sigma CI')

plt.title('Kalman Filter: State Estimation and Forecasting')
plt.xlabel('Time Step')
plt.ylabel('Value')
plt.legend()
plt.grid(True)
plt.show()
                        

Dependencies & Resources

Dependencies: numpy, pandas, pykalman, matplotlib (for plotting).