Simultaneous Kalman Filters
simdkalman provides Kalman filters vectorized as Single Instruction, Multiple Data, enabling efficient processing of multiple independent time series simultaneously. It is designed for performance when dealing with large numbers of parallel Kalman filter estimations. The library is actively maintained and currently at version 1.0.4, with a stable release cadence focused on performance and bug fixes.
Common errors
-
ValueError: operands could not be broadcast together with shapes (X,Y) (Z,W) (and similar numpy shape errors)
cause Input data (observations, state transition matrices, noise covariance matrices) does not conform to the expected dimensions for vectorized processing. simdkalman typically expects `(n_series, n_timesteps, n_features)` for observations or `(n_series, n_features, n_features)` for covariance matrices.fixCarefully check the shape of all input arrays against the documentation requirements. Use `np.newaxis` or `reshape` to ensure your data has the correct number of dimensions, especially for `n_features` if your data is 1D. -
AttributeError: 'KalmanFilter' object has no attribute 'compute'
cause Attempting to use the `compute` method on `KalmanFilter` from a specific version (1.0.0) that had a bug affecting this method. Or, using an API that was changed/removed in older versions.fixUpdate `simdkalman` to version 1.0.1 or newer, which fixed the `compute` method. Always refer to the latest documentation for current API usage. -
RuntimeError: The observation_model must be set.
cause The `observation_model` parameter, which defines how hidden states map to observations, was not provided during `KalmanFilter` initialization.fixEnsure `KalmanFilter` is initialized with a valid `observation_model` (e.g., `np.array([[1]])` for a simple case, or a callable for a more complex model) alongside `state_transition`, `process_noise`, and `observation_noise`.
Warnings
- gotcha Versions prior to 1.0.2 contained a bug where shape checks for updates with varying or vectorized H-matrices were incorrect, potentially leading to wrong results without explicit errors for affected use cases.
- gotcha Versions prior to 1.0.4 might consume significantly more memory, especially when processing very large datasets or many parallel time series, due to less optimized internal data structures.
- gotcha simdkalman is designed for vectorized (simultaneous) Kalman filter operations on multiple time series. While it can be used for a single series, it might be less performant or efficient than single-series-optimized Kalman filter implementations or simpler statistical methods for very small datasets.
Install
-
pip install simdkalman
Imports
- KalmanFilter
from simdkalman.KalmanFilter import KalmanFilter
import simdkalman kalman_filter = simdkalman.KalmanFilter(...)
Quickstart
import numpy as np
import simdkalman
# Generate some synthetic data for 3 series, 50 time steps each
n_series = 3
n_timesteps = 50
rand = np.random.RandomState(0)
true_states = np.cumsum(rand.normal(0, 0.1, size=(n_series, n_timesteps)), axis=1)
observations = true_states + rand.normal(0, 1, size=(n_series, n_timesteps))
# Initialize a Kalman Filter
# Simple 1-D random walk model:
# state_transition = [[1]] (state at t is state at t-1)
# process_noise = [[0.1]] (noise in state transition)
# observation_model = [[1]] (observation is directly the state)
# observation_noise = [[1.0]] (noise in observation)
kf = simdkalman.KalmanFilter(
state_transition = np.array([[1]]), # 1D state, previous state is current state
process_noise = np.diag([0.1]), # Variance of 0.1 for state evolution
observation_model = np.array([[1]]), # Observation is the state itself
observation_noise = np.diag([1.0]) # Observation noise variance of 1.0
)
# Smooth the observations
# `observations` needs to be 3D: (n_series, n_timesteps, n_features)
# Here n_features is 1 for 1D data.
smoothed_states = kf.smooth(observations[:, :, np.newaxis]).states.mean
print(f"Smoothed states shape: {smoothed_states.shape}")
# Expected: (n_series, n_timesteps, 1)
# You can also predict new values
predicted_states = kf.predict(observations[:, :, np.newaxis], n_test=10).states.mean
print(f"Predicted states shape: {predicted_states.shape}")