Files
foxhunt/docs/codebase-cleanup/wave26_p1.6_adaptive_dropout_report.md
jgrusewski 2df1ea92e1 feat(ml): WAVE 29 DQN Codebase Cleanup & Refactoring Campaign
BREAKING CHANGES:
- Removed orphaned dqn.rs monolithic trainer (4,975 lines)
- Removed orphaned dqn_ensemble.rs module (816 lines)
- Removed orphaned tft.rs and tft_complete_int8_integration_test.rs
- TFT trainer split into modular directory structure

DQN Module Refactoring:
- Split trainers/dqn.rs into modular structure (config.rs, statistics.rs, trainer.rs)
- Fixed hyperopt 39D search space (continuous params only)
- Boolean flags (use_dueling, use_double_dqn, use_per, use_noisy_nets) are now FIXED architectural decisions
- use_distributional defaults to false (Candle BUG #36 - scatter_add gradient issues)

Clean Module Structure:
- ml/src/trainers/dqn/ directory with proper mod.rs exports
- ml/src/trainers/tft/ directory with config.rs, types.rs, model.rs, trainer.rs, tests.rs
- All P0 features validated: TD-error clamping, batch diversity, LR scheduler, priority staleness

Documentation:
- Added comprehensive docs in docs/codebase-cleanup/
- ADR-001 for DQN refactoring decisions
- Rainbow DQN component matrix and quick reference guides

Build Status: Compiles with zero errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 23:46:13 +01:00

6.2 KiB

Wave 26 P1.6: Adaptive Dropout Scheduler Implementation

Summary

Implemented adaptive dropout scheduling that linearly decreases dropout rate from an initial high value to a final low value over a specified number of training steps. High dropout early in training prevents overfitting, while low dropout late allows fine-tuning.

Implementation Details

1. DropoutScheduler Struct

Location: /home/jgrusewski/Work/foxhunt/ml/src/dqn/network.rs (lines 13-58)

pub struct DropoutScheduler {
    initial_rate: f64,
    final_rate: f64,
    decay_steps: usize,
    current_step: usize,
}

Key Methods:

  • new(initial_rate, final_rate, decay_steps) - Creates scheduler
  • get_rate() - Returns current dropout rate using linear interpolation
  • step(steps) - Advances scheduler by N steps
  • current_step() - Returns current step count

Formula:

progress = min(current_step / decay_steps, 1.0)
rate = initial_rate * (1 - progress) + final_rate * progress

2. QNetworkConfig Extension

Location: /home/jgrusewski/Work/foxhunt/ml/src/dqn/network.rs (lines 60-93)

New Field:

pub dropout_schedule: Option<(f64, f64, usize)>  // (initial, final, decay_steps)
  • None - Uses static dropout_prob (existing behavior)
  • Some((0.5, 0.1, 100000)) - Adaptive dropout from 0.5 → 0.1 over 100k steps

3. QNetwork Integration

Changes:

  1. Added scheduler field (line 132):

    dropout_scheduler: std::sync::Mutex<Option<DropoutScheduler>>
    
  2. Initialize scheduler in constructor (lines 229-235):

    let dropout_scheduler = if let Some((initial, final_rate, steps)) = config.dropout_schedule {
        Some(DropoutScheduler::new(initial, final_rate, steps))
    } else {
        None
    };
    
  3. Updated forward pass (lines 258-259):

    let dropout_rate = self.get_dropout_rate();
    let layers = NetworkLayers::new_with_dropout_rate(&var_builder, &config, &device, dropout_rate)?;
    
  4. Step scheduler after each forward (lines 292-296):

    if let Ok(mut scheduler_opt) = self.dropout_scheduler.lock() {
        if let Some(scheduler) = scheduler_opt.as_mut() {
            scheduler.step(1);
        }
    }
    
  5. New helper method (lines 408-418):

    pub fn get_dropout_rate(&self) -> f64 {
        if let Ok(scheduler_opt) = self.dropout_scheduler.lock() {
            if let Some(scheduler) = scheduler_opt.as_ref() {
                return scheduler.get_rate();
            }
        }
        self.config.dropout_prob  // Fallback to static
    }
    

4. NetworkLayers Refactoring

Location: /home/jgrusewski/Work/foxhunt/ml/src/dqn/network.rs (lines 142-180)

Changes:

  • Split new() to delegate to new_with_dropout_rate()
  • new_with_dropout_rate() accepts explicit dropout rate parameter
  • Allows dynamic dropout rate during forward pass

Test Coverage

Location: /home/jgrusewski/Work/foxhunt/ml/src/dqn/tests/dropout_scheduler_tests.rs

Test Cases (11 tests):

  1. test_dropout_scheduler_creation - Verifies initialization
  2. test_dropout_scheduler_linear_decay - Tests linear interpolation at 0%, 25%, 50%, 75%, 100%
  3. test_dropout_scheduler_step_increment - Tests single-step increments
  4. test_dropout_scheduler_current_step_tracking - Verifies step counter
  5. test_qnetwork_config_with_dropout_schedule - Config validation
  6. test_qnetwork_with_adaptive_dropout - Full integration test
  7. test_dropout_scheduler_zero_decay_steps - Edge case: immediate final rate
  8. test_dropout_scheduler_same_initial_and_final - Edge case: constant rate
  9. test_dropout_scheduler_realistic_training_schedule - Real-world example (0.5 → 0.05 over 100k steps)
  10. Tests boundary conditions and thread safety

Usage Example

// Configure adaptive dropout
let config = QNetworkConfig {
    state_dim: 64,
    num_actions: 3,
    dropout_schedule: Some((0.5, 0.1, 100_000)),  // 0.5 → 0.1 over 100k steps
    ..Default::default()
};

let network = QNetwork::new(config)?;

// During training:
// - Early (step 0): dropout_rate = 0.5 (high regularization)
// - Mid (step 50k): dropout_rate = 0.3 (moderate)
// - Late (step 100k+): dropout_rate = 0.1 (fine-tuning)

Benefits

  1. Early Training (High Dropout):

    • Prevents overfitting to noisy early experiences
    • Encourages robust feature learning
    • Regularizes aggressive exploration
  2. Late Training (Low Dropout):

    • Allows network to use full capacity
    • Enables precise fine-tuning
    • Improves final policy quality
  3. Smooth Transition:

    • Linear decay avoids sudden behavior changes
    • Gradual adaptation matches learning progress

Backward Compatibility

  • Default behavior unchanged: dropout_schedule: None uses static dropout_prob
  • Opt-in feature: Only active when dropout_schedule is set
  • No breaking changes: Existing code continues to work

Technical Notes

  1. Thread Safety: Uses Mutex<Option<DropoutScheduler>> for safe concurrent access
  2. Step Tracking: Increments on every forward() call
  3. Saturation: saturating_add() prevents overflow
  4. Progress Clamping: min(1.0) ensures rate doesn't go below final value

Files Modified

  1. /home/jgrusewski/Work/foxhunt/ml/src/dqn/network.rs

    • Added DropoutScheduler struct (45 lines)
    • Extended QNetworkConfig with dropout_schedule field
    • Modified QNetwork to integrate scheduler
    • Refactored NetworkLayers::new() to support dynamic dropout
  2. /home/jgrusewski/Work/foxhunt/ml/src/dqn/tests/dropout_scheduler_tests.rs (NEW)

    • 11 comprehensive tests (189 lines)
    • Unit tests for scheduler logic
    • Integration tests for QNetwork
  3. /home/jgrusewski/Work/foxhunt/ml/src/dqn/tests/mod.rs

    • Added mod dropout_scheduler_tests;

Next Steps

To run tests (once existing compilation errors are fixed):

cargo test --package ml --lib dqn::tests::dropout_scheduler_tests
cargo test --package ml --lib dqn::network::tests  # Existing network tests

Status

Implementation complete (TDD approach) Tests written (11 test cases) ⚠️ Tests pending - blocked by existing codebase compilation errors unrelated to this feature Backward compatible Documentation complete