refactor(A2): production α=0.1, tests opt in to α=0.3 via with_alpha()

LearningHealth::new() now uses α=0.1 (the production-appropriate ~10-sample
EMA window for 80-100 epoch runs). Tests that need to reach threshold
assertions inside a 5-iteration loop (warmup=3 + 2 EMA steps) use
LearningHealth::with_alpha(0.3) instead of bending production behaviour
to satisfy test convenience.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-04-20 21:38:53 +02:00
parent b05036ab93
commit 5bc712478e

View File

@@ -86,12 +86,22 @@ pub struct LearningHealth {
}
impl LearningHealth {
/// Production constructor. α=0.1 gives ~10-sample EMA window — appropriate
/// smoothing for an 80100 epoch training run where we want health to be
/// responsive but not whipsaw on single-epoch noise.
pub fn new() -> Self {
Self::with_alpha(0.1)
}
/// Test/tuning constructor with an explicit α. Tests use higher α (≈0.3)
/// to satisfy threshold assertions inside a 5-iteration (warmup + 2 EMA
/// steps) test loop; production code should use `new()`.
pub fn with_alpha(alpha: f32) -> Self {
Self {
value: 0.5, // neutral start
epoch: 0,
components: NormalizedComponents::default(),
ema_alpha: 0.3,
ema_alpha: alpha,
warmup_epochs: 3,
}
}
@@ -144,7 +154,9 @@ mod tests {
grad_consistency: -0.3, // gradients contradict
spectral_gap: 50.0, // rank 1
};
let mut health = LearningHealth::new();
// Tests use α=0.3 to reach thresholds inside the short 5-iteration loop;
// production new() uses α=0.1.
let mut health = LearningHealth::with_alpha(0.3);
// Skip warmup
for _ in 0..5 { health.update(&raw); }
assert!(health.value <= 0.3, "Collapsed state should give health <= 0.3, got {}", health.value);
@@ -161,7 +173,7 @@ mod tests {
grad_consistency: 0.9, // consistent direction
spectral_gap: 1.5, // balanced rank
};
let mut health = LearningHealth::new();
let mut health = LearningHealth::with_alpha(0.3);
for _ in 0..5 { health.update(&raw); }
assert!(health.value >= 0.7, "Healthy state should give health >= 0.7, got {}", health.value);
}
@@ -173,7 +185,7 @@ mod tests {
grad_norm: 50_000.0, ens_disagreement: 0.0,
grad_consistency: -0.5, spectral_gap: 100.0,
};
let mut health = LearningHealth::new();
let mut health = LearningHealth::with_alpha(0.3);
// First 3 updates are warmup — should stay at 0.5
for _ in 0..3 {
let v = health.update(&raw);