diff --git a/config/training/dqn-localdev.toml b/config/training/dqn-localdev.toml index db55d4fb8..66d371bc1 100644 --- a/config/training/dqn-localdev.toml +++ b/config/training/dqn-localdev.toml @@ -32,7 +32,7 @@ buffer_size = 10000 min_replay_size = 100 [early_stopping] -enabled = false +enabled = true patience = 20 min_epochs_before_stopping = 50 diff --git a/crates/ml-dqn/src/dqn.rs b/crates/ml-dqn/src/dqn.rs index 7bb733ee1..c65f42948 100644 --- a/crates/ml-dqn/src/dqn.rs +++ b/crates/ml-dqn/src/dqn.rs @@ -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, } diff --git a/crates/ml/src/hyperopt/adapters/dqn.rs b/crates/ml/src/hyperopt/adapters/dqn.rs index 1da62578f..3fa675340 100644 --- a/crates/ml/src/hyperopt/adapters/dqn.rs +++ b/crates/ml/src/hyperopt/adapters/dqn.rs @@ -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) diff --git a/crates/ml/src/trainers/dqn/config.rs b/crates/ml/src/trainers/dqn/config.rs index 9aa944073..dee50c302 100644 --- a/crates/ml/src/trainers/dqn/config.rs +++ b/crates/ml/src/trainers/dqn/config.rs @@ -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() } }