Mode Collapse Detection
Mode collapse occurs when the generator produces limited variety.
What is Mode Collapse?
- Generator ignores latent input
- All outputs look similar
- Discriminator can't distinguish (always ~0.5)
- Training becomes unstable
Detection Methods
Diversity Score
#![allow(unused)] fn main() { let collapse_score = gan.detect_mode_collapse(num_samples); // collapse_score ∈ [0, 1] // 0 = perfect diversity // 1 = complete collapse (all identical) }
Implementation
#![allow(unused)] fn main() { pub fn detect_mode_collapse(&mut self, num_samples: usize) -> f32 { let latents = self.sample_latent(num_samples); let samples: Vec<Vec<u32>> = latents.iter() .map(|z| self.generator.generate(z)) .collect(); // Count unique sequences let unique: HashSet<_> = samples.iter().collect(); let diversity = unique.len() as f32 / num_samples as f32; // Mode collapse score = 1 - diversity 1.0 - diversity } }
Prevention Strategies
1. Minibatch Discrimination
#![allow(unused)] fn main() { fn minibatch_features(batch: &[Vec<u32>]) -> Vec<f32> { let features: Vec<Vec<f32>> = batch.iter() .map(|x| embed(x)) .collect(); // Compute pairwise distances let mut diversity_features = Vec::new(); for i in 0..features.len() { let distances: Vec<f32> = features.iter() .map(|f| l2_distance(&features[i], f)) .collect(); diversity_features.extend(distances); } diversity_features } }
2. Historical Averaging
#![allow(unused)] fn main() { fn historical_averaging_loss( current_params: &[f32], history: &VecDeque<Vec<f32>>, ) -> f32 { let avg: Vec<f32> = average_params(history); mse(current_params, &avg) } }
3. Unrolled GAN
#![allow(unused)] fn main() { fn unrolled_generator_loss( gan: &mut CodeGan, unroll_steps: usize, ) -> f32 { // Save discriminator state let d_state = gan.discriminator.clone(); // Unroll discriminator updates for _ in 0..unroll_steps { gan.train_discriminator_step(&real_batch); } // Compute generator loss against unrolled discriminator let g_loss = gan.generator_loss(); // Restore discriminator gan.discriminator = d_state; g_loss } }
Monitoring Dashboard
#![allow(unused)] fn main() { // During training for step in 0..total_steps { let g_loss = gan.train_generator_step(); let d_loss = gan.train_discriminator_step(&batch); if step % 100 == 0 { let collapse = gan.detect_mode_collapse(100); println!( "Step {}: G={:.4} D={:.4} Collapse={:.2}%", step, g_loss, d_loss, collapse * 100.0 ); if collapse > 0.8 { eprintln!("WARNING: Mode collapse detected!"); // Consider: reduce LR, add noise, restart } } } }