Filters¶
One of the principal functions of a dynamical systems inference engine is filtering, i.e., computation of the distribution \(p(x_t \mid y_{1:T}, \theta)\). In the computation of a filtering distribution, we also obtain estimates of the marginal likelihood, \(p(y_{1:T} | \theta)\), used for parameter inference/system identification. To tell dynestyx that a dynamical system should be processed via a filtering algorithm, we use the Filter class.
BaseLogFactorAdder
¶
ContinuousTimeDPFConfig
dataclass
¶
Bases: PFConfig, ContinuousTimeConfig
Continuous-discrete Differentiable Particle Filter (CD-DPF).
Particle filter for continuous-time SDEs. Particles are propagated by solving the SDE between observations; importance weights are updated at each observation time. Supports non-Gaussian observations and arbitrary nonlinear dynamics.
Uses multinomial resampling by default (vs. systematic in PFConfig)
for better compatibility with gradient-based training.
See PFConfig for particle tuning options and ContinuousTimeConfig
for solver options.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
resampling_method |
PFResamplingConfig
|
Defaults to
|
Algorithm Reference
The bootstrap version of the continuous-discrete PF is the same as the discrete-time PF version.
See PFConfig for more information.
ContinuousTimeEKFConfig
dataclass
¶
Bases: EKFConfig, ContinuousTimeConfig
Continuous-discrete Extended Kalman Filter (CD-EKF).
Fast Gaussian filter for mildly nonlinear SDEs. Requires differentiable dynamics (JAX autodiff is used). The moment equations for the Gaussian approximation are solved between observations and a Kalman update is applied at each observation.
See EKFConfig for linearisation options and ContinuousTimeConfig
for solver options.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
References:
- For a modern textbook reference, see Chapter 10.7 of: Särkkä, S., & Solin, A. (2019). Applied Stochastic Differential Equations. Cambridge University Press. Available Online.
ContinuousTimeEnKFConfig
dataclass
¶
Bases: EnKFConfig, ContinuousTimeConfig
Continuous-discrete Ensemble Kalman Filter (CD-EnKF).
The default filter for continuous-time models. Each ensemble member is propagated forward by solving the SDE between observations; the ensemble Kalman update is applied at observation times. Works with any SDE model without requiring gradients.
See EnKFConfig for particle/ensemble tuning options and
ContinuousTimeConfig for solver options.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
References:
- The implementation details are due to: Sanz-Alonso, D., Stuart, A. M., & Taeb, A. (2018). Inverse problems and data assimilation. arXiv:1810.06191.
- For a classical reference to the ensemble Kalman filter, see: Evensen, G. (2003). The ensemble Kalman filter: Theoretical formulation and practical implementation. Ocean Dynamics, 53(4), 343-367.
- The solution using automatic differentiation for nonlinear dynamics is due to: Chen, Y., Sanz-Alonso, D., & Willett, R. (2022). Autodifferentiable ensemble Kalman filters. SIAM Journal on Mathematics of Data Science, 4(2), 801-833. Available Online.
ContinuousTimeKFConfig
dataclass
¶
Bases: BaseFilterConfig, ContinuousTimeConfig
Continuous-discrete Kalman Filter (CD-KF).
The exact Bayesian filter for continuous-time linear-Gaussian models.
Use this when your model was built with LTI_continuous. For nonlinear
SDEs, use ContinuousTimeEKFConfig, ContinuousTimeUKFConfig, or
ContinuousTimeEnKFConfig.
Inherits solver options from ContinuousTimeConfig and recording
options from BaseFilterConfig.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
Between observations the mean and covariance evolve via the Kalman–Bucy ODEs:
At each observation the standard Kalman update is applied.
References:
- For a modern textbook reference, see Chapter 10.6 of: Särkkä, S., & Solin, A. (2019). Applied Stochastic Differential Equations. Cambridge University Press. Available Online.
ContinuousTimeUKFConfig
dataclass
¶
Bases: UKFConfig, ContinuousTimeConfig
Continuous-discrete Unscented Kalman Filter (CD-UKF).
Derivative-free Gaussian filter for nonlinear SDEs. Sigma points are propagated through the SDE between observations; the unscented transform is applied at each observation update. More accurate than CD-EKF for strongly nonlinear drifts without requiring Jacobians.
See UKFConfig for sigma-point tuning options and ContinuousTimeConfig
for solver options.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
References:
- For a modern textbook reference, see Section 10.8 of: Särkkä, S., & Solin, A. (2019). Applied Stochastic Differential Equations. Cambridge University Press. Available Online.
EKFConfig
dataclass
¶
Bases: BaseFilterConfig
Extended Kalman Filter (EKF) for discrete-time models.
The EKF linearizes nonlinear dynamics at the current mean estimate via a first-order Taylor expansion. It is fast and simple, but may not work well for strongly nonlinear models. The Taylor series expansion is automatically performed via Jax autodiff.
This is exact (but wasteful) for linear-Gaussian models.
This is the default discrete-time filter when no filter_config is
passed to Filter.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_emission_order |
FilterEmissionOrder
|
Linearisation order for
the observation function. |
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
The EKF propagates a Gaussian approximation \(\mathcal{N}(\hat x_{t|t}, P_{t|t})\) through Jacobian linearizations of \(f\) and \(h\):
where \(F_t\) is the Jacobian of \(f\) at \(\hat x_{t|t-1}\), and proceeds via the typical Kalman update.
References:
- The
cuthbertimplementation of the EKF is based on thetaylor_kfmodule therein. See the cuthbert documentation for more information. - For a more modern textbook reference, see Chapter 7 of: Särkkä, S., & Svensson, L. (2023). Bayesian Filtering and Smoothing (Vol. 17). Cambridge University Press. Available Online.
EnKFConfig
dataclass
¶
Bases: BaseFilterConfig
Ensemble Kalman Filter (EnKF) for discrete-time models.
A good general-purpose filter for nonlinear models. Works with any differentiable or non-differentiable dynamics and scales well to moderate state dimensions. Cheaper per-step than the particle filter, but assumes observations are approximately Gaussian given the ensemble.
The primary tuning knob is n_particles, with more particles providing
more accurate results at the cost of higher compute.
If the ensemble collapses over long trajectories, increase
inflation_delta slightly (e.g. 0.05–0.2).
Attributes:
| Name | Type | Description |
|---|---|---|
n_particles |
int
|
Number of ensemble members. More members give a
better covariance estimate at higher compute cost. Defaults to
|
crn_seed |
Array | None
|
Fixed PRNG key for the ensemble. Defaults
to |
perturb_measurements |
bool | None
|
Add noise to observations before
the ensemble update (stochastic EnKF). Set |
inflation_delta |
float | None
|
Scale ensemble anomalies by
\(\sqrt{1 + \delta}\) before the update to prevent collapse.
|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
The ensemble Kalman filter comprises ensemble members \(x_t^{(i)}, i = 1, \ldots, N_{\text{particles}}\). There are many implementation tricks in the EnKF; we describe the basic version here.
For each time step \(t\), the ensemble is propagated forward by the transition model:
where \(u_t\) is the control input at time \(t\) and \(t_t\) is the time of the transition, and \(\epsilon_t^{(i)} \sim \mathcal{N}(0, Q)\) is the process noise.
Each ensemble member is then updated using observations:
where \(\hat{K}_t^{(i)}\) is the Kalman gain for the \(i\)-th ensemble member, computed as
where \(\hat{P}_t^{(i)}\) is the empirical covariance of the particles, and \(R\) is the covariance of the observation model.
The resulting estimator is known to be biased for non-linear observations, but is often rather robust in practice to moderate nonlinearities. It is particualrly effective for high-dimensional inverse problems, where other particle methods like particle filters often struggle.
References:
- The implementation details are due to: Sanz-Alonso, D., Stuart, A. M., & Taeb, A. (2018).
Inverse problems and data assimilation. [arXiv:1810.06191](https://arxiv.org/abs/1810.06191).
- For a classical reference to the ensemble Kalman filter, see: Evensen, G. (2003).
The ensemble Kalman filter: Theoretical formulation and practical implementation. Ocean Dynamics, 53(4), 343-367.
- The solution using automatic differentiation for nonlinear dynamics is due to: Chen, Y., Sanz-Alonso, D., & Willett, R. (2022).
Autodifferentiable ensemble Kalman filters. SIAM Journal on Mathematics of Data Science, 4(2), 801-833.
[Available Online](https://epubs.siam.org/doi/abs/10.1137/21M1434477).
Filter
dataclass
¶
Bases: BaseLogFactorAdder
Performs Bayesian filtering to compute the filtering distribution \(p(x_t | y_{1:t})\) and the marginal likelihood \(\log p(y_{1:T})\).
A Filter object should be used as a context manager around a call to a model with a dsx.sample(...) statement
to condition a dynamical model on observations via a filtering algorithm. The filter
is selected and dispatched according to the filter_config argument, which adds the
marginal log-likelihood as a NumPyro factor, allowing for downstream parameter inference.
Examples:
>>> def model(obs_times=None, obs_values=None):
... dynamics = DynamicalModel(...)
... return dsx.sample("f", dynamics, obs_times=obs_times, obs_values=obs_values)
>>> def filtered_model(t, y):
... with Filter(filter_config=KFConfig()):
... return model(obs_times=t, obs_values=y)
What this does¶
Filtering is the recursive (potentially approximate) computation of the filtering distribution \(p(x_t \mid y_{1:t})\). It allows for the computation of the marginal likelihood:
which in turn can be used to compute the posterior distribution over the parameters \(p(\theta | y_{1:T})\).
Available Filter Configurations¶
There are several different filters available in dynestyx, each with their own strengths and weaknesses.
What filters are applicable to a given model depends heavily on any special structure of the model (for example, linear and/or Gaussian observations).
For a summary table of all config classes and when to use them, see
Available filter configurations.
Defaults¶
If filter_config=None, defaults are:
ContinuousTimeEnKFConfig()for continuous-time models, andEKFConfig(filter_source="cuthbert")for discrete-time models.
Notes
- If your latent state is discrete (an HMM), you must use
HMMConfig. - What gets recorded to the trace (means/covariances, particles/weights,
etc.) depends on
filter_config.record_*and the backend implementation.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_config |
BaseFilterConfig | None
|
Selects the filtering algorithm and its hyperparameters.
If |
_add_log_factors(name: str, dynamics: DynamicalModel, *, obs_times: jax.Array | None = None, obs_values: jax.Array | None = None, ctrl_times=None, ctrl_values=None, **kwargs)
¶
Add the marginal log likelihood as a numpyro factor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the factor. |
required |
dynamics
|
DynamicalModel
|
Dynamical model to filter. |
required |
obs_times
|
Array | None
|
Observation times. |
None
|
obs_values
|
Array | None
|
Observed values. |
None
|
ctrl_times
|
Control times (optional). |
None
|
|
ctrl_values
|
Control values (optional). |
None
|
HMMConfig
dataclass
¶
Bases: BaseFilterConfig
Exact filter for Hidden Markov Models (finite discrete state space).
Use this when your latent state takes values in a finite set (e.g. a discrete regime model). The forward algorithm computes the exact marginal log-likelihood and filtered belief over states at each time step.
For continuous latent-state models, use any other filter config.
Attributes:
| Name | Type | Description |
|---|---|---|
record_filtered |
bool | None
|
Save the filtered state probabilities
\(p(z_t \mid y_{1:t})\) as a deterministic site. |
record_log_filtered |
bool | None
|
Save the log of the filtered state
probabilities as a deterministic site. |
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
At each step the belief vector \(\pi_t = p(z_t \mid y_{1:t})\) is updated exactly:
The log-likelihood is the sum of the log normalisation constants.
KFConfig
dataclass
¶
Bases: BaseFilterConfig
Kalman Filter (KF) for discrete-time linear-Gaussian models.
The exact Bayesian filter for linear-Gaussian state-space models; requires
a model built with LTI_discrete or using
LinearGaussianStateEvolution + LinearGaussianObservation. For
nonlinear Gaussian models, use EKFConfig, UKFConfig, or EnKFConfig instead.
Attributes:
| Name | Type | Description |
|---|---|---|
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
When the dynamics and observation process of a dynamical system are both linear-Gaussian, the recursive updates can be computed in closed form.
This proceeds via a "prediction" step, where the mean and covariance are propagated forward in time, and an "update" step, where the mean and covariance are updated with the observation.
The prediction step is given by:
The update step is given by:
where \(K_t\) is the Kalman gain.
The Kalman gain is given by:
where \(H\) is the Jacobian of \(h\) at \(\hat x_{t|t-1}\).
There are variants to the particular algorithm; the cuthbert implementation is the so-called "square root" form.
This provides a more numerically stable implementation of the Kalman filter.
References:
- For the classsical reference, see: Kalman, R. E. (1960). A New Approach to Linear Filtering and Prediction Problems. Journal of Basic Engineering, 82(1), 35-45.
- For a more modern textbook reference, see Chapter 6 of: Särkkä, S., & Svensson, L. (2023). Bayesian Filtering and Smoothing (Vol. 17). Cambridge University Press. Available Online.
- For more details on the
cuthbertimplementation, see the cuthbert documentation.
PFConfig
dataclass
¶
Bases: BaseFilterConfig
Bootstrap Particle Filter (PF) for discrete-time models.
The most flexible filter: works with any model, including non-Gaussian observations and highly nonlinear dynamics. The main cost is that accuracy scales with the number of particles, so large state dimensions can become expensive.
The primary tuning knob is n_particles. Estimates will generally get better
and less noisy with more particles, but introduces a linear computational cost.
ess_threshold_ratio controls the frequency of resampling; sampling more frequently
can help avoid particle degeneracy, but also increases variance.
Attributes:
| Name | Type | Description |
|---|---|---|
n_particles |
int
|
Number of particles. More particles give a lower-
variance log-likelihood estimate at linear compute cost. Defaults
to |
resampling_method |
PFResamplingConfig
|
Controls the resampling
algorithm and gradient behaviour. See |
ess_threshold_ratio |
float
|
Resampling fires when the effective
sample size drops below |
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
At each step, particles are propagated through the transition and reweighted by the observation likelihood. The resulting empirical distribution is asymptotically exact to the true filtering distribution as the number of particles goes to infinity. The marginal log-likelihood without a resampling step is estimated as:
where \(\tilde{w}_t^{(i)}\) is the are unnormalized weights of each particle.
There are several different resampling algorithms available, which result in different
approximations of the score function \(\nabla_\theta \log p(y_{1:T} | \theta)\).
For more information on these options, see PFResamplingConfig.
References:
- For a classical reference to particle filters, see: Doucet, A., De Freitas, N., & Gordon, N. (2001). An Introduction to Sequential Monte Carlo Methods. In Sequential Monte Carlo Methods in Practice (pp. 3-14). New York, NY: Springer New York.
- For a more modern textbook, see Chapter 11.4 of: Särkkä, S., & Svensson, L. (2023). Bayesian Filtering and Smoothing (Vol. 17). Cambridge University Press. Available Online.
- For a more recent review of differentiable particle filters, see: Brady, J. J., Cox, B., Li, Y., & Elvira, V. (2025). PyDPF: A Python Package for Differentiable Particle Filtering. arXiv:2510.25693.
PFResamplingConfig
dataclass
¶
Resampling strategy for particle-based filters.
The defaults ("systematic", "stop_gradient") are appropriate for most
workflows. The resampling step includes both a non-differentiable base method,
and a differentiable method for handling gradients.
For most problems, especially with bootstrap particle filters, the stop_gradient method is preferred.
The soft method can be useful when a non-bootstrap PF is used and gradients are required to flow through the resampling step.
The straight_through approach is biased on the backwards pass, and is not recommended, but is okay to use for gradient-free inference.
Attributes:
| Name | Type | Description |
|---|---|---|
base_method |
ResamplingBaseMethod
|
Algorithm used to draw new
particles from the weight distribution. |
differential_method |
ResamplingDifferentiableMethod
|
How gradients
are handled across the discrete resampling step.
|
softness |
float
|
Temperature for soft resampling. Only used when
|
Algorithm Reference
The stop gradient method provides an unbiased score estimate for the marginal likelihood via the classical Fisher estimate. This is accomplished directly through automatic differentiation. For non-bootstrap filters, the proposal estimates will be biased.
The soft resampling method provides biased score estimates, but propagates gradients through the reasmpling step. It is fast.
References:
- For the stop_gradient method, see: Ścibior, A., & Wood, F. (2021).
Differentiable particle filtering without modifying the forward pass. [arXiv:2106.10314](https://arxiv.org/abs/2106.10314).
- For the soft method, see: Karkus, P., Hsu, D., & Lee, W. S. (2018, October). Particle filter networks with application to visual localization.
In Conference on Robot Learning (pp. 169-178). [Available Online](https://proceedings.mlr.press/v87/karkus18a.html).
- For a recent review of differentiable particle filters, see: Brady, J. J., Cox, B., Li, Y., & Elvira, V. (2025).
PyDPF: A Python Package for Differentiable Particle Filtering. [arXiv:2510.25693](https://arxiv.org/abs/2510.25693).
UKFConfig
dataclass
¶
Bases: BaseFilterConfig
Unscented Kalman Filter (UKF) for discrete-time models.
A derivative-free Gaussian filter that handles stronger nonlinearities than the EKF by propagating a small, deterministic set of sigma points through the dynamics. No Jacobians are computed. Slightly more expensive than the EKF but often more accurate on curved manifolds.
The default parameters (alpha, beta, kappa) work well for most
problems; they rarely need to be changed.
Attributes:
| Name | Type | Description |
|---|---|---|
alpha |
float
|
Spread of sigma points around the current mean. Smaller → tighter cluster; larger → sigma points reach further. Defaults to \(\sqrt{3}\). |
beta |
int
|
Encodes prior knowledge about the distribution shape.
|
kappa |
int
|
Secondary scaling parameter. Defaults to |
filter_source |
FilterSource
|
Backend. Defaults to |
Algorithm Reference
For a state of dimension \(n\), \(2n+1\) sigma points are placed as:
Each sigma point is propagated through \(f\) and \(h\); the outputs are recombined with weights depending on \(\alpha, \beta, \kappa\) to recover the predicted mean and covariance.
References: - For the original paper, see: Julier, S. J., & Uhlmann, J. K. (1997). New extension of the Kalman filter to nonlinear systems. SPIE Proceedings, 3068. - For a more modern textbook reference, see Section 8.8 of: Särkkä, S., & Svensson, L. (2023). Bayesian Filtering and Smoothing (Vol. 17). Cambridge University Press. Available Online.
_default_filter_config(dynamics: DynamicalModel)
¶
Return appropriate default filter config when none specified.
_filter_continuous_time(name: str, dynamics: DynamicalModel, filter_config: BaseFilterConfig, key: jax.Array | None = None, *, obs_times: jax.Array, obs_values: jax.Array, ctrl_times=None, ctrl_values=None, **kwargs) -> None
¶
Continuous-time marginal likelihood via CD-Dynamax.
Supports: EnKF, DPF, EKF, UKF (inferred from config type).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the factor. |
required |
dynamics
|
DynamicalModel
|
Dynamical model to filter. |
required |
filter_config
|
BaseFilterConfig
|
Configuration for the filter. |
required |
obs_times
|
Array
|
Observation times. |
required |
obs_values
|
Array
|
Observed values. |
required |
ctrl_times
|
Control times (optional). |
None
|
|
ctrl_values
|
Control values (optional). |
None
|
_filter_discrete_time(name: str, dynamics: DynamicalModel, filter_config: BaseFilterConfig, key: jax.Array | None = None, *, obs_times: jax.Array, obs_values: jax.Array, ctrl_times=None, ctrl_values=None, **kwargs) -> None
¶
Discrete-time marginal likelihood via cuthbert or cd-dynamax.
Filter type inferred from config class: KFConfig, EKFConfig, UKFConfig (cd-dynamax) or EKFConfig (cuthbert), PFConfig (cuthbert).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the factor. |
required |
dynamics
|
DynamicalModel
|
Dynamical model to filter. |
required |
filter_config
|
BaseFilterConfig
|
Configuration for the filter. |
required |
obs_times
|
Array
|
Observation times. |
required |
obs_values
|
Array
|
Observed values. |
required |
ctrl_times
|
Control times (optional). |
None
|
|
ctrl_values
|
Control values (optional). |
None
|