EasyGAN

Mode Collapse Detection

Generative Adversarial Networks (GAN)

Easy

Problem

Implement a specified diversity heuristic for detecting possible mode collapse. Compute the population standard deviation of every feature across the generated batch, then average those deviations.

s_j = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_{ij}-\mu_j)^2}

s = \frac{1}{D}\sum_{j=1}^{D}s_j

Here, N is the number of generated samples, D is the number of features, x_{ij} is feature j of sample i, \mu_j is that feature's batch mean, s_j is its population standard deviation, and s is the diversity score. Mark the batch as collapsed only when s is strictly less than threshold. Return a dictionary containing diversity_score as a Python float and is_collapsed as a boolean.

Theory

Mode collapse is one of the most common failure modes in GANs. It occurs when the generator produces limited varieties of samples, mapping different noise vectors to nearly identical outputs. Instead of learning the full data distribution, the generator "collapses" onto one or a few modes.

This problem detects mode collapse through the diversity score: the mean per-feature standard deviation of generated samples. When this score falls below a threshold, the generator is flagged as collapsed.


What It Is

Mode collapse detection measures output diversity to identify generator failure. A healthy generator produces varied outputs when given different noise inputs. Sample 100 random noise vectors z_1, \ldots, z_{100} and the resulting G(z_1), \ldots, G(z_{100}) should span the data distribution. In a collapsed generator, these outputs cluster tightly around one or a few points regardless of the input noise.

The detection mechanism computes a diversity score from a generated batch. Each feature dimension is examined independently for variation across the batch. If the generator has collapsed, every feature has near-zero variance. The diversity score aggregates per-feature variation into a single number compared against a threshold to produce a boolean is_collapsed signal.

This is a diagnostic tool, not a training objective. It tells you whether the generator has failed but does not fix the problem. Think of it as a smoke detector for GANs.


Key Equations

Given N generated samples, each with D features, arranged as X \in \mathbb{R}^{N \times D}:

Per-feature mean:

\mu_j = \frac{1}{N} \sum_{i=1}^{N} X_{i,j}

Per-feature standard deviation:

\sigma_j = \sqrt{\frac{1}{N} \sum_{i=1}^{N} (X_{i,j} - \mu_j)^2}

This is the population standard deviation (dividing by N, not N-1).

Diversity score (mean of per-feature stds):

\text{diversity\_score} = \frac{1}{D} \sum_{j=1}^{D} \sigma_j

Collapse detection:

\text{is\_collapsed} = \begin{cases} \text{True} & \text{if } \text{diversity\_score} < \text{threshold} \\ \text{False} & \text{otherwise} \end{cases}

The threshold depends on the data domain. For normalized data (features in [0, 1]), a threshold around 0.1 is common. For standardized data, thresholds around 0.5 may be appropriate.


What Mode Collapse Looks Like

All outputs nearly identical despite different noise inputs. The generator learns to ignore z and maps everything to roughly the same output: G(z_1) \approx G(z_2) \approx \cdots \approx G(z_N) for all noise vectors. The generator becomes essentially a constant function. If generating images, every image looks the same. If generating tabular data, every row has nearly identical values.

The generator ignores z. A well-functioning generator uses noise as a source of randomness, mapping different latent regions to different data regions. A collapsed generator develops weights that cancel out z's influence. The hidden layers produce similar activations regardless of input, and the information bottleneck discards diversity rather than carrying it through.

Everything maps to one or a few modes. Real distributions are multimodal. Consider handwritten digits with 10 modes (digits 0-9). A fully collapsed generator might produce only "1" because that single mode temporarily fools the discriminator. A partially collapsed generator might produce only "1" and "7". In both cases the generator fails to capture the full distribution.


Why Mode Collapse Happens

Mode collapse arises from the adversarial training dynamics between generator and discriminator:


Types of Mode Collapse


Paper Context

Goodfellow et al. (2014) introduced GANs with the minimax formulation:

\min_G \max_D \; \mathbb{E}_{x \sim p_{\text{data}}}[\log D(x)] + \mathbb{E}_{z \sim p_z}[\log(1 - D(G(z)))]

The paper proves this objective has a global optimum where p_G = p_{\text{data}}. However, the proof assumes infinite capacity and perfect optimization. In practice, a finite neural network may lack capacity to represent p_{\text{data}}, and gradient-based optimization may not find the global optimum. Mode collapse is a direct consequence of this gap between theory and practice.

The paper acknowledges that training requires careful balancing of G and D updates. When D is too strong, G receives vanishing gradients. When D is too weak, G receives noisy gradients. Both scenarios can trigger or worsen mode collapse.

Subsequent work addressing mode collapse includes minibatch discrimination (Salimans et al., 2016), unrolled GANs (Metz et al., 2017), Wasserstein GANs (Arjovsky et al., 2017), and spectral normalization (Miyato et al., 2018). Each attacks the problem from a different angle but none eliminates it entirely.


The Standard Deviation Metric

Standard deviation is a proxy for diversity because it directly measures spread. High std along a feature means that feature takes a wide range of values across the batch, indicating diversity. Near-zero std means all samples share nearly the same value, indicating collapse.

Why per feature then average? Different features may have different natural scales. A single global std would be dominated by high-magnitude features. Computing per-feature stds and averaging gives each feature equal weight in the diversity score.

What low std means geometrically. Each generated sample is a point in \mathbb{R}^D. A healthy generator scatters points throughout the region occupied by real data. Low std along all features means all points cluster in a tiny hyperrectangle. In the extreme (\sigma_j = 0 for all j), all points occupy a single location. Mode collapse shrinks the point cloud from a region to a point or a few isolated clusters.

Averaging vs. minimum. The mean of per-feature stds provides a smoother signal than \min_j \sigma_j. The minimum is more conservative (flags collapse if any single feature collapses) but more sensitive to noise. The mean is less prone to false positives from individual noisy features.


Numerical Example

Generator with D = 3 features, batch of N = 5 samples.

Collapsed generator output:

Sample Feature 1 Feature 2 Feature 3
1 0.51 0.82 0.34
2 0.50 0.81 0.35
3 0.52 0.83 0.33
4 0.50 0.82 0.34
5 0.51 0.82 0.34

Per-feature means: \mu_1 = 0.508, \mu_2 = 0.820, \mu_3 = 0.340.

Feature 1 deviations: [0.002, -0.008, 0.012, -0.008, 0.002]. Squared: [0.000004, 0.000064, 0.000144, 0.000064, 0.000004]. Mean: 0.000056. \sigma_1 = \sqrt{0.000056} \approx 0.0075.

Feature 2: deviations [0.00, -0.01, 0.01, 0.00, 0.00]. Mean of squares: 0.00004. \sigma_2 \approx 0.0063.

Feature 3: deviations [0.00, 0.01, -0.01, 0.00, 0.00]. Mean of squares: 0.00004. \sigma_3 \approx 0.0063.

Diversity score: (0.0075 + 0.0063 + 0.0063) / 3 \approx 0.0067.

With threshold = 0.1: 0.0067 < 0.1 \Rightarrow \text{is\_collapsed} = \text{True}. All five samples are nearly identical.

Healthy generator output:

Sample Feature 1 Feature 2 Feature 3
1 0.23 0.91 0.67
2 0.78 0.15 0.42
3 0.45 0.63 0.89
4 0.12 0.47 0.31
5 0.89 0.72 0.55

Per-feature stds: \sigma_1 \approx 0.299, \sigma_2 \approx 0.253, \sigma_3 \approx 0.196.

Diversity score: (0.299 + 0.253 + 0.196) / 3 \approx 0.249. With threshold = 0.1: 0.249 > 0.1 \Rightarrow \text{is\_collapsed} = \text{False}. The generator produces varied samples.


Mitigation Strategies

Once mode collapse is detected, several techniques can address it:


Pitfalls

1. Threshold too high gives false positives.

If real data naturally has low diversity in some features (binary features, categorical features with few values), the diversity score of a perfect generator would also be low. The threshold must be calibrated relative to the real data's diversity, not set arbitrarily.

2. Threshold too low misses partial collapse.

A threshold of 0.01 catches complete collapse but misses a generator stuck on a handful of modes. Inter-mode variation can inflate per-feature stds, making a partially collapsed generator look healthy.

3. Std of 0 does not always mean collapse.

If the real data has a constant feature (e.g., a bias column always equal to 1.0), then \sigma_j = 0 for that feature is correct behavior. A perfect generator should reproduce constant features exactly. Interpreting zero std as collapse without checking the real distribution leads to false alarms.

4. Confusing low quality with mode collapse.

A generator can produce diverse but unrealistic samples (high diversity, low quality) or one very realistic sample repeatedly (low diversity, high quality). The diversity score measures only spread, not realism. A high score does not mean the GAN works well.

5. Batch size too small for reliable std.

With N = 5 samples, the std estimate has high variance. A generator might appear collapsed because a small batch happened to produce similar outputs by chance. Use batches of at least 100-500 samples for reliable detection. The metric is meant for substantial batches, not training minibatches of size 8 or 16.


Examples

Example 1

Input
generated_samples = [[1,2,3],[1,2,3],[1,2,3]], threshold = 0.1
Output
{"diversity_score":0,"is_collapsed":true}
Explanation
Identical rows have zero deviation in every feature, so their diversity score falls below the threshold.

Example 2

Input
generated_samples = [[1,0],[-1,2],[0.5,-1.5],[2,1],[-0.5,0.5]], threshold = 0.1
Output
{"diversity_score":1.112646,"is_collapsed":false}

Example 3

Input
generated_samples = [[1,2],[1.01,2.02],[0.99,1.98],[1,2.01]], threshold = 0.1
Output
{"diversity_score":0.010931,"is_collapsed":true}

Hints

  1. Reduce the standard deviation over axis zero.
  2. Average the resulting per-feature values before comparing with the threshold.

Requirements

Constraints

Starter Code

import numpy as np

def detect_mode_collapse(generated_samples: np.ndarray, threshold: float = 0.1) -> dict:
    """
    Returns diversity_score and is_collapsed in a dictionary.
    """
    pass

Test Cases

CaseMatches
Identical samplespublic
Diverse samplespublic
Low-variance samplespublic