Commit Graph

4 Commits

Author SHA1 Message Date
jgrusewski
332b3eb120 feat(training): cosine LR decay in TOML profile, min_epochs_before_stopping=80
- Added lr_decay_type (0=constant, 1=linear, 2=cosine) and lr_min to
  the TOML training profile system. Wired through apply_to() with
  total_steps derived from epochs.

- dqn-localdev.toml: lr_decay_type=2 (cosine 1e-4→1e-5 over 200 epochs),
  min_epochs_before_stopping=80 (was 50, gives model more room to recover
  after C51 transition).

- Smoketest config unchanged (lr_decay_type not set → default Constant).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:16:47 +02:00
jgrusewski
f6caf61252 fix(training): 4 metric quality fixes — buffer, episodes, hyperopt, Q-stats
1. Localdev config: gpu_n_episodes 32→64, gpu_timesteps 100→200
   (12,800 exp/epoch, 4x more → stable Sharpe estimation)

2. Localdev config: buffer_size 10K→50K, min_replay_size 100→500
   (fills over ~4 epochs instead of <1, reduces overfitting)

3. Hyperopt: added CampaignConfig::dqn_localdev() (10 trials × 20 epochs),
   updated test_local_hyperopt to use it with env var overrides
   (FOXHUNT_HYPEROPT_TRIALS, FOXHUNT_HYPEROPT_EPOCHS)

4. Q-value range: was [X,X] every epoch because:
   - train_step.rs Q-stats code was DEAD (training loop uses
     fused.run_full_step() directly, not self.train_step())
   - Only sampled 10 experiences for Q-stats (tiny batch → tight range)
   Fix: reduce_current_q_stats() reads the training batch's q_out_buf
   directly (64 samples, no extra forward pass), wired into the training
   loop's inner step. q_stats_kernel.cu converted to f32 arithmetic.
   Now shows real variation: [-5.25, 5.03] instead of [2.80, 2.80]

Removed dead Q-estimation code from train_step.rs (was never reached
in the fused GPU training path).

11/11 smoke tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:06:09 +02:00
jgrusewski
e9e2e87a64 fix(hyperopt): max_steps_per_epoch by GPU tier, adam_epsilon 1e-3→1e-8
- Hyperopt adapter now sets max_training_steps_per_epoch:
  RTX 3050 (≤40GB) = 200 steps, H100 (≥40GB) = 2000 steps.
  Without this, each trial trained the full dataset (2917 steps/epoch)
  making hyperopt 11x slower than necessary on local GPU.

- adam_epsilon default 1e-3→1e-8 everywhere (conservative(), DQNConfig).
  The old 1e-3 was a BF16 workaround (bf16(1e-8)=0 → div-by-zero).
  Adam is now f32, so standard 1e-8 is correct.

- Early stopping enabled in dqn-localdev.toml (patience=20).

Hyperopt: 2 trials × 5 epochs in 132s (was ~20min). Zero NaN.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 17:22:16 +02:00
jgrusewski
948ffa7c67 fix(monitoring): f32 epoch accumulators, per-branch diversity, remove dead kernels
- acc_buf bf16→f32: epoch gradient/loss accumulators were bf16, causing
  avg_grad to be quantized to 0.895 every epoch. Now f32, shows real
  variation (0.776→0.783→0.788).

- EPOCH_DIAG warn!→info!: diagnostic logging, not a warning condition.

- Removed legacy training_guard_check + training_guard_accumulate kernels
  (dead code, replaced by fused training_guard_check_and_accumulate).

- Added dqn-localdev.toml: 200-epoch RTX 3050 profile for extended runs.

200-epoch run completed successfully:
  Best Sharpe: +6.43 at epoch 107
  Final: Sharpe=+2.05, PF=1.35, Return=+1052%, 0 NaN

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:49:38 +02:00