Evaluation & Metrics
Fréchet Inception Distance
The standard sample-based score for image generative models, the Fréchet (2-Wasserstein) distance between Gaussians fitted to Inception-v3 features of real and generated images; its formula, its small-sample bias, its sensitivity to resizing and compression, its ImageNet bias, and the related metrics IS, KID, precision and recall, and FD-DINOv2.
intermediate
The Fréchet Inception Distance (FID) scores a generative model by comparing a set of its images with a set of real images. Both sets are passed through Inception-v3, an image classification network trained on ImageNet; a Gaussian is fitted to each set’s feature vectors, and FID is the Fréchet distance between the two Gaussians. Lower is better, and 0 means the fitted Gaussians are identical. Heusel et al. (2017) introduced it as an improvement on the Inception Score, which never looks at real images. Parmar et al. (2022) call it the most ubiquitous metric for generative models. It is easy to misuse: it is biased for small samples, sensitive to preprocessing, and tied to the ImageNet classes.
Formula
Let be the mean and covariance of the features of the real images and those of the generated images. Then
This is the squared 2-Wasserstein distance between and , the smallest expected squared distance over all ways of pairing samples and of the two distributions. Heusel et al. take the closed form for Gaussians from Dowson and Landau (1982). Their text calls the distance the FID, but their equation 6 (equation 7 in Appendix A1, arXiv v6) gives , and implementations such as pytorch-fid return : FID is in squared feature units, with no square root.
The product is not symmetric, but it has the same eigenvalues as the symmetric positive semidefinite matrix , so they are nonnegative and . When the covariances commute, for example when both are diagonal with variances and , the trace term reduces to . In one dimension FID is .
The features are the 2048 outputs of the last pooling layer of Inception-v3 (Szegedy et al., 2016), usually called pool3. In the architecture’s Table 1, this pool reduces the final grid to a 2048-vector just before the classifier; the input is , so every image is resized first. Heusel et al. took the pretrained network used for the Inception Score, computed the real statistics on the whole training set and the generated statistics on 50,000 samples.
Intuition
The mean term grows when the average content drifts: wrong colors, wrong textures, systematic blur. The covariance term grows when the spread differs: a generator that covers only some real modes has a smaller, differently shaped covariance. FID adds both, so it rewards fidelity and diversity together but cannot say which is lacking.
Only the first two moments of the features enter, which Heusel et al. justify by the Gaussian being the maximum-entropy distribution for a given mean and covariance. The features are far from Gaussian: they come from ReLUs, so they are never negative and have no density, with about 2% of components typically exactly zero (Bińkowski et al., 2018). It follows from the formula that two different feature distributions with equal means and covariances score 0.
Interpretation
FID ranges from 0 to infinity and has no absolute scale; a value means something only next to values computed under the same protocol. For scale, Parmar et al. (2022, arXiv v3, §3.3) put StyleGAN2 on FFHQ at around 3 and note that recent methods on that benchmark typically differ by less than 1.
Heusel et al. (Figure 3 and Appendix A1, arXiv v6) showed that FID rises steadily as CelebA images are disturbed with Gaussian noise, Gaussian blur, black rectangles, swirls or salt-and-pepper noise, or mixed with ImageNet images. Bińkowski et al. (Appendix E) found the Inception Score more monotonic than Heusel et al. had, so this advantage of FID may not be robust to small changes in method. Kynkäänniemi et al. (2023) summarize the practical experience: large values reliably indicate failed training, and FID is dependable for monitoring a single run, but comparisons between sufficiently different architectures or training setups are where it can mislead.
When to Use It
FID is the default for comparing image generators on the same dataset and for tracking training. Use it under a fixed, published protocol: the same reference images, the same number of generated samples (50,000 is common), the same network weights, and the same resizing and file format. Report a measure that separates fidelity from diversity alongside it, and for models that use ImageNet-pretrained components, a Fréchet distance in a feature space not trained on ImageNet classes.
The widely used pytorch-fid implementation computes the matrix square root with scipy.linalg.sqrtm, discards the tiny imaginary parts that round-off can leave after checking that they are small, and adds a small multiple of the identity to both covariances if the square root is not finite (fid_score.py, as of October 2026). A sample covariance of vectors has rank at most , so with 2048 features it is singular unless exceeds 2048.
Failure Cases
Small samples bias it upward. In practice the FID of a finite sample overestimates the FID of the distributions. Bińkowski et al. (Figure 1b) compared the CIFAR-10 training and test sets, which come from the same distribution: FID was still about 8.1 with and still falling, and they show that no unbiased estimator of FID exists (Appendix D.3). Chong and Forsyth (2020) showed that the bias is approximately for generated images, with a constant that depends on the generator. Fixing therefore does not make generators comparable: in their Figure 3 (arXiv v3), two independently trained DCGANs of identical architecture swap rank as changes.
Preprocessing changes it. Parmar et al. (2022) found that the resizing in the TensorFlow and PyTorch FID implementations uses a fixed-width bilinear filter, which aliases when it shrinks large images to 299 pixels. The same 1024-pixel FFHQ images resized with PyTorch’s bilinear filter and with PIL’s antialiased bicubic filter are 4.36 apart (Table 1, arXiv v3). FFHQ images at 256 pixels saved as quality-75 JPEG, PIL’s default, score 20.96 against the PNG originals (Figure 6), although they look alike. A StyleGAN2 trained on LSUN Churches, which are stored as quality-75 JPEGs, improved from 4.00 to 3.48 just by saving its samples as quality-87 JPEG (Figure 8). They recommend storing new datasets as PNG.
It is tied to ImageNet classes. The pool3 features are one affine layer away from the ImageNet logits. Kynkäänniemi et al. (2023) resampled StyleGAN2 outputs so that their Top-1 ImageNet class histogram matched the real images’ histogram. Across datasets this lowered FID by about 10% (FFHQ: 5.30 to 4.70, −11.3%, Table 1, arXiv v3) without making any image better. Resampling to match all such “fringe” features lowered the FFHQ FID by 66.4%, to 1.78, while a Fréchet distance in CLIP features fell only from 2.76 to 2.64 (Table 2).
It can miss visible artifacts. In the same paper, a Projected FastGAN, whose discriminator uses an ImageNet-pretrained network, and StyleGAN2 reach nearly the same FFHQ FID (5.28 and 5.30). Its faces are visibly more distorted (Figure 7), and Kynkäänniemi et al. report that a human preference study by Sauer et al. (2021) rated Projected FastGAN’s FFHQ samples lower in quality and diversity than StyleGAN2’s; the CLIP-feature distance (4.67 against 2.76) agrees. In human evaluations of 41 models on four datasets, Stein et al. (2023) found that no metric correlated strongly with human judgment, and that FID preferred GANs over diffusion models, which humans judged the most realistic on three of the four datasets.
Variants
FID∞. Chong and Forsyth compute FID at several sample sizes, at least 5,000 (Algorithm 1, arXiv v3), fit a line in and report its value at . They also found that drawing the generator’s latent vectors from a Sobol low-discrepancy sequence instead of independent normal draws lowered both the estimates and their spread.
Clean-FID keeps the formula but standardizes antialiased bicubic resizing and the handling of quantization and compression (Parmar et al., 2022).
Other feature spaces. Any embedding can replace Inception-v3: Kynkäänniemi et al. (2023) use CLIP, SwAV and ResNet-50 features, and Stein et al. (2023) recommend the self-supervised DINOv2 ViT-L/14 encoder, whose distance, , recovered the correlation with human evaluations that FID lacked. Values from different feature spaces are not comparable.
Example
No pretrained network is used here, so a fixed random feature map stands in for Inception-v3: 64 zero-mean random filters, a ReLU and global average pooling, giving 64 features instead of 2048. The real images are shapes (disk, square, ring, bar, cross) with random position, size, brightness and noise. The script checks the implementation against closed forms, compares 10,000 real images with generated sets that drop modes or are blurred with a Gaussian filter, and measures the Fréchet distance (FD) between two real samples as their size grows.
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view
from scipy import linalg, ndimage
def frechet_distance(mu1, s1, mu2, s2):
"""Squared Frechet (2-Wasserstein) distance between N(mu1, s1) and N(mu2, s2)."""
covmean = linalg.sqrtm(s1 @ s2) # (s1 s2)^{1/2}; not symmetric
covmean = covmean.real # drop round-off imaginary parts
diff = mu1 - mu2
return diff @ diff + np.trace(s1 + s2 - 2 * covmean)
def stats(f):
return f.mean(axis=0), np.cov(f, rowvar=False)
# ---- 1. Check against closed forms for known Gaussians ----------------------
rng = np.random.default_rng(0)
d = 8
mu1, mu2 = rng.normal(size=d), rng.normal(size=d)
a, b = rng.uniform(0.5, 2, d), rng.uniform(0.5, 2, d)
closed = np.sum((mu1 - mu2) ** 2) + np.sum((np.sqrt(a) - np.sqrt(b)) ** 2)
print(f"diagonal: sqrtm {frechet_distance(mu1, np.diag(a), mu2, np.diag(b)):.6f}"
f" closed form {closed:.6f}")
A, B = rng.normal(size=(d, d)), rng.normal(size=(d, d))
s1, s2 = A @ A.T + 0.1 * np.eye(d), B @ B.T + 0.1 * np.eye(d)
r1 = linalg.sqrtm(s1).real # symmetric form of the trace term
sym = np.sum((mu1 - mu2) ** 2) + np.trace(s1 + s2) \
- 2 * np.sum(np.sqrt(np.linalg.eigvalsh(r1 @ s2 @ r1)))
print(f"full cov: sqrtm {frechet_distance(mu1, s1, mu2, s2):.6f}"
f" symmetric form {sym:.6f}")
# ---- 2. Synthetic 16x16 shape images with five modes ------------------------
H = 16
yy, xx = np.mgrid[:H, :H]
def draw(kind, rng):
cy, cx = 7.5 + rng.uniform(-2, 2, 2)
r = rng.uniform(3, 5)
dy, dx = yy - cy, xx - cx
if kind == 0: m = dy**2 + dx**2 <= r**2 # disk
elif kind == 1: m = (abs(dy) <= r * 0.8) & (abs(dx) <= r * 0.8) # square
elif kind == 2: m = abs(np.hypot(dy, dx) - r) <= 1.0 # ring
elif kind == 3: m = (abs(dy) <= 1.2) & (abs(dx) <= r + 2) # bar
else: m = ((abs(dy) <= 1) | (abs(dx) <= 1)) & (abs(dy) <= r) & (abs(dx) <= r) # cross
img = rng.uniform(0.6, 1.0) * m + rng.normal(0, 0.05, (H, H))
return np.clip(img, 0, 1)
def sample(n, rng, modes=(0, 1, 2, 3, 4), blur=0.0):
kinds = rng.choice(modes, size=n)
imgs = np.stack([draw(k, rng) for k in kinds])
if blur > 0:
imgs = ndimage.gaussian_filter(imgs, sigma=(0, blur, blur))
return imgs
# ---- 3. Fixed random feature map: STAND-IN for Inception-v3 pool features ---
D, K = 64, 5 # 64 features (Inception-v3: 2048)
frng = np.random.default_rng(123) # the "pretrained network" is fixed
W = frng.normal(size=(K * K, D))
W -= W.mean(axis=0) # zero-mean filters: respond to edges
def features(imgs, batch=1000):
out = []
for i in range(0, len(imgs), batch):
p = sliding_window_view(imgs[i:i + batch], (K, K), axis=(1, 2))
p = p.reshape(*p.shape[:3], K * K) # (n, 12, 12, 25) patches
out.append(np.maximum(p @ W, 0).mean(axis=(1, 2))) # ReLU + avg pool
return np.concatenate(out)
rng = np.random.default_rng(3)
mu_r, s_r = stats(features(sample(10000, rng))) # reference "real" statistics
def fd_to_real(imgs):
mu, s = stats(features(imgs))
fd = frechet_distance(mu_r, s_r, mu, s)
return fd, np.sum((mu_r - mu) ** 2) # total and mean term
print("\nFD to 10,000 real images (generated sets of 10,000): FD mean term")
for name, kw in [("fresh real sample", {}),
("drop the cross", dict(modes=(0, 1, 2, 3))),
("drop cross and bar", dict(modes=(0, 1, 2))),
("only disks", dict(modes=(0,))),
("blur sigma=0.5", dict(blur=0.5)),
("blur sigma=1.0", dict(blur=1.0)),
("blur sigma=2.0", dict(blur=2.0))]:
fd, mt = fd_to_real(sample(10000, rng, **kw))
print(f" {name:20s} {fd:8.4f} {mt:8.4f}")
# ---- 4. Small-sample bias: two samples of the SAME distribution -------------
pool = features(sample(40000, rng)) # 40,000 real images
print("\nFD between two disjoint real samples of size N (50 repeats):")
Ns = np.array([200, 500, 1000, 2000, 5000, 10000])
means = []
for n in Ns:
v = []
for _ in range(50):
idx = rng.permutation(len(pool))
v.append(frechet_distance(*stats(pool[idx[:n]]), *stats(pool[idx[n:2 * n]])))
means.append(np.mean(v))
print(f" N={n:5d} FD = {np.mean(v):.5f} +/- {np.std(v):.5f} N*FD = {n * np.mean(v):.1f}")
slope, intercept = np.polyfit(1 / Ns, means, 1)
print(f"linear fit in 1/N: FD = {intercept:.5f} + {slope:.2f}/N")
Output (NumPy 2.3.5, SciPy 1.16.3, about 6 seconds):
diagonal: sqrtm 17.203278 closed form 17.203278
full cov: sqrtm 37.927716 symmetric form 37.927716
FD to 10,000 real images (generated sets of 10,000): FD mean term
fresh real sample 0.0004 0.0001
drop the cross 0.0317 0.0204
drop cross and bar 0.2510 0.1579
only disks 0.3150 0.0783
blur sigma=0.5 0.3880 0.3544
blur sigma=1.0 2.4760 2.2752
blur sigma=2.0 6.9492 6.5549
FD between two disjoint real samples of size N (50 repeats):
N= 200 FD = 0.03551 +/- 0.01805 N*FD = 7.1
N= 500 FD = 0.01386 +/- 0.00697 N*FD = 6.9
N= 1000 FD = 0.00650 +/- 0.00297 N*FD = 6.5
N= 2000 FD = 0.00335 +/- 0.00243 N*FD = 6.7
N= 5000 FD = 0.00154 +/- 0.00081 N*FD = 7.7
N=10000 FD = 0.00079 +/- 0.00043 N*FD = 7.9
linear fit in 1/N: FD = -0.00016 + 7.11/N
The sqrtm result matches both closed forms. A fresh real sample scores 0.0004, the floor set by sampling noise. Dropping one of five shapes raises the distance about 80-fold, dropping two raises it further, and collapsing to disks alone raises it most among the mode-dropping cases, mostly through the covariance term (0.3150 − 0.0783), since one shape varies less. Blur shows up mainly in the mean term, because these edge filters respond less to every blurred image. Two samples of the same distribution never score 0: their distance falls roughly as ( stays between 6.5 and 7.9), and a line in extrapolates to −0.00016, close to the true 0, the idea behind FID∞. Rerunning with filter seeds 0 and 1 and data seeds 0 and 1 left the ordering of the generated sets unchanged. That a blur costs more here than dropping two modes shows that the weight of each defect depends on the feature network.
Related Metrics
- Inception Score (IS) (Salimans et al., 2016): , computed from Inception’s class probabilities on generated images only; it is high when each image is confidently classified and the classes are varied. The authors advised 50,000 samples.
- Kernel Inception Distance (KID) (Bińkowski et al., 2018): the squared maximum mean discrepancy between Inception features with the cubic kernel . It makes no Gaussian assumption, also compares skewness, and has an unbiased estimator whose spread shrinks quickly even for small samples.
- Precision and recall for generative models. Sajjadi et al. (2018) cluster real and generated Inception features together with -means () and compare the cluster histograms to trace a precision–recall curve. Kynkäänniemi et al. (2019) estimate the real and generated feature manifolds as unions of -nearest-neighbor balls (, VGG-16 features). Precision is the fraction of generated images inside the real manifold and recall the fraction of real images inside the generated one, separating what FID mixes, by analogy with classification precision and recall.
Related
- Generative Adversarial Network
A generative model trained as a game between a generator that turns random noise into images and a discriminator that tries to tell them from real images; the minimax objective and its Jensen–Shannon interpretation, the non-saturating loss, DCGAN, mode collapse and training instability, Wasserstein and other remedies, conditional and large-scale GANs, and why diffusion models overtook them.
- Diffusion Model
A generative model that learns to reverse a gradual Gaussian noising of images, generating by starting from pure noise and denoising step by step; the forward and reverse processes, the noise, data and score parameterizations, the U-Net and transformer denoisers, noise schedules, conditioning and the unifying score-SDE view.
- Gaussian Distribution
The bell-shaped probability distribution defined by a mean and a covariance, the default model for noise and uncertainty in estimation and tracking.
- ImageNet
A large database of web images organized by the noun hierarchy of WordNet, whose 1,000-class ILSVRC subset became the standard benchmark for image classification and the default source of pretrained networks.
- Sampling and Aliasing
How a continuous image becomes a grid of samples, when the samples determine it completely, and how detail too fine for the grid turns into false, coarser patterns.
- CLIP
A dual-encoder model from OpenAI that trains an image encoder and a text encoder contrastively on 400 million image–caption pairs from the internet, so that images can be classified "zero-shot" by comparing them with embedded text prompts such as "a photo of a dog."
References
- Heusel, M., Ramsauer, H., Unterthiner, T., Nessler, B. & Hochreiter, S. (2017). GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium. Advances in Neural Information Processing Systems 30 (NIPS).
- Heusel, M., Ramsauer, H., Unterthiner, T., Nessler, B. & Hochreiter, S. (2017). GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium. arXiv:1706.08500v6 (version with appendices).
- Dowson, D. C. & Landau, B. V. (1982). The Fréchet Distance between Multivariate Normal Distributions. Journal of Multivariate Analysis, 12(3), 450–455.
- Szegedy, C., Vanhoucke, V., Ioffe, S., Shlens, J. & Wojna, Z. (2016). Rethinking the Inception Architecture for Computer Vision. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2818–2826.
- Salimans, T., Goodfellow, I., Zaremba, W., Cheung, V., Radford, A. & Chen, X. (2016). Improved Techniques for Training GANs. Advances in Neural Information Processing Systems 29 (NIPS).
- Bińkowski, M., Sutherland, D. J., Arbel, M. & Gretton, A. (2018). Demystifying MMD GANs. International Conference on Learning Representations (ICLR).
- Chong, M. J. & Forsyth, D. (2020). Effectively Unbiased FID and Inception Score and Where to Find Them. IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 6069–6078.
- Parmar, G., Zhang, R. & Zhu, J.-Y. (2022). On Aliased Resizing and Surprising Subtleties in GAN Evaluation. IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 11400–11410.
- Sajjadi, M. S. M., Bachem, O., Lucic, M., Bousquet, O. & Gelly, S. (2018). Assessing Generative Models via Precision and Recall. Advances in Neural Information Processing Systems 31 (NeurIPS).
- Kynkäänniemi, T., Karras, T., Laine, S., Lehtinen, J. & Aila, T. (2019). Improved Precision and Recall Metric for Assessing Generative Models. Advances in Neural Information Processing Systems 32 (NeurIPS).
- Kynkäänniemi, T., Karras, T., Aittala, M., Aila, T. & Lehtinen, J. (2023). The Role of ImageNet Classes in Fréchet Inception Distance. International Conference on Learning Representations (ICLR).
- Stein, G., Cresswell, J. C., Hosseinzadeh, R., Sui, Y., Ross, B. L., Villecroze, V., Liu, Z., Caterini, A. L., Taylor, J. E. T. & Loaiza-Ganem, G. (2023). Exposing Flaws of Generative Model Evaluation Metrics and Their Unfair Treatment of Diffusion Models. Advances in Neural Information Processing Systems 36 (NeurIPS), 3732–3784.
- Seitzer, M. pytorch-fid: FID score for PyTorch (fid_score.py). GitHub repository.