Perceptual and Generative Evaluation › Diversity, Sharpness, and Multimodality
World Models HandbookAll chapters Perceptual and Generative Evaluation › Diversity, Sharpness, and MultimodalityOne section · Sections in this chapter4 / 8 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Unobserved quantities and measurement noise can make a future stochastic given the available history. An exposed point prediction does not communicate that uncertainty, even if the model maintains a distribution internally. To evaluate probabilistic predictions, inspect the declared conditional distribution as well as point-loss performance.
The vocabulary here is easy to get wrong, so let us separate what these words mean when we use them as metrics.
- Visual sharpness: crispness or high-frequency structure in individual rendered samples. This is distinct from forecast sharpness, the concentration of a predictive distribution. A visually sharp sample can come from a broad multimodal forecast.
- Mode coverage: whether the generator represents materially probable alternatives, evaluated with a specified feature-space or event-based diagnostic. Merely assigning nonzero density everywhere is not useful coverage.
- Diversity: the spread of samples the model can generate. High diversity alone is not virtue either; a model that samples noise is diverse but useless.
- Calibration: the agreement between the model's implied probabilities and the empirical frequencies of events it predicts.
These are different properties, and a single number cannot summarize all of them. Image-gradient or frequency diagnostics can describe visual sharpness but also reward noise. Entropy or interval widths can describe forecast concentration under a declared representation. Precision/recall-style diagnostics describe feature-space fidelity and coverage; variance or mode counts describe sampled diversity; event reliability describes calibration. NLL evaluates the probabilities or densities assigned to outcomes, not sharpness alone.
It is worth pausing on why these words are easy to conflate. Visual sharpness is a property of one rendered image. Diversity is a property of a set of rendered images. Mode coverage is a property of the set relative to the true conditional. Calibration is a property of the model's probability assignments, which may or may not be visible in any rendered image. A model can score high on any one of these and low on the others. A table that reports a single number under the heading "quality" is hiding at least three questions.
Best-of-: oracle selection inflates scores
Best-of- selection appears in stochastic video-prediction work: the SAVP project presents stochastic predictions selected for their best similarity to the reference among 100 samples. The metric samples predictions from the model's conditional, compares each to the realized future, and reports the best score. This number improves monotonically as grows, because you are taking a minimum over more samples; formally, for each realized future and predicted set , the best-of- error is for a chosen distance , and the expectation of a minimum over i.i.d. samples is non-increasing in . It is oracle selection: no real deployment gets to see the realized future and pick the closest of candidates. Best-of- only has interpretation if is held fixed across the models you compare and the full sampling protocol is reported.
Adding a sample to a nested pool cannot increase its minimum error. The expectation for i.i.d. samples follows the same ordering. A misspecified forecast can therefore obtain a small best-of- error if it assigns positive probability to a sufficiently close neighborhood of the reference: the chance of at least one hit is , where is that neighborhood's probability. If , no sample budget creates coverage. This improvement is selection, not evidence of calibration.
In the following experiment, each repetition draws one maximum-budget sample pool from a Gaussian centered slightly off the realized future. Each uses the first samples from that same pool. These nested sets guarantee non-increasing error for every repetition and for their mean. Independently resampled finite estimates for different need not be monotone, even though their expectations are non-increasing. Neither result establishes calibration.
rng = np.random.default_rng(20240501)
SIGMA_POS = 1.2
K_values = np.array([1, 2, 4, 8, 16, 32, 64, 128])
repeats = 400
sample_pool = rng.normal(
REALIZED_X + 1.5, SIGMA_POS, size=(repeats, int(K_values.max()))
)
prefix_best = np.minimum.accumulate(np.abs(sample_pool - REALIZED_X), axis=1)
best_of_k_mean = prefix_best[:, K_values - 1].mean(axis=0)
assert np.all(np.diff(best_of_k_mean) <= 1e-9), (
"best-of-K must be non-increasing in K"
)
assert best_of_k_mean[0] > best_of_k_mean[-1]
The figure is not evidence that the model is getting better. It is evidence that oracle selection is happening. When you see a table that reports best-of- numbers, check whether the same holdout data is used for all models, whether is constant, and whether the number is a mean or a minimum. If the sampling protocol is not in the paper, treat the number as uninterpretable.
A deployment may generate one sample or an ensemble. What it cannot generally do is select the sample closest to a future that has not occurred. Report the deployment sample budget and selection procedure separately from reference-based best-of-. Single-sample error and distributional or probabilistic scores are useful complementary diagnostics, not substitutes for that distinction.
Diversity through high variance is not coverage
High variance need not mean useful diversity. An increasingly wide Gaussian centered between two narrow modes has full real-line support, yet assigns vanishing probability to fixed neighborhoods of those modes as its scale grows. Useful coverage concerns probability mass near plausible alternatives, not merely nonzero density or spread. Feature-space sample diagnostics and event-based probability checks answer different parts of that question.
The reason spread is a weak proxy for coverage is that a distribution can spread out while simultaneously thinning out on the regions that matter.
The same distinction appears as a density plot. The target mixes two Gaussians centered at and , each with standard deviation 0.3. The comparison forecast is a zero-mean Gaussian with standard deviation 2. Its variance is 4, compared with the target's , so these distributions are not variance-matched. The broad forecast has full support but less density at the target modes, about 26.5% of the target's mode density. We also compute probability mass in the two fixed intervals within 0.3 of each mode: density at a point and probability in a neighborhood are different quantities. The plotted window shows the central region, not the full tails.
import numpy as np
def gaussian_density(x, mu, sigma):
return np.exp(-0.5 * ((x - mu) / sigma) ** 2) / (
sigma * np.sqrt(2.0 * np.pi)
)
x_coverage = np.linspace(-4.0, 4.0, 400)
true_bimodal = 0.5 * gaussian_density(
x_coverage, -1.0, 0.3
) + 0.5 * gaussian_density(x_coverage, 1.0, 0.3)
broad_gaussian = gaussian_density(x_coverage, 0.0, 2.0)
_target_at_mode = float(
0.5 * gaussian_density(1.0, 1.0, 0.3)
+ 0.5 * gaussian_density(1.0, -1.0, 0.3)
)
_broad_at_mode = float(gaussian_density(1.0, 0.0, 2.0))
mode_density_ratio = _broad_at_mode / _target_at_mode
# Analytic density ratio, not an unsupported near-zero threshold.
expected_density_ratio = 0.3 * np.exp(-0.125) / (1 + np.exp(-2 / 0.09))
assert np.isclose(mode_density_ratio, expected_density_ratio)
target_variance, broad_variance = 1 + 0.3**2, 2.0**2
assert np.isclose(target_variance, 1.09) and broad_variance == 4.0
from math import erf
def interval_mass(lo, hi, mu, sigma):
return 0.5 * (
erf((hi - mu) / (sigma * np.sqrt(2.0)))
- erf((lo - mu) / (sigma * np.sqrt(2.0)))
)
mode_intervals = [(-1.3, -0.7), (0.7, 1.3)]
target_mode_mass = sum(
0.5 * interval_mass(lo, hi, mu, 0.3)
for lo, hi in mode_intervals
for mu in (-1.0, 1.0)
)
broad_mode_mass = sum(
interval_mass(lo, hi, 0.0, 2.0) for lo, hi in mode_intervals
)
assert 0 < broad_mode_mass < target_mode_mass < 1
moment_grid = np.linspace(-20.0, 20.0, 20001)
target_density = 0.5 * gaussian_density(
moment_grid, -1.0, 0.3
) + 0.5 * gaussian_density(moment_grid, 1.0, 0.3)
broad_density = gaussian_density(moment_grid, 0.0, 2.0)
assert np.isclose(
np.trapezoid(moment_grid**2 * target_density, moment_grid), target_variance
)
assert np.isclose(
np.trapezoid(moment_grid**2 * broad_density, moment_grid), broad_variance
)
As this Gaussian's standard deviation tends to infinity, probability in any fixed bounded neighborhood tends to zero. At every finite positive scale, however, that probability remains positive: samples near the target modes are unlikely rather than impossible. Continuous point probabilities are zero for both distributions; the plotted heights are densities, not point masses.
Sajjadi et al. (2018) formulated generative precision and recall, and Kynkaanniemi et al. (2019) proposed an improved feature-manifold estimator. For that estimator, the two quantities separate:
- Precision: the fraction of generated feature samples inside an estimated real-data support region.
- Recall: the fraction of real feature samples inside an estimated generated-data support region. It is not a fraction of a manifold's geometric volume.
The decomposition is useful because the two failure modes have different fixes. Low precision suggests the generator needs to be constrained toward the real data distribution. Low recall suggests it needs to diversify, for example by using more modes or a less collapsed latent. Reporting a single score hides which of the two problems is present.
These diagnostics are useful because they separate coverage from fidelity, and they avoid the moment-matching limitations of FID. But their semantics depend on hyperparameters (typically -nearest-neighbor radii or manifold balls), on feature choice, and on sample counts. Two implementations with different conventions can rank models differently. Report the implementation you used.
A toy feature-distance illustration
The following example is deliberately simple. It uses one synthesized feature dimension and two discrete actions. We work in one feature dimension with two actions. Under action the true conditional feature is Gaussian with mean and standard deviation , and under action it is Gaussian with mean and standard deviation . We have two candidate generators:
- G1 (matched) produces features with mean under and mean under . It matches the ground-truth conditional.
- G2 (reversed) produces features with mean under and mean under . It reverses every action.
With equal action weights, G1 and G2 have identical population marginals: the same two Gaussians appear in the same proportions. We draw their finite samples independently, so the empirical pooled sets and scores will not be identical. Their small differences are sampling effects, not evidence that pooling detects the reversed action labels.
We compute a "toy feature Gaussian distance", defined as the squared 2-Wasserstein distance between two Gaussian fits of the empirical features. For one-dimensional features with means and standard deviations ,
where:
- : the sample mean of the first empirical feature set
- : the sample mean of the second empirical feature set
- : the sample standard deviation of the first feature set
- : the sample standard deviation of the second feature set
In one dimension, the 2-Wasserstein distance between two Gaussians and reduces to . The first difference captures a location shift and the second captures a spread mismatch.
The reason we use a Wasserstein distance rather than an distance between densities or parameters is that it is the same construction that FID uses, just with matrices in place of scalars. Keeping the algebra identical while collapsing dimension is what makes the toy example informative: the failure mode you see here is exactly the failure mode a real FID exhibits, minus the high-dimensional bookkeeping.
We compute the distance separately within each action and average with equal weights, then compute it on the concatenated pools. Population pooled distances are both zero. Finite independent samples yield small nonzero pooled distances, while the conditional distance reveals G2's reversal because its action means differ from their references.
This is explicitly a toy feature Gaussian distance. It is not FID, not LPIPS, not SSIM, and not FVD. It is a pedagogical device for the conceptual failure. Real FID and FVD would use high-dimensional learned features and a matrix square root. The algebra is the same and the failure mode is identical.
def toy_feature_gauss_dist(x, y):
"""Toy 1-D Gaussian Wasserstein distance squared between two empirical feature sets.
For Gaussian features this equals $(\mu_x - \mu_y)^2 + (\sigma_x - \sigma_y)^2$.
This is *not* FID, LPIPS, SSIM, or FVD; it is a hand-designed device to
illustrate the action-conditioned vs pooled-marginal failure.
"""
mu_x, mu_y = float(np.mean(x)), float(np.mean(y))
sd_x, sd_y = float(np.std(x, ddof=1)), float(np.std(y, ddof=1))
return (mu_x - mu_y) ** 2 + (sd_x - sd_y) ** 2rng = np.random.default_rng(7)
N_PER_ACTION = 400
MODE_MEAN_POS = 1.0
MODE_MEAN_NEG = -1.0
FEATURE_SD = 0.5
# Large separation relative to sampling noise is a design heuristic for this toy,
# not a necessary detection threshold.
assert (MODE_MEAN_POS - MODE_MEAN_NEG) > 4 * FEATURE_SD / np.sqrt(N_PER_ACTION)
# Ground-truth conditional features under each action.
gt_a1 = rng.normal(MODE_MEAN_POS, FEATURE_SD, N_PER_ACTION)
gt_a2 = rng.normal(MODE_MEAN_NEG, FEATURE_SD, N_PER_ACTION)
# G1: matched conditional.
g1_a1 = rng.normal(MODE_MEAN_POS, FEATURE_SD, N_PER_ACTION)
g1_a2 = rng.normal(MODE_MEAN_NEG, FEATURE_SD, N_PER_ACTION)
# G2: reversed conditional (a1 features look like a2 features and vice versa).
g2_a1 = rng.normal(MODE_MEAN_NEG, FEATURE_SD, N_PER_ACTION)
g2_a2 = rng.normal(MODE_MEAN_POS, FEATURE_SD, N_PER_ACTION)G1 conditional 0.006109 G2 conditional 4.021280 G1 pooled 0.004088 G2 pooled 0.001985

A reported FID needs its conditioning protocol: a single headline number might be pooled, stratified, or computed for one condition. Pooling alone cannot rule out the balanced label-swap failure. One diagnostic computes FID or FVD within stated action or history strata, then aggregates with declared weights. Multiple covariance estimates and matrix square roots can increase cost, while smaller per-stratum sample sizes increase estimation uncertainty. Stratification does not remove feature-moment blind spots.
Each stratum needs enough samples for reliable statistics. Binning or clustering is one approach for continuous or high-dimensional conditions, but the chosen resolution can merge important differences. Conditional two-sample methods or joint condition-output tests are alternatives. Report the grouping, weights, sample counts, and remaining blind spots.
Finite-sample estimation bias
For two independent samples of size from the same nondegenerate Gaussian, the population toy distance is zero but the expected plug-in estimate is positive. Mean and standard-deviation errors are of order here. In particular, the expected squared difference of sample means alone is . The additional squared standard-deviation difference is nonnegative, so this matched-sample expectation remains positive at finite and tends to zero as grows. Degenerate data or comparing a sample with itself are different cases.
The positive expectation arises from squaring estimator differences. It is a property of this plug-in estimator and sampling setup, not a theorem that every finite-sample metric must be biased or that every realization decreases monotonically with sample count.
rng = np.random.default_rng(99)
n_list = np.array([50, 100, 200, 400, 800, 1600])
bias_estimates = []
for n in n_list:
vals = []
for _ in range(300):
a = rng.normal(MODE_MEAN_POS, FEATURE_SD, int(n))
b = rng.normal(MODE_MEAN_POS, FEATURE_SD, int(n))
vals.append(toy_feature_gauss_dist(a, b))
bias_estimates.append(float(np.mean(vals)))
bias_estimates = np.array(bias_estimates)
# The claim is that bias is positive at finite n and decays as n grows.
assert np.all(bias_estimates > 0.0)
assert bias_estimates[0] > bias_estimates[-1]
This is a finite-sample illustration for independent Gaussian samples. It does not establish the magnitude or direction of bias for every real FID/FVD protocol. Real feature covariance estimates additionally become rank-deficient when sample counts are too small for their dimension. Chong and Forsyth (2020) show that FID's finite-sample bias depends on the evaluated generator, so equal sample counts alone do not eliminate biased comparisons. A reported score depends on the model, encoder, sample counts, and estimator.
Using the same sample count for two models does not guarantee equal bias. Report the feature encoder, sampling protocol, estimator, and uncertainty. Confidence intervals describe sampling variation under that protocol; they do not remove estimator bias. Chong and Forsyth's analysis explains why the model-dependent bias also matters when comparing scores.
Sharpness metrics and their limits
Negative log-likelihood (NLL) evaluates outcome assignments, not visual sharpness alone. For a declared discrete probability mass function or continuous density , the realized-future score is
where:
- : the negative log-likelihood of the realized future under the model's predictive distribution (the quantity being defined)
- : the model's predictive probability (or density) of the realized future observations given history and actions
- : the history at time , as defined earlier
- : the sequence of actions over the prediction horizon
Here the logarithm is natural, so the score is in nats. Lower values indicate more assigned probability mass or density at the realized outcome. With a common reference measure and finite expectations, expected NLL is the true conditional entropy plus the conditional KL divergence, averaged over histories and actions. The true conditional distribution therefore minimizes expected NLL among unrestricted normalized forecasts. Calibration on selected events alone does not establish this optimum.
Zero assigned mass or density gives positive infinity. Discrete NLL is nonnegative; continuous densities can exceed one, giving negative NLL, and their numerical values depend on units and base measure. Clipping a log score is not necessarily scoring a normalized model: flooring the probabilities at gives , whose sum exceeds one. Renormalize a floored distribution, or use a declared mixture with a normalized contamination distribution, and disclose the change. A uniform contamination density on an unbounded Euclidean observation space cannot be normalized.
Near-optimal NLL and imperfect event reliability can coexist; exact optimal expected NLL under these assumptions is a stronger statement. For a binary event occurring with probability , forecasting gives expected NLL about nats, versus the optimum of about nats, yet the forecast is off by . Reliability diagrams reveal that mismatch rather than replacing the log score.
The following reliability curves are stipulated illustrations, not estimates from labeled outcomes. The diagonal represents calibration. The second curve has event frequencies more extreme than the forecast probabilities, so it depicts underconfidence. No average accuracy or NLL is computed for either curve.
import numpy as np
probability_bins = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
calibrated_frequency = probability_bins
underconfident_frequency = probability_bins + 0.15 * (probability_bins - 0.5)
underconfident_frequency = np.clip(underconfident_frequency, 0.0, 1.0)
assert np.all(
(underconfident_frequency - probability_bins) * (probability_bins - 0.5)
>= 0
)
For probabilistic forecasts, distinguish concentration of the forecast from its calibration and coverage. Where these diagnostics are defined, report NLL, a diversity diagnostic, and reliability on relevant events. State the interpretation and assumptions of any rank histogram. A sharpness claim alone leaves those other properties untested.