Skip to content

BUG (KS2/2.5/3): get_whitening_matrix normalizes covariance by ceil((Nbatch-1)/nSkipCov) but accumulates floor(..)+1 batches #1046

Description

@cindykrafft

Describe the issue:

preProcess/get_whitening_matrix.m (line 48; identical in v2.0.2, v2.5.2, v3.0.2):

while ibatch<=Nbatch
    ...
    CC = CC + (datr' * datr)/NT;
    ibatch = ibatch + ops.nSkipCov;
end
CC = CC / ceil((Nbatch-1)/ops.nSkipCov);

The loop visits floor((Nbatch-1)/nSkipCov) + 1 batches; the normalizer is ceil((Nbatch-1)/nSkipCov). Whenever nSkipCov divides Nbatch-1 exactly these differ by one, and the covariance is inflated by (m+1)/m with m = (Nbatch-1)/nSkipCov. Since Wrot ~ C^(-1/2), the whitened data are then uniformly scaled by sqrt(m/(m+1)), and every threshold expressed in whitened units (ops.Th, ops.spkTh) becomes effectively sqrt((m+1)/m) harder. With the default nSkipCov = 25:

Nbatch duration @30 kHz covariance effective thresholds
26 ~57 s x2.00 x1.414
51 ~1.9 min x1.50 x1.225
251 ~9.5 min x1.10 x1.049
1651 ~62 min x1.015 x1.008

One in 25 possible batch counts is affected, so adding ~2 s of recording can discontinuously change detection behavior; the bias is material for short recordings and negligible for hour-long ones.

Kilosort 4 already fixed this by counting loop iterations (kilosort/preprocessing.py::get_whitening_matrix, variable k).

Suggested one-line fix (either):

CC = CC / (floor((Nbatch-1)/ops.nSkipCov) + 1);

or count iterations in the loop as KS4 does.

Arithmetic + whitening-scale demonstration: https://github.com/cindykrafft/research-software-audit/blob/main/audits/kilosort/verify/km3_nskipcov.py

Context: found while auditing the Kilosort versions used by 60 papers in six high-impact journals (2021–2026); 41 of them pin KS2/2.5/3.


Generated by Claude Code

Activity

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