Evaluation API
Metrics for reconstruction quality, generative quality, memorization probing, and bootstrap confidence intervals. The generative-quality entry points (FID, precision/recall, NLL) are convenient one-call functions, with stateful calculator classes for streaming features over many batches.
Generative Quality
- medlatents.evaluation.calculate_fid(real_features, generated_features, eps=1e-06)[source][source]
Calculate Fréchet Inception Distance (FID) between real and generated features.
FID = ||mu_real - mu_gen||^2 + Tr(Sigma_real + Sigma_gen - 2*sqrt(Sigma_real @ Sigma_gen))
- Parameters:
real_features (
Float[Tensor, 'n_real features']) – Features from real images [N_real, D]generated_features (
Float[Tensor, 'n_gen features']) – Features from generated images [N_gen, D]eps (
float, default:1e-06) – Small constant for numerical stability
- Return type:
- Returns:
FID score (lower is better)
- medlatents.evaluation.calculate_precision_recall(real_features, generated_features, k=3)[source][source]
Calculate Precision and Recall for generative models.
Precision: What fraction of generated samples are realistic? Recall: What fraction of real samples are covered by the generator?
Based on “Improved Precision and Recall Metric for Assessing Generative Models” (Kynkäänniemi et al., 2019)
- Parameters:
real_features (
Float[Tensor, 'n_real features']) – Features from real images [N_real, D]generated_features (
Float[Tensor, 'n_gen features']) – Features from generated images [N_gen, D]k (
int, default:3) – Number of nearest neighbors
- Return type:
- Returns:
(precision, recall) tuple, both in [0, 1]
- medlatents.evaluation.calculate_nll(model, tokens, reduction='mean')[source][source]
Calculate Negative Log-Likelihood for discrete latent models.
- Parameters:
- Return type:
- Returns:
NLL value (lower is better)
- class medlatents.evaluation.FIDCalculator(extractor_type='radimagenet', device='cuda', **extractor_kwargs)[source][source]
Bases:
objectFID calculator with feature extraction.
Handles feature extraction and FID calculation in one class.
Example
>>> calculator = FIDCalculator(extractor_type='radimagenet') >>> # Extract features from real images >>> for batch in real_loader: ... calculator.update_real(batch) >>> # Extract features from generated images >>> for batch in gen_loader: ... calculator.update_generated(batch) >>> fid = calculator.compute()
- Parameters:
- __init__(extractor_type='radimagenet', device='cuda', **extractor_kwargs)[source][source]
Initialize FID calculator.
- update_real(images)[source][source]
Extract and store features from real images.
- Parameters:
images (
Float[Tensor, 'batch channel height width']) – Real images [B, C, H, W]- Return type:
- update_generated(images)[source][source]
Extract and store features from generated images.
- Parameters:
images (
Float[Tensor, 'batch channel height width']) – Generated images [B, C, H, W]- Return type:
- class medlatents.evaluation.PrecisionRecallCalculator(k=3, extractor_type='radimagenet', device='cuda', **extractor_kwargs)[source][source]
Bases:
objectPrecision/Recall calculator with feature extraction.
Example
>>> calculator = PrecisionRecallCalculator(k=5) >>> for batch in real_loader: ... calculator.update_real(batch) >>> for batch in gen_loader: ... calculator.update_generated(batch) >>> precision, recall = calculator.compute()
- Parameters:
- __init__(k=3, extractor_type='radimagenet', device='cuda', **extractor_kwargs)[source][source]
Initialize Precision/Recall calculator.
- update_real(images)[source][source]
Extract and store features from real images.
- Parameters:
images (
Float[Tensor, 'batch channel height width'])- Return type:
- update_generated(images)[source][source]
Extract and store features from generated images.
- Parameters:
images (
Float[Tensor, 'batch channel height width'])- Return type:
FID Bootstrap and Feature Extraction
- medlatents.evaluation.fid_from_features(real_feats, gen_feats, ridge=1e-06)[source][source]
Closed-form Fréchet Inception Distance on already-extracted features.
Uses the symmetric form
tr( (sigma_r sigma_g)^{1/2} ) = sum sqrt eig( sigma_r^{1/2} sigma_g sigma_r^{1/2} )computed via twoeighcalls. ~50× faster thanscipy.linalg.sqrtmon the 192-dim covariances used for FID-192 at low resolution, and numerically more stable (eigenvalues are non-negative by construction).
- medlatents.evaluation.bootstrap_fid_real_vs_gen(real_feats, gen_feats, n=None, B=200, seed=42, verbose=False)[source][source]
95% CI for FID(real, gen) via paired bootstrap of feature indices.
For
Breps, samplenindices with replacement from each ofreal_featsandgen_feats, recompute FID. The resulting distribution captures the estimator uncertainty at the given sample size, given a fixed underlying generator. It does not capture train-time stochasticity (which requires re-sampling the model itself). Defaultsntomin(len(real_feats), len(gen_feats)).
- medlatents.evaluation.bootstrap_fid_noise_floor(features, n_per_half=(1000, 2500, 5000, 10000), B=200, seed=42, verbose=False)[source][source]
Estimate FID’s estimator-variance noise floor via random splits.
For each
ninn_per_half, drawBrandom splits offeaturesinto two disjoint halves of sizeneach, compute FID(half_A, half_B), and return summary statistics. Because both halves come from the same underlying distribution, the resulting FID distribution characterises the minimum detectable FID gap at sample sizen— gaps below this floor are within metric noise.
Reconstruction Metrics
- medlatents.evaluation.calculate_psnr(reference, prediction, data_range=None)[source][source]
Compute peak signal-to-noise ratio in dB.
Memorization Probing
- class medlatents.evaluation.InceptionPool3FeatureExtractor(device='cpu', batch_size=64)[source][source]
Bases:
objectExtract 192-d Inception V3 pool3 features (matches FID-192).
The backbone is the same one used by
torchmetrics.image.fidwithfeature=192; sharing the feature space ensures the memorization metric and the reported FID values live on the same Inception manifold.- extract(images)[source][source]
Return
(N, 192)float features for the given images.imagesmay be(N, 1, H, W)or(N, 3, H, W), dtype uint8 or float in [0,1]. Grayscale inputs are tiled to RGB. The inception backbone intorchmetrics.image.fidexpects uint8 inputs (the normalisation is handled internally), so floats are rescaled to[0, 255]and cast.
- medlatents.evaluation.memorization_metrics(gen_features, train_features, device='cpu')[source][source]
Compute the memorization-ratio and AuthPct scalars.
Returns a dict with keys:
memorization_ratio: median(d_g->t) / median(d_t->t)auth_pct: fraction of generated samples for which d(gen, NN_train) < d(NN_train, NN2_train)median_d_gen_to_train: median nearest-neighbor distance from generated to trainingmedian_d_train_to_train: median nearest-neighbor distance within training (excluding self)mean_d_gen_to_train: mean version of the abovemean_d_train_to_train: ditton_gen,n_train: sample counts
- medlatents.evaluation.memorization_pairs(gen_features, train_features, top_k=8, device='cpu')[source][source]
Return the
top_k(gen_idx, train_idx, cosine_distance) pairs with the smallest gen→train distances — the most likely memorisation suspects to display in a side-by-side gallery.
- medlatents.evaluation.nearest_neighbor_gallery_pairs(generated_images, train_images, pairs, max_pairs=None)[source][source]
Select image tensors for generated/training nearest-neighbor galleries.
Classifier Utility
- medlatents.evaluation.build_grayscale_resnet18(num_classes)[source][source]
ResNet-18 with single-channel conv1 + multi-label classification head.
- medlatents.evaluation.train_classifier(model, train_loader, val_loader, epochs, device, lr=0.001, weight_decay=0.0001, log_fn=<built-in function print>)[source][source]
Train
modelwith BCE-with-logits, AdamW, per-epoch val AUC.Returns
{"best_val_mean_auc", "best_state_dict", "history": [...]}. The model is mutated in place; restore best state viamodel.load_state_dict(returned["best_state_dict"])before evaluation.
- medlatents.evaluation.evaluate_auc(model, loader, device, class_names=None)[source][source]
Per-class + mean ROC-AUC over a DataLoader (multi-label).
Classes for which the loader contains all-positive or all-negative labels yield NaN AUC and are excluded from the mean.