Skip to content

Learning

kalman_py.learning.fit_noise

fit_noise(
    F: ArrayLike,
    H: ArrayLike,
    zs: ArrayLike,
    x0: ArrayLike,
    P0: ArrayLike,
    *,
    Q0: ArrayLike | None = None,
    R0: ArrayLike | None = None,
    estimate: Collection[str] = ("Q", "R"),
    method: Method = "auto",
    max_iter: int | None = None,
    tol: float | None = None,
) -> NoiseFit

Estimate Q and/or R of x_k = F x_{k-1} + w, z_k = H x_k + v by maximum likelihood, with (x0, P0) the prior before the first prediction (as in KalmanFilter).

method="gradient" maximizes the exact log-likelihood with BFGS, differentiating through the JAX filter (needs JAX; enable jax_enable_x64 for float64 accuracy). Q and R are parameterized by Cholesky factors with log-diagonals, so they stay positive-definite. The likelihood is often flat and badly conditioned (e.g. a full Q from position-only data), where BFGS line searches stall; it is restarted from where it stopped until the gradient of the per-step average log-likelihood is below tol (default 1e-6) or progress stops. max_iter (default 1000) caps the BFGS iterations of each run.

method="em" is expectation-maximization (Shumway & Stoffer) on the NumPy backend: each iteration runs the filter and RTS smoother, then updates Q and R in closed form. It never decreases the likelihood and needs no JAX, but on such flat likelihoods it converges very slowly. It stops when an iteration improves the log-likelihood by less than tol * max(1, |log-likelihood|) (default 1e-8) or after max_iter (default 200).

method="auto" uses the gradient method when JAX is installed, EM otherwise.

Q0 and R0 are starting values (identity by default, like pykalman); covariances not listed in estimate stay fixed at them.

kalman_py.learning.NoiseFit dataclass

NoiseFit(
    Q: Array,
    R: Array,
    log_likelihood: float,
    n_iter: int,
    converged: bool,
    history: Array,
)

Fitted noise covariances and how the fit went.