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.