Losses

One module per objective, named after the task it trains. Three families live here: tempo as a number (regression) or a distribution over bins (classification), and the frame-level beat objectives — beat alone, or beat plus bar position.

The two bar-position losses differ in how they model position: beat_phase_loss() uses two independent sigmoids (one/last), which never asks the discriminative “1 or 3?” question, and beat_position_loss() replaces them with a softmax over all G positions. The latter is what the project trains with; the former is kept so existing checkpoints stay readable.

The three modules that are not losses themselves hold the knobs both beat objectives share: which frames the position term is supervised on (phase_conditioning), how the beat term’s positive class is weighted (pos_weight), and how much timing error the beat term forgives (shift_tolerance).

All three are coupled, and in a chain. Conditioning on beats removes most of the imbalance pos_weight exists to correct. Shift tolerance then replaces the target smearing that defines where “a beat” is at all, which changes the gate phase_conditioning builds and the imbalance pos_weight measures — a sharp target cuts the positive mass ~3.75x, and the ignore band removes negatives that the weight would otherwise count. Change one and re-read the other two.

tempo_regression

Regression losses on a single BPM value per clip.

tempo_classification

Tempo-as-classification: a softmax over BPM bins with a Gaussian soft target.

beat_only

Beat detection alone, with no bar-position term.

beat_phase

Bar position as two independent binary detectors (one and last).

beat_position

Bar position as a softmax over the G positions in a bar.

phase_conditioning

Which frames the bar-position terms are supervised on.

pos_weight

Positive-class weighting for the frame-wise beat BCE term.

shift_tolerance

Forgiving the beat head a few frames of timing error.