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:
@@ -32,7 +32,7 @@ buffer_size = 10000
|
||||
min_replay_size = 100
|
||||
|
||||
[early_stopping]
|
||||
enabled = false
|
||||
enabled = true
|
||||
patience = 20
|
||||
min_epochs_before_stopping = 50
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user