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>
This commit is contained in:
jgrusewski
2026-03-29 17:22:16 +02:00
parent 948ffa7c67
commit e9e2e87a64
4 changed files with 11 additions and 7 deletions

View File

@@ -32,7 +32,7 @@ buffer_size = 10000
min_replay_size = 100
[early_stopping]
enabled = false
enabled = true
patience = 20
min_epochs_before_stopping = 50

View File

@@ -325,7 +325,7 @@ impl Default for DQNConfig {
// Agent-level trading parameters
minimum_profit_factor: 1.5, // BUG #7 FIX: 50% margin above breakeven
weight_decay: 1e-4, // WAVE 30: Standard L2 regularization strength
adam_epsilon: 1e-3, // BF16-safe: bf16(1e-8)=0
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
dropout_rate: 0.0, // Disabled by default; hyperopt wires from dropout_initial
// Mixed precision: disabled by default (auto-detected at runtime)
@@ -610,7 +610,7 @@ impl DQNConfig {
minimum_profit_factor: 1.5,
weight_decay: 1e-4,
adam_epsilon: 1e-3, // BF16-safe: bf16(1e-8)=0
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
..Default::default()
}
@@ -677,7 +677,7 @@ impl DQNConfig {
minimum_profit_factor: 2.0, // Higher safety margin for conservative config
weight_decay: 1e-4,
adam_epsilon: 1e-3, // BF16-safe: bf16(1e-8)=0
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
..Default::default()
}
@@ -769,7 +769,7 @@ impl DQNConfig {
minimum_profit_factor: 1.5,
weight_decay: 1e-4,
adam_epsilon: 1e-3, // BF16-safe: bf16(1e-8)=0
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
dropout_rate: 0.0,
}

View File

@@ -2700,6 +2700,10 @@ impl HyperparameterOptimizable for DQNTrainer {
// medium GPUs (16-24GB) where optimal_n_episodes might not kick in.
gpu_n_episodes: if budget.gpu_memory_mb >= 40960 { 512 } else { 128 },
gpu_timesteps_per_episode: 500,
// Cap steps/epoch by GPU tier: RTX 3050 = fast iteration, H100 = full quality.
// Without this, the default (0=unlimited) trains on the entire dataset per epoch,
// making each hyperopt trial ~10min on RTX 3050 instead of ~30s.
max_training_steps_per_epoch: if budget.gpu_memory_mb >= 40960 { 2000 } else { 200 },
avg_spread: 0.0001,
// GPU-dynamic network sizing (from hyperopt search space)

View File

@@ -1503,7 +1503,7 @@ impl DQNHyperparameters {
// WAVE 30: L2 Weight Decay
weight_decay: 1e-4, // Default: 0.0001 (standard regularization strength)
adam_epsilon: 1e-3, // BF16-safe
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
// Conservative Q-Learning (CQL)
cql_alpha: 0.1, // Default: mild conservatism (0.1 of 0.0-1.0 range)
@@ -1713,7 +1713,7 @@ pub(crate) fn dqn_default_config() -> DQNConfig {
minimum_profit_factor: 1.5,
weight_decay: 1e-4,
adam_epsilon: 1e-3, // BF16-safe
adam_epsilon: 1e-8, // f32 Adam (master weights are f32)
..Default::default()
}
}