Skip to content

[BUG] Incorrect summary statistics in LinearGaussianConjugateSSM.fit_blocked_gibbs #416

Closed

Description

@hylkedonker

There is a slight mistake in the Gibbs sampling step of the dynamics parameters of the LinearGaussianConjugateSSM model.

Briefly, defining the dynamics parameters as $W_{z} \equiv [F, B, b]^\intercal $, for this model the prior is given by:

$$Q, W_{z} \sim \mathcal{MN}\mathcal{W}^{-1} (M_{z0}, V_{z0}, \nu_{q0}, \psi_{q0})$$

and states are subsequently sampled according to

$$\begin{aligned} z^{(i)}_t \sim \mathcal{N}(F z^{(i)}_{t-1} + B u^{(i)}_t + b, Q) \equiv \mathcal{N}(W_{z} x^{(i)}_{zt}, Q)\\\ \end{aligned}$$

where we defined $x^{(i)}_{zt} = [z^{(i)}_{t-1}, u^{(i)}_t, 1]^\intercal$. Using the conjugacy of the matrix normal inverse-Wishart distribution, the dynamics parameters and variances, $Q, W_{z} \sim \mathcal{MN}\mathcal{W}^{-1} (M_{z}, V_{z}, \nu_{q}, \psi_{q})$, given the states are derived from the summary statistics:

$$\begin{aligned} S_{z}^{xx} = V_{z0} + \sum_{i=1}^{m} \sum_{t=2}^T x^{(i)}_{zt} {x^{(i)}_{zt}}^\intercal\\\ S_{z}^{yy} = M_{z0} V_{z0} M_{z0}^\intercal + \sum_{i=1}^{m} \sum_{t=2}^T z^{(i)}_{t} {z^{(i)}_{t}}^\intercal\\\ S_{z}^{yx} = M_{z0} V_{z0} + \sum_{i=1}^{m} \sum_{t=2}^Tz^{(i)}_{t} {x^{(i)}_{t}}^\intercal \\\ S_{z}^{y|x} = S_{z}^{yx} - S_{z}^{yx} (S_{z}^{xx})^{-1} {S_{z}^{yx}}^\intercal \end{aligned}$$

However, in the code the summary statistics are calculated based on $[z^{(i)}_{t}, u^{(i)}_t, 1]^\intercal $ instead of $x^{(i)}_{zt} = [z^{(i)}_{t-1}, u^{(i)}_t, 1]^\intercal $.
I had already corrected this mistake in PR #403. But if you want, I can make a separate PR with just this fix instead.

Kind regards,

Hylke

Activity

  1. nkbranigan commented on Aug 26, 2026

    @nkbranigan
    Collaborator

    Hi @hylkedonker, thank you for finding this! I agree that this is a bug, and in my opinion a separate PR would be helpful to expedite getting this fixed. Let me know if you’re still interested in working on that, or I’m happy to give it a go.

    Also, it looks to me like this bug extends beyond LinearGaussianConjugateSSM.fit_blocked_gibbs to a lot of continuous state inference. (I would check: linear_gaussian_ssm/inference.py, linear_gaussian_ssm/parallel_inference.py, linear_gaussian_ssm/info_inference.py, linear_gaussian_ssm/models.py, nonlinear_gaussian_ssm/inference_ekf.py, nonlinear_gaussian_ssm/inference_ukf.py, generalized_gaussian_ssm/inference.py, slds/inference.py.)

  2. hylkedonker commented on Aug 31, 2026

    @hylkedonker
    Author

    Unfortunately, I currently have little additional time on my hands to make a separate PR.
    So, feel free to give it a go! ;-)

  3. nkbranigan commented on Sep 1, 2026

    @nkbranigan
    Collaborator

    Sounds good, and will do!

  4. PeerAhammad commented on Oct 2, 2026

    @PeerAhammad

    Hi, I’d like to work on this issue.

    While investigating, I noticed that the input timing convention is not consistent across the LinearGaussianSSM code paths: sample uses the input associated with the transition into (z_t), while the filter/smoother, EM M-step, and Gibbs statistics currently use a different indexing convention.

    Since changing only the Gibbs statistics could leave the Gibbs sampler internally inconsistent, I’m thinking of first aligning the relevant linear-Gaussian inference paths and adding a consistency regression test, rather than making an isolated one-line change.

    I also noticed the overlap with PR #403. Before I start implementing, could you confirm whether this broader scope is appropriate for #416, and whether anyone is currently working on this issue?

    Thanks!

  5. nkbranigan commented on Oct 3, 2026

    @nkbranigan
    Collaborator

    Hi @PeerAhammad, thank you for investigating! I’ve been working on #466, almost complete, that I believe fixes the issues you’ve found, as well as some related ones. Please let me know if I’ve missed any of your concerns!

  6. PeerAhammad commented on Oct 3, 2026

    @PeerAhammad

    Thanks @nkbranigan, #466 appears to cover everything I found, so I'll hold off on a separate PR. I independently reproduced the input-timing mismatch in the linear Gaussian filters, EM, and Gibbs statistics, and I have a dense joint-Gaussian reference test (filter log-likelihood and smoothed means against sample's convention), along with EM/Gibbs recovery tests for the input weights. Happy to contribute these to #466 or run them against your branch if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions