Skip to content

Metrics & Diagnostics

kalbee provides standard filter performance metrics for evaluating estimation quality and filter consistency.

Available Metrics

RMSE — Root Mean Square Error

Measures how far estimates are from the truth:

\[\text{RMSE} = \sqrt{\frac{1}{T} \sum_{k=1}^{T} (x_k - \hat{x}_k)^2}\]
from kalbee import rmse
import numpy as np

estimated = np.array([1.1, 2.0, 3.2, 3.9, 5.1])
truth = np.array([1.0, 2.0, 3.0, 4.0, 5.0])

print(f"RMSE: {rmse(estimated, truth):.4f}")

NEES — Normalized Estimation Error Squared

Tests filter consistency. For a well-tuned filter, the average NEES should be approximately equal to the state dimension \(n\):

\[\text{NEES}_k = (x_k - \hat{x}_k)^T P_k^{-1} (x_k - \hat{x}_k)\]
from kalbee import nees
import numpy as np

# Simulate consistent errors
state_errors = [np.array([[0.1], [0.05]]) for _ in range(100)]
covariances = [np.eye(2) * 0.1 for _ in range(100)]

nees_values = nees(state_errors, covariances)
print(f"Average NEES: {np.mean(nees_values):.2f}  (should be ≈ 2)")

NIS — Normalized Innovation Squared

Tests measurement consistency. Average NIS should be ≈ measurement dimension \(m\):

\[\text{NIS}_k = v_k^T S_k^{-1} v_k\]
from kalbee import nis

innovations = [np.array([[0.5]]), np.array([[0.3]]), np.array([[-0.2]])]
S_matrices = [np.array([[1.0]])] * 3

nis_values = nis(innovations, S_matrices)
print(f"NIS values: {nis_values}")

Log-Likelihood

For model comparison — higher is better:

\[\mathcal{L} = -\frac{1}{2} \sum_k \left[ m \log(2\pi) + \log|S_k| + v_k^T S_k^{-1} v_k \right]\]
from kalbee import log_likelihood

ll = log_likelihood(innovations, S_matrices)
print(f"Log-likelihood: {ll:.4f}")

Using with Experiments

from kalbee import run_experiment

report = run_experiment(
    signal="sine",
    filters=["kf", "ekf", "ukf"],
    noise_std=0.5,
    seed=42,
)

# Each result has built-in metrics
for result in report.results:
    print(f"{result.filter_name}: "
          f"RMSE={result.position_rmse():.4f}  "
          f"NEES={result.average_nees():.2f}")