$$ % Define your custom commands here \newcommand{\bmat}[1]{\begin{bmatrix}#1\end{bmatrix}} \newcommand{\E}{\mathbb{E}} \newcommand{\P}{\mathbb{P}} \newcommand{\S}{\mathbb{S}} \newcommand{\R}{\mathbb{R}} \newcommand{\S}{\mathbb{S}} \newcommand{\norm}[2]{\|{#1}\|_{{}_{#2}}} \newcommand{\pd}[2]{\frac{\partial #1}{\partial #2}} \newcommand{\pdd}[2]{\frac{\partial^2 #1}{\partial #2^2}} \newcommand{\vectornorm}[1]{\left|\left|#1\right|\right|} \newcommand{\abs}[1]{\left|{#1}\right|} \newcommand{\mbf}[1]{\mathbf{#1}} \newcommand{\mc}[1]{\mathcal{#1}} \newcommand{\bm}[1]{\boldsymbol{#1}} \newcommand{\nicefrac}[2]{{}^{#1}\!/_{\!#2}} \newcommand{\argmin}{\operatorname*{arg\,min}} \newcommand{\argmax}{\operatorname*{arg\,max}} \newcommand{\dd}{\operatorname{d}\!} $$

filters.common

filters.common

Shared filter types and numerical helpers.

The filters in this package are deliberately generic: they know about a transition function, an observation matrix, and covariances, and nothing about body weight. The model-specific wiring lives in wdm.estimation. This separation is what lets the same unscented filter be tested against a linear system with a known closed-form answer, which is the only honest way to be confident it works.

Classes

Name Description
FilterResult Output of a forward filtering pass.
GaussianState A Gaussian belief over the state.
SmootherResult Output of a Rauch-Tung-Striebel backward pass.

FilterResult

filters.common.FilterResult()

Output of a forward filtering pass.

Attributes

Name Type Description
filtered_mean, filtered_cov Belief at each step after incorporating that step’s observation.
predicted_mean, predicted_cov Belief at each step before the observation. Needed by the RTS smoother and for honest one-step-ahead diagnostics.
loglik Float[Array, ''] Marginal log-likelihood of the observed data, accumulated via the prediction-error decomposition. This is the objective that parameter estimation maximizes, so its correctness is load-bearing.
innovation, innovation_var One-step-ahead residuals and their predicted variances. Standardised innovations should be white and unit-variance if the model is adequate; they are the primary diagnostic and the first place a misspecified noise model shows up.
observed Float[Array, ' t'] Mask of which steps carried an observation.

GaussianState

filters.common.GaussianState()

A Gaussian belief over the state.

SmootherResult

filters.common.SmootherResult()

Output of a Rauch-Tung-Striebel backward pass.

The smoothed estimate at time k conditions on the entire record, past and future. For reviewing history this is strictly the right thing to look at: today’s weigh-in genuinely does tell you something about last Tuesday’s true trend. For deciding what to eat tomorrow, only the filtered estimate at the final step is available, since the future has not happened yet.

Functions

Name Description
gaussian_loglik Log density of a scalar Gaussian residual.
innovation_loglik Log density of a scalar innovation: Student-t with squared scale scale2.
joseph_update Joseph-form covariance update.
safe_cholesky Lower-triangular Cholesky factor, with symmetrization and jitter.
symmetrise Force exact symmetry.

gaussian_loglik

filters.common.gaussian_loglik(residual, variance)

Log density of a scalar Gaussian residual.

innovation_loglik

filters.common.innovation_loglik(residual, scale2, dof)

Log density of a scalar innovation: Student-t with squared scale scale2.

dof=None gives the Gaussian with variance scale2. Otherwise the innovation is treated as Student-t with the predicted innovation variance as its squared scale, the same approximation the measurement update makes (see wdm.models.observation.student_t_inflation).

joseph_update

filters.common.joseph_update(p, k, h, r)

Joseph-form covariance update.

\[ P^+ = (I - KH) P (I - KH)^\top + K R K^\top \]

Algebraically identical to the shorter \((I - KH)P\), but it stays positive semi-definite under round-off because it is manifestly a sum of two positive semi-definite terms. Over a few hundred steps the short form can accumulate enough error to produce a negative variance, which then poisons everything downstream. The extra matrix product is worth it.

safe_cholesky

filters.common.safe_cholesky(p, jitter=JITTER)

Lower-triangular Cholesky factor, with symmetrization and jitter.

symmetrise

filters.common.symmetrise(p)

Force exact symmetry.

Covariance updates are symmetric in exact arithmetic but drift in floating point, and an asymmetric matrix will eventually fail Cholesky in a way whose error message points nowhere useful. Cheap insurance, applied after every covariance update.