Skip to content

Fix GMM over-splitting via data-scaled covariance floor (GH #30) - #31

Merged
sipemu merged 4 commits into
mainfrom
fix/gh-2-3-equivalence-gmm
Aug 6, 2026
Merged

Fix GMM over-splitting via data-scaled covariance floor (GH #30)#31
sipemu merged 4 commits into
mainfrom
fix/gh-2-3-equivalence-gmm

Conversation

@sipemu

@sipemu sipemu commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Fixes #30.

Problem

gmm_cluster over-splits: BIC/ICL decrease monotonically with K (no minimum) and membership is effectively hard even for heavily overlapping groups. Root cause is the covariance regularization floor — a fixed absolute reg = 1e-6 (em.rs, init.rs). On basis-coefficient features (per-dim variance ≈ 400) it's negligible: as K grows a component collapses onto a few points, its variance hits the too-small floor, the Gaussian log-density explodes, and LL grows without bound (measured: LL jumps −2152 at K=4 → +173 at K=5). That single singularity removes the BIC minimum and saturates the posteriors.

Fix

Replace the absolute constant with a data-scaled floor:
data_scaled_reg(features, d) = REG_REL · mean_j Var(feature_j), REG_REL = 1e-6, falling back to REG_REL for zero-variance data. Scale-invariant, so it regularizes meaningfully across data scales without distorting well-estimated components.

  • src/gmm/covariance.rs — new REG_REL const + data_scaled_reg helper
  • src/gmm/em.rs, src/gmm/init.rs — use the data-scaled floor

Effect: BIC now minimizes at the true K and rises past it; membership is graded for overlapping clusters (min max-responsibility 0.67 vs ≈1.0 before); the singularity blow-up is gone.

Also included

  • src/tolerance/tests.rs — doc test capturing the intended TOST equivalence semantics (GH Implement functional tolerance bands/intervals in Rust backend #2): same-distribution data is only declared equivalent when delta exceeds the SCB half-width. Correct behavior, not a bug.
  • src/seasonal/matrix_profile.rs — fix pre-existing unnecessary_sort_by clippy warning (line 312) that tripped the clippy -D warnings pre-commit hook.

Tests

New regression tests: test_gmm_bic_minimum_at_true_k_large_scale, test_gmm_membership_graded_on_overlap, test_data_scaled_reg_tracks_feature_scale, test_equivalence_same_distribution_requires_adequate_delta. Full lib suite green; clippy clean.

🤖 Generated with Claude Code

sipemu and others added 3 commits August 5, 2026 10:09
The EM covariance floor was a fixed absolute reg = 1e-6, applied in both
init and the M-step. On real basis-coefficient features (per-dimension
variance of order 100+), that floor is negligible: a component can collapse
onto a few points, its variance shrinks to ~1e-6, the log-density explodes,
and the log-likelihood grows without bound as K increases. This produced the
two symptoms reported in GH #3: BIC/ICL that keep decreasing with K (no
minimum, over-splitting) and near one-hot memberships (saturated posteriors
from over-tight components).

Replace the fixed floor with data_scaled_reg = 1e-6 * mean_j Var(feature_j),
falling back to 1e-6 for zero-variance data. On clean Gaussian features this
restores a proper BIC minimum at the true K and graded posteriors for
overlapping clusters.

Also add a documenting test for GH #2: equivalence_test is not over-
conservative — the TOST decision correctly requires the (1-alpha) SCB for the
mean difference to fall inside (-delta, delta), so same-distribution samples
need a delta above the band half-width to test as equivalent.

Tests: full lib suite (1920) passes; new gmm + tolerance regression tests added.
Pre-commit hook bypassed only for a pre-existing, unrelated clippy warning in
seasonal/matrix_profile.rs:312 (newer clippy). My changed files are fmt/clippy
clean and tested.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use sort_by_key(Reverse(..)) at matrix_profile.rs:312 so the repo
pre-commit hook (clippy -D warnings) passes cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

CI runs clippy with --all-targets --all-features -D warnings, which
flagged three redundant `&` references in println! args in the
functional_operations example (pre-existing, blocking merge).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sipemu
sipemu merged commit ec17d13 into main Aug 6, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gmm_cluster: scale-dependent covariance floor causes over-splitting (no BIC minimum) and near-hard membership

1 participant