Instructions to use originbio/TinyPath with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use originbio/TinyPath with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-feature-extraction", model="originbio/TinyPath", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoImageProcessor, AutoModel processor = AutoImageProcessor.from_pretrained("originbio/TinyPath", trust_remote_code=True) model = AutoModel.from_pretrained("originbio/TinyPath", trust_remote_code=True, device_map="auto") - timm
How to use originbio/TinyPath with timm:
import timm model = timm.create_model("hf-hub:originbio/TinyPath", pretrained=True) - Notebooks
- Google Colab
- Kaggle
TinyPath
TinyPath is a 103.6M-parameter Vision Transformer for H&E histopathology tiles. It was pruned from Prov-GigaPath (1.13B parameters) and then distilled from it.
- Architecture: ViT with 33 blocks, width 640, 10 heads, patch size 16 and a SwiGLU MLP
- Input: 224 Γ 224 RGB tiles
- Output: a 640-d CLS embedding and 196 patch tokens
- Teacher: Prov-GigaPath
Evaluation
TinyPath and Prov-GigaPath were run through the same evaluation pipeline, and the other three models' scores are published. H0-mini's come from the HEST and PLISM leaderboards and, for EVA, from its paper. H-optimus-0's come from the HEST, EVA 0.4.5 and PLISM leaderboards, and DistillPath-KS16-HOpt0's from its paper. Error bars are Β±1 SD over repeated runs (Β±1 SEM over folds for PORPOISE); the published scores have none.
- Higher is better on every benchmark: Pearson r for HEST, balanced accuracy for the EVA classification tasks, Dice for EVA MoNuSAC, the leaderboard score and its components for PLISM, c-index for PORPOISE and AUROC for GTEx.
- A missing bar or a dash means that model has no published score on that benchmark.
- PLISM measures robustness to scanner and stain changes rather than accuracy. It is run two ways: on its 224 px tiles unresized, the setting of its public leaderboard and of H0-mini's own preprocessing, and with tiles resized to 256 px and center-cropped to 224, as PLISM's code now does for Prov-GigaPath. The PLISM figure uses 224 px, the only setting with scores for every model.
- H0-mini is Bioptimus's 86M-parameter ViT-B, distilled from H-optimus-0 (1.1B parameters) on the same 6,093 TCGA slides as TinyPath. All its scores here use the class token, like TinyPath's. Its EVA scores come from its paper's table, which has no BreakHis or Gleason. The paper's HEST score (0.4044) concatenates the class token with the mean patch token, so the HEST leaderboard's class-token score is used instead.
- On HEST, H0-mini scores higher than TinyPath but keeps less of its teacher: 95.4% of H-optimus-0's score, where TinyPath keeps 98.6% of Prov-GigaPath's. Under its paper's protocol it keeps 95.7% (0.4044 against H-optimus-0's 0.4224). The two students differ in more than their teachers, though: H0-mini is a ViT-B with 14 px patches and four register tokens, does not start from its teacher's weights, distills through its teacher's pretrained projection heads, which Prov-GigaPath does not ship, and saw about 215M tiles, 2.7 times TinyPath's 78.9M. Retention alone cannot say which of these differences matters.
- DistillPath-KS16-HOpt0 is kaiko's 22M-parameter ViT-S/16, further distilled from H-optimus-0's class and patch tokens on 6,000 TCGA slides. Its paper uses the same EVA, HEST and PLISM protocols but reports PLISM retrieval at top-5 rather than top-10, so only its PLISM score and median cosine are listed.
- TinyPath and H0-mini were trained without labels on the same 6,093 TCGA slides, which include slides from 18 of MoNuSAC's 25 test patients and 443 of PORPOISE's 444 patients. Prov-GigaPath never saw TCGA.
Exact numbers
| Benchmark | Metric (split) | Better | TinyPath | Prov-GigaPath | H0-mini (published) | H-optimus-0 (published) | DistillPath-KS16-HOpt0 (published) |
|---|---|---|---|---|---|---|---|
| HEST, mean of 9 tasks | Pearson r | Higher | 0.3822 | 0.3875 | 0.3958 | 0.4150 | 0.376 |
| EVA PatchCamelyon | Balanced accuracy (test), 5 runs | Higher | 0.9462 Β± 0.0010 | 0.9436 Β± 0.0015 | 0.942 | 0.943 | 0.921 |
| EVA CRC | Balanced accuracy (val), 5 runs | Higher | 0.9571 Β± 0.0006 | 0.9519 Β± 0.0014 | 0.961 | 0.955 | 0.943 |
| EVA BACH | Balanced accuracy (val), 5 runs | Higher | 0.7601 Β± 0.0135 | 0.7637 Β± 0.0025 | 0.774 | 0.759 | 0.742 |
| EVA Gleason (Arvaniti) | Balanced accuracy (val), 5 runs | Higher | 0.7346 Β± 0.0092 | 0.7246 Β± 0.0100 | β | 0.770 | 0.756 |
| EVA BreakHis | Balanced accuracy (val), 5 runs | Higher | 0.7875 Β± 0.0098 | 0.8288 Β± 0.0084 | β | 0.801 | 0.690 |
| EVA Camelyon16-small | Balanced accuracy (test), 20 runs | Higher | 0.8368 Β± 0.0221 | 0.8036 Β± 0.0308 | 0.842 | 0.827 | β |
| EVA Camelyon16, 10,000 patches per slide | Balanced accuracy (test), 20 runs | Higher | 0.9340 Β± 0.0126 | 0.8897 Β± 0.0316 | β | β | β |
| EVA PatchCamelyon 10-shot | Balanced accuracy (test), 50 runs | Higher | 0.8628 Β± 0.0397 | 0.8477 Β± 0.0492 | β | β | β |
| EVA MoNuSAC | Dice (release test split), 5 runs | Higher | 0.6443 Β± 0.0065 | 0.6834 Β± 0.0066 | 0.643 | 0.685 | 0.634 |
| PLISM | Leaderboard score (8,139 positions, 256 px) | Higher | 0.520 | 0.320 | β | β | β |
| PLISM | Leaderboard score (8,139 positions, 224 px) | Higher | 0.530 | 0.333 | 0.541 | 0.480 | 0.480 |
| PORPOISE LUAD | Overall-survival c-index, fold mean Β± SEM | Higher | 0.5816 Β± 0.0221 | 0.5534 Β± 0.0235 | β | β | β |
| GTEx findings (5 tasks) | Mean AUROC, ABMIL | Higher | 0.7587 | 0.7699 | β | β | β |
| GTEx findings (5 tasks) | Mean AUROC, mean-pool logistic regression | Higher | 0.7426 | 0.7349 | β | β | β |
| GTEx findings (5 tasks) | Mean AUROC, slide linear probe | Higher | 0.7501 | 0.7470 | β | β | β |
| GTEx findings (5 tasks) | Mean AUROC, slide k-NN probe | Higher | 0.7259 | 0.7321 | β | β | β |
HEST, Pearson r per task (higher is better):
| Encoder | IDC | PRAD | PAAD | SKCM | COAD | READ | CCRCC | LUNG | LYMPH_IDC | Mean |
|---|---|---|---|---|---|---|---|---|---|---|
| TinyPath | 0.5679 | 0.3759 | 0.4722 | 0.5474 | 0.2688 | 0.1672 | 0.2395 | 0.5454 | 0.2553 | 0.3822 |
| Prov-GigaPath | 0.5515 | 0.3698 | 0.4746 | 0.5618 | 0.2992 | 0.1960 | 0.2429 | 0.5411 | 0.2500 | 0.3875 |
| H0-mini (published) | 0.5862 | 0.3687 | 0.4919 | 0.6012 | 0.2494 | 0.1863 | 0.2670 | 0.5482 | 0.2629 | 0.3958 |
| H-optimus-0 (published) | 0.5976 | 0.3848 | 0.4911 | 0.6454 | 0.3086 | 0.2216 | 0.2676 | 0.5590 | 0.2591 | 0.4150 |
| DistillPath-KS16-HOpt0 (published) | 0.554 | 0.349 | 0.458 | 0.554 | 0.261 | 0.177 | 0.228 | 0.546 | 0.256 | 0.376 |
PLISM by component over 8,139 positions (higher is better in every column). TinyPath and Prov-GigaPath ran in float16:
| Encoder | Input | Median cosine, all pairs | Top-10, scanner only | Top-10, staining only | Top-10, both differ | Leaderboard | Mean cosine |
|---|---|---|---|---|---|---|---|
| TinyPath | 256 px | 0.7460 | 0.9082 | 0.2681 | 0.1581 | 0.520 | 0.7192 |
| Prov-GigaPath | 256 px | 0.5533 | 0.5659 | 0.1098 | 0.0489 | 0.320 | 0.5388 |
| TinyPath | 224 px | 0.7556 | 0.9218 | 0.2737 | 0.1686 | 0.530 | 0.7283 |
| Prov-GigaPath | 224 px | 0.5704 | 0.5920 | 0.1178 | 0.0539 | 0.333 | 0.5547 |
| H0-mini (published) | 224 px | 0.800 | 0.864 | 0.318 | 0.183 | 0.541 | β |
| H-optimus-0 (published) | 224 px | 0.685 | 0.744 | 0.327 | 0.166 | 0.480 | β |
| DistillPath-KS16-HOpt0 (published) | 224 px | 0.656 | β | β | β | 0.480 | β |
Usage
pip install -r requirements.txt
Tiles are resized to 256 px on the shorter side (bicubic), center-cropped to 224 and normalized with ImageNet statistics. AutoImageProcessor and the timm transform do this for you.
transformers
import torch
from PIL import Image
from transformers import AutoImageProcessor, AutoModel
processor = AutoImageProcessor.from_pretrained("<org>/tinypath")
model = AutoModel.from_pretrained("<org>/tinypath", trust_remote_code=True).eval()
image = Image.open("patch.png").convert("RGB")
with torch.no_grad():
outputs = model(processor(image, return_tensors="pt")["pixel_values"], pool_mode="cls")
embedding = outputs.pooler_output # [1, 640]
tokens = outputs.last_hidden_state # [1, 197, 640]
Without trust_remote_code, the same weights load into transformers' built-in TimmWrapperModel.
timm
import timm
model = timm.create_model("hf-hub:<org>/tinypath", pretrained=True).eval()
transform = timm.data.create_transform(**timm.data.resolve_data_config({}, model=model))
with torch.no_grad():
embedding = model(transform(image).unsqueeze(0)) # [1, 640]
uint8 encoder
From a local copy of this repository:
from modeling_tinypath import build_encoder, eval_transform
encoder = build_encoder(".")
with torch.no_grad():
embedding = encoder(eval_transform()(image).unsqueeze(0)) # [1, 640]
python run_inference.py checks that every interface loads all weights and returns identical outputs.
- Downloads last month
- 19


