Per pearl_controller_anchors_isv_driven, every controller anchor/target/
cap derives from a tracked signal, not hardcoded constants. The σ-only
revert kept Kendall σ as a free Adam-learned scalar — that violated ISV
discipline and fought Adam's m/√v normalization
(pearl_adam_normalizes_loss_weights).
Single source of truth for both per-horizon controllers:
log_sigma_h[h] ← max(log(0.5), 0.5 * log(loss_ema[h]))
Kendall equilibrium (∂L/∂log σ = 0 ⟹ σ_h² = mean_bce_h)
in closed form. Asymmetric floor at log(0.5) prevents
collapse. No Adam state, no gradient delay.
lambda[h] ← clamp(1.0, 2.0, 1.0 + Z_SCALE_ISV * z_h)
Z_SCALE_ISV = (LAMBDA_CEILING - LAMBDA_FLOOR) / z_max_ema
Adaptive scale auto-uses the full clamp envelope:
the historical-max-z horizon maps exactly to
LAMBDA_CEILING. Replaces hardcoded Z_SCALE=0.5 which
rarely engaged on real data (max observed λ ~1.04).
Both anchor on the same ISV (loss_ema). z_max_ema is a new single-scalar
EMA state tracking max |z| across horizons, with first-obs bootstrap.
Removes:
- opt_log_sigma AdamW optimizer (σ no longer learned)
- grad_log_sigma_h_d memset (BCE kernel writes; output ignored — kept
only to preserve BCE kernel signature)
Kernel signature change (horizon_ema_and_lambda):
+z_max_ema [1] (read+write EMA state)
+log_sigma_h [5] (closed-form output, overwrite)
Discipline:
- First-obs bootstrap (sentinel <= 0) per pearl_first_observation_bootstrap
- Permanent floor (max(real, floor)) per pearl_blend_formulas_must_have_permanent_floor
- Asymmetric clamp per pearl_audit_unboundedness_for_implicit_asymmetry
- Z-score normalisation per pearl_zscore_normalization_for_magnitude_asymmetric_signals
- No nvrtc, no atomicAdd, no host branches in graph capture
All 9 perception_overfit tests pass — including
horizon_ema_and_lambda_track_after_training which validates the kernel
end-to-end through 64 K-loop iterations of capture/replay.
Submit local smoke; cluster A/B vs σ-only baseline (0.7506/0.7519) and
vs Phase 1+2+3 (0.7749/0.7591) follows once the perf-only 3-fold A/B
confirms no regression at b23f8f2ef.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
115 lines
5.2 KiB
Plaintext
115 lines
5.2 KiB
Plaintext
// horizon_lambda.cu — ISV-driven per-horizon gradient scaler AND closed-form Kendall σ.
|
||
//
|
||
// Single source of truth for the two per-horizon controllers:
|
||
//
|
||
// 1) lambda[h] ∈ [LAMBDA_FLOOR, LAMBDA_CEILING] — multiplier on the
|
||
// trunk grad_h contribution in heads_grn_bwd. Boosts horizons
|
||
// that the model is currently failing to learn (per their
|
||
// unweighted BCE EMA).
|
||
//
|
||
// 2) log_sigma_h[h] — Kendall σ for the BCE forward kernel. Computed
|
||
// in closed form from the same loss_ema signal (Kendall's
|
||
// gradient equilibrium ⟹ σ_h = sqrt(mean_bce_h)). Replaces
|
||
// Adam-learned σ, eliminating the m/√v normalization conflict
|
||
// (pearl_adam_normalizes_loss_weights).
|
||
//
|
||
// ISV anchors per `pearl_controller_anchors_isv_driven`: every anchor/
|
||
// target/cap derives from a tracked signal, never from hardcoded
|
||
// constants outside the bootstrap epsilons:
|
||
//
|
||
// loss_ema[h] — EMA(unweighted BCE per horizon)
|
||
// z_max_ema — EMA(max |z_h|) across horizons → drives
|
||
// adaptive Z_SCALE so the OBSERVED-max-z
|
||
// horizon maps exactly to LAMBDA_CEILING.
|
||
// With the prior hardcoded Z_SCALE=0.5 the
|
||
// controller rarely engaged on real data
|
||
// (max observed lambda ~1.04); adaptive
|
||
// Z_SCALE uses the full envelope.
|
||
//
|
||
// Sentinel bootstrap (`prev <= 0`) per
|
||
// `pearl_first_observation_bootstrap.md`; permanent floor
|
||
// (`max(real, floor)`) per `pearl_blend_formulas_must_have_permanent_floor.md`;
|
||
// asymmetric clamp (floor-only on σ, floor + ceiling on λ) per
|
||
// `pearl_audit_unboundedness_for_implicit_asymmetry.md`. Z-score
|
||
// normalization per `pearl_zscore_normalization_for_magnitude_asymmetric_signals.md`.
|
||
|
||
#define N_HORIZONS_LAMBDA 5
|
||
#define ALPHA_FIXED 0.1f
|
||
#define LAMBDA_FLOOR 1.0f
|
||
#define LAMBDA_CEILING 2.0f
|
||
#define LOG_SIGMA_FLOOR (-0.6931472f) // log(0.5) — σ never collapses below 0.5
|
||
#define Z_MAX_FLOOR 0.1f // guards Z_SCALE_ISV when z_max_ema is tiny
|
||
|
||
extern "C" __global__ void horizon_ema_and_lambda(
|
||
const float* __restrict__ loss_per_horizon, // [5] — current step UNWEIGHTED BCE
|
||
float* __restrict__ loss_ema, // [5] — EMA state (read + write)
|
||
float* __restrict__ z_max_ema, // [1] — EMA(max|z|) state (read + write)
|
||
float* __restrict__ lambda, // [5] — output: λ_h
|
||
float* __restrict__ log_sigma_h // [5] — output: closed-form Kendall σ
|
||
) {
|
||
if (threadIdx.x != 0 || blockIdx.x != 0) return;
|
||
|
||
// -------- 1) EMA update on loss_per_horizon, with first-obs bootstrap.
|
||
float new_ema[N_HORIZONS_LAMBDA];
|
||
float sum = 0.0f;
|
||
#pragma unroll
|
||
for (int h = 0; h < N_HORIZONS_LAMBDA; ++h) {
|
||
const float cur = loss_per_horizon[h];
|
||
const float prev = loss_ema[h];
|
||
new_ema[h] = (prev <= 0.0f) ? cur : (prev + ALPHA_FIXED * (cur - prev));
|
||
loss_ema[h] = new_ema[h];
|
||
sum += new_ema[h];
|
||
}
|
||
const float mean = sum / (float)N_HORIZONS_LAMBDA;
|
||
|
||
// -------- 2) Z-score normalize across horizons.
|
||
float ssq = 0.0f;
|
||
#pragma unroll
|
||
for (int h = 0; h < N_HORIZONS_LAMBDA; ++h) {
|
||
const float diff = new_ema[h] - mean;
|
||
ssq += diff * diff;
|
||
}
|
||
const float std = sqrtf(ssq / (float)N_HORIZONS_LAMBDA + 1e-12f);
|
||
const float inv_std = (std > 1e-6f) ? (1.0f / std) : 0.0f;
|
||
|
||
float z[N_HORIZONS_LAMBDA];
|
||
float z_max = 0.0f;
|
||
#pragma unroll
|
||
for (int h = 0; h < N_HORIZONS_LAMBDA; ++h) {
|
||
z[h] = (new_ema[h] - mean) * inv_std;
|
||
const float az = fabsf(z[h]);
|
||
if (az > z_max) z_max = az;
|
||
}
|
||
|
||
// -------- 3) z_max_ema: tracks the typical spread, drives adaptive Z_SCALE.
|
||
// Sentinel = 0 ⇒ first-obs bootstrap. Fixed α matches loss_ema's
|
||
// smoothing horizon.
|
||
const float prev_zmax = z_max_ema[0];
|
||
const float new_zmax = (prev_zmax <= 0.0f)
|
||
? z_max
|
||
: (prev_zmax + ALPHA_FIXED * (z_max - prev_zmax));
|
||
z_max_ema[0] = new_zmax;
|
||
|
||
// -------- 4) Adaptive Z_SCALE: maps the historical-max-z to LAMBDA_CEILING.
|
||
// When z_max_ema is large (spread regime), Z_SCALE_ISV shrinks
|
||
// to avoid saturating early; when small (tight regime), it
|
||
// grows to amplify the controller into engagement.
|
||
const float z_anchor = fmaxf(new_zmax, Z_MAX_FLOOR);
|
||
const float z_scale_isv = (LAMBDA_CEILING - LAMBDA_FLOOR) / z_anchor;
|
||
|
||
// -------- 5) Per-horizon outputs.
|
||
#pragma unroll
|
||
for (int h = 0; h < N_HORIZONS_LAMBDA; ++h) {
|
||
// λ_h: boost-only, asymmetric clamped.
|
||
const float raw_lambda = 1.0f + z_scale_isv * z[h];
|
||
lambda[h] = fmaxf(LAMBDA_FLOOR, fminf(LAMBDA_CEILING, raw_lambda));
|
||
|
||
// log σ_h: Kendall equilibrium from the same loss_ema signal.
|
||
// ∂L/∂log σ = 0 ⟹ σ_h² = mean_bce_h ⟹ log σ_h = ½·log(loss_ema_h).
|
||
// Floor at log(0.5) so σ can't collapse to 0 (which would explode w_h).
|
||
const float ema_h = fmaxf(new_ema[h], 1e-12f);
|
||
const float raw_log_sigma = 0.5f * logf(ema_h);
|
||
log_sigma_h[h] = fmaxf(LOG_SIGMA_FLOOR, raw_log_sigma);
|
||
}
|
||
}
|