Skip to main content
Coreset sampling is a critical component of PatchCore that reduces the memory bank size from potentially millions of patch features to a manageable subset, while preserving the representation quality. This enables efficient storage and fast inference without sacrificing detection performance.

Why Coreset Sampling?

Without subsampling, the memory requirements would be prohibitive:
Example: For a dataset with 200 training images at 224×224 resolution:
  • Patches per image: 56 × 56 = 3,136
  • Total patches: 200 × 3,136 = 627,200 patches
  • With 1024-dim features: ~2.4 GB of memory
After 10% coreset sampling:
  • Sampled patches: ~62,720 patches
  • Memory: ~240 MB (10× reduction)

Sampling Strategies

PatchCore provides three sampling strategies:

Identity Sampler

No sampling - uses all features

Random Sampler

Random subset selection

Greedy Coreset

Intelligent diversity-based selection

IdentitySampler

The simplest sampler that returns all features unchanged:
sampler.py
Use IdentitySampler for small datasets or when memory is not a constraint.

RandomSampler

Randomly selects a percentage of features:
sampler.py
Random sampling is fast but may miss important feature diversity. Use it as a baseline comparison.

GreedyCoresetSampler

The recommended sampling strategy that selects a diverse subset using a greedy farthest-point algorithm:
sampler.py

Dimensionality Reduction for Speed

To accelerate distance computations, features are projected to a lower dimension:
sampler.py
The random projection is only used for distance computation during sampling. The original high-dimensional features are returned for the memory bank.

Core Algorithm

The greedy coreset selection algorithm:
sampler.py

Algorithm Breakdown

1

Initialize

Compute full pairwise distance matrix between all features
2

Select Farthest Point

Choose the point with maximum distance to already selected points (initially, maximum norm)
3

Update Distances

For each remaining point, compute its distance to the newly selected point and update minimum distances
4

Repeat

Continue until desired number of samples is reached

Distance Computation

Efficient batched Euclidean distance calculation:
sampler.py
This uses the identity: ||a - b||² = ||a||² + ||b||² - 2⟨a,b⟩ for efficient computation

ApproximateGreedyCoresetSampler

For very large feature sets, the approximate version trades some optimality for memory efficiency:
sampler.py

Approximate Algorithm

sampler.py

Key Differences

Instead of computing the full N×N distance matrix, it:
  1. Starts with distances to a small random subset
  2. Computes distances incrementally as new points are selected
  3. Memory: O(N × k) instead of O(N²) where k = number of selected samples
  • GreedyCoresetSampler: O(N²) distance computation + O(N × k) selection
  • ApproximateGreedyCoresetSampler: O(N × k²) for incremental distance updates
For small k (e.g., 10% of N), approximate version is slower but uses much less memory.
The approximate version uses mean distances to random starting points for initialization, which may not find the globally optimal coreset but works well in practice.

Usage in PatchCore

Coreset sampling is applied during the training phase:
patchcore.py

Configuration Examples

Performance vs. Sampling Rate

Finding: Greedy coreset at 10% typically loses less than 0.1% AUROC while providing 10× speedup!

Visualization: Coreset Coverage

The greedy algorithm ensures good coverage of the feature space:

Implementation Tips

GPU Acceleration: For datasets with >100k patches, ensure coreset sampling runs on GPU by passing the correct device:
Percentage Validation: The BaseSampler enforces 0 < percentage < 1:
Use decimals (0.1 for 10%), not percentages (10).

Next Steps

Anomaly Scoring

Learn how the coreset memory bank is used for scoring

PatchCore Algorithm

See how coreset fits into the full pipeline