taejoon89 commited on
Commit
507d72b
ยท
verified ยท
1 Parent(s): b57d99f

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. README.md +24 -20
  2. eval/st_bench.py +3 -3
README.md CHANGED
@@ -12,18 +12,21 @@ library_name: pytorch
12
  pipeline_tag: image-feature-extraction
13
  ---
14
 
15
- # OpenPath โ€” Pathology Foundation Model (training & evaluation code)
 
 
16
 
17
  **OpenPath** is a vision foundation model for computational pathology: a **ViT-g/14** encoder
18
  pre-trained with self-supervision (**DINOv2** + **gram anchoring**) on **public-only** whole-slide
19
  histopathology tiles. This repository contains the **training, reproduction, and evaluation code**.
20
  The corpus and checkpoints are hosted separately (see below).
21
 
22
- > **Headline result.** On a **contamination-free** in-house spatial-transcriptomics (ST) cohort โ€” the
23
- > least leakage-prone benchmark, since no public foundation model was trained on it โ€” OpenPath **ranks
24
- > #1 among seven foundation models** (mean Pearson: OpenPath **0.323** > UNI2-h 0.301 > OpenMidnight
25
- > 0.300 > Virchow2 0.292 > prov-gigapath 0.286 > Phikon-v2 0.274 > UNI 0.257). Released checkpoint:
26
- > **`training_316250`** (in `openpath-checkpoints`). See [Evaluation](#evaluation).
 
27
 
28
  - **Encoder:** ViT-g/14 (reg4), 1536-dim CLS embedding
29
  - **Objective:** DINO + iBOT + KDE (DINOv2) with **gram anchoring** ported from DINOv3
@@ -47,7 +50,7 @@ scripts/
47
  run_hest_3way.py # HEST evaluation (Meta DINOv2 / Phikon-v2 / OpenPath)
48
  eval/ # downstream benchmark / reference-FM comparison
49
  openpath_eva_backbone.py # backbone factories: OpenPath + Phikon / OpenMidnight / UNI / UNI2-h / gigapath / Virchow2
50
- st_bench.py # in-house spatial-transcriptomics benchmark (LOPO ridge, headline)
51
  run_patch_eval.sh # PCam / CRC / BACH patch probing via kaiko-eva
52
  eva_configs/ # eva YAML configs (crc / bach / patch_camelyon)
53
  requirements.txt
@@ -110,15 +113,16 @@ cls = m.forward_features(x)["x_norm_clstoken"] # (B, 1536)
110
 
111
  ## Evaluation
112
 
113
- Frozen-encoder linear/ridge probing. The headline benchmark is a **contamination-free** in-house
114
- Visium spatial-transcriptomics (ST) cohort (leave-one-patient-out, mean Pearson over top-50
115
- highly-variable genes) โ€” **no public FM was trained on it**, so it is the least leakage-prone
116
- comparison. The reported OpenPath checkpoint is `training_316250`.
 
117
 
118
  **Comparison** โ€” all 7 models loaded through one backbone factory and probed under an identical
119
- protocol; sorted by the clean ST benchmark:
120
 
121
- | Model | ST (in-house, clean) โ†“ | HEST-1K (public) | NCT-CRC-HE (9-cls acc) | BACH (4-cls acc) |
122
  |---|---|---|---|---|
123
  | **OpenPath** | **0.323** | 0.372 | 0.954 | 0.761 |
124
  | UNI2-h | 0.301 | 0.414 | 0.966 | 0.908 |
@@ -128,12 +132,12 @@ protocol; sorted by the clean ST benchmark:
128
  | Phikon-v2 | 0.274 | 0.375 | 0.937 | 0.708 |
129
  | UNI | 0.257 | 0.386 | 0.946 | 0.777 |
130
 
131
- **On the contamination-free ST cohort OpenPath ranks #1** among all seven foundation models. The
132
- picture inverts on the **public** benchmarks (HEST-1K, CRC, BACH): there OpenPath is mid-pack to
133
  low, and the large FMs lead. Those benchmarks derive from public repositories (TCGA/GTEx/etc.) that
134
  these FMs were pre-trained on, so their apparent edge is confounded by **train/test leakage** โ€” which
135
- is exactly why the leakage-free in-house ST cohort is our headline. (The reported checkpoint
136
- `training_316250` is selected by ST; OpenPath's HEST-1K peaks earlier in training at ~0.38.)
137
  PCam / CAMELYON is excluded because it overlaps our own training corpus.
138
 
139
  ### Reproducing the comparison
@@ -144,7 +148,7 @@ UNI2-h, gigapath, Virchow2) are directly comparable.
144
 
145
  ```bash
146
  export PYTHONPATH="$PWD/OpenPath:$PWD/eval"
147
- # Headline: in-house spatial-transcriptomics (LOPO ridge; cohort is private, code is provided)
148
  python eval/st_bench.py --backbone openpath --weights <teacher_checkpoint.pth>
149
  python eval/st_bench.py --backbone uni # reference FM (also: uni2 / gigapath / virchow2 / phikon / openmidnight)
150
 
@@ -168,7 +172,7 @@ decision-making.
168
  - **Public-benchmark leakage.** Public benchmarks (HEST-1K, NCT-CRC-HE, BACH) derive from repositories
169
  (TCGA/GTEx/โ€ฆ) that many foundation models โ€” and partly OpenPath โ€” were pre-trained on. Absolute
170
  numbers and cross-model rankings on them are confounded; prefer leakage-controlled evaluation.
171
- - **Checkpoint trade-off.** The released `training_316250` is selected by the clean ST benchmark;
172
  earlier checkpoints score higher on HEST-1K (~0.38). Pick a checkpoint to match your downstream task.
173
  - **Domain.** Trained on H&E WSIs at native magnification. Behavior on IHC, cytology, frozen sections,
174
  non-0.5 ยตm-per-pixel inputs, or non-pathology images is untested.
@@ -181,7 +185,7 @@ A paper is in preparation. Until then, please cite the repository and the upstre
181
 
182
  ```bibtex
183
  @misc{openpath2026,
184
- title = {OpenPath: a public-data pathology foundation model},
185
  author = {OpenPath authors},
186
  year = {2026},
187
  note = {https://huggingface.co/taejoon89/openpath}
 
12
  pipeline_tag: image-feature-extraction
13
  ---
14
 
15
+ # OpenPath: Public-Data Pathology Foundation Models and Leakage-Free Evaluation
16
+
17
+ *Training, reproduction, and evaluation code.*
18
 
19
  **OpenPath** is a vision foundation model for computational pathology: a **ViT-g/14** encoder
20
  pre-trained with self-supervision (**DINOv2** + **gram anchoring**) on **public-only** whole-slide
21
  histopathology tiles. This repository contains the **training, reproduction, and evaluation code**.
22
  The corpus and checkpoints are hosted separately (see below).
23
 
24
+ > **Headline result.** On **AMC-HCC-ST** โ€” a contamination-free in-house Asan Medical Center
25
+ > hepatocellular-carcinoma spatial-transcriptomics cohort, the least leakage-prone benchmark since no
26
+ > public foundation model was trained on it โ€” OpenPath **ranks #1 among seven foundation models** (mean
27
+ > Pearson: OpenPath **0.323** > UNI2-h 0.301 > OpenMidnight 0.300 > Virchow2 0.292 > prov-gigapath 0.286
28
+ > > Phikon-v2 0.274 > UNI 0.257). Released checkpoint: **`training_316250`** (in `openpath-checkpoints`).
29
+ > See [Evaluation](#evaluation).
30
 
31
  - **Encoder:** ViT-g/14 (reg4), 1536-dim CLS embedding
32
  - **Objective:** DINO + iBOT + KDE (DINOv2) with **gram anchoring** ported from DINOv3
 
50
  run_hest_3way.py # HEST evaluation (Meta DINOv2 / Phikon-v2 / OpenPath)
51
  eval/ # downstream benchmark / reference-FM comparison
52
  openpath_eva_backbone.py # backbone factories: OpenPath + Phikon / OpenMidnight / UNI / UNI2-h / gigapath / Virchow2
53
+ st_bench.py # AMC-HCC-ST benchmark (LOPO ridge, headline)
54
  run_patch_eval.sh # PCam / CRC / BACH patch probing via kaiko-eva
55
  eva_configs/ # eva YAML configs (crc / bach / patch_camelyon)
56
  requirements.txt
 
113
 
114
  ## Evaluation
115
 
116
+ Frozen-encoder linear/ridge probing. The headline benchmark is **AMC-HCC-ST** โ€” a
117
+ **contamination-free** in-house Asan Medical Center hepatocellular-carcinoma Visium
118
+ spatial-transcriptomics cohort (leave-one-patient-out, mean Pearson over top-50 highly-variable
119
+ genes) โ€” **no public FM was trained on it**, so it is the least leakage-prone comparison. The
120
+ reported OpenPath checkpoint is `training_316250`.
121
 
122
  **Comparison** โ€” all 7 models loaded through one backbone factory and probed under an identical
123
+ protocol; sorted by the clean AMC-HCC-ST benchmark:
124
 
125
+ | Model | AMC-HCC-ST (clean) โ†“ | HEST-1K (public) | NCT-CRC-HE (9-cls acc) | BACH (4-cls acc) |
126
  |---|---|---|---|---|
127
  | **OpenPath** | **0.323** | 0.372 | 0.954 | 0.761 |
128
  | UNI2-h | 0.301 | 0.414 | 0.966 | 0.908 |
 
132
  | Phikon-v2 | 0.274 | 0.375 | 0.937 | 0.708 |
133
  | UNI | 0.257 | 0.386 | 0.946 | 0.777 |
134
 
135
+ **On the contamination-free AMC-HCC-ST cohort OpenPath ranks #1** among all seven foundation models.
136
+ The picture inverts on the **public** benchmarks (HEST-1K, CRC, BACH): there OpenPath is mid-pack to
137
  low, and the large FMs lead. Those benchmarks derive from public repositories (TCGA/GTEx/etc.) that
138
  these FMs were pre-trained on, so their apparent edge is confounded by **train/test leakage** โ€” which
139
+ is exactly why the leakage-free AMC-HCC-ST cohort is our headline. (The reported checkpoint
140
+ `training_316250` is selected by AMC-HCC-ST; OpenPath's HEST-1K peaks earlier in training at ~0.38.)
141
  PCam / CAMELYON is excluded because it overlaps our own training corpus.
142
 
143
  ### Reproducing the comparison
 
148
 
149
  ```bash
150
  export PYTHONPATH="$PWD/OpenPath:$PWD/eval"
151
+ # Headline: AMC-HCC-ST (LOPO ridge; cohort is private, code is provided)
152
  python eval/st_bench.py --backbone openpath --weights <teacher_checkpoint.pth>
153
  python eval/st_bench.py --backbone uni # reference FM (also: uni2 / gigapath / virchow2 / phikon / openmidnight)
154
 
 
172
  - **Public-benchmark leakage.** Public benchmarks (HEST-1K, NCT-CRC-HE, BACH) derive from repositories
173
  (TCGA/GTEx/โ€ฆ) that many foundation models โ€” and partly OpenPath โ€” were pre-trained on. Absolute
174
  numbers and cross-model rankings on them are confounded; prefer leakage-controlled evaluation.
175
+ - **Checkpoint trade-off.** The released `training_316250` is selected by the clean AMC-HCC-ST benchmark;
176
  earlier checkpoints score higher on HEST-1K (~0.38). Pick a checkpoint to match your downstream task.
177
  - **Domain.** Trained on H&E WSIs at native magnification. Behavior on IHC, cytology, frozen sections,
178
  non-0.5 ยตm-per-pixel inputs, or non-pathology images is untested.
 
185
 
186
  ```bibtex
187
  @misc{openpath2026,
188
+ title = {OpenPath: Public-Data Pathology Foundation Models and Leakage-Free Evaluation},
189
  author = {OpenPath authors},
190
  year = {2026},
191
  note = {https://huggingface.co/taejoon89/openpath}
eval/st_bench.py CHANGED
@@ -1,5 +1,5 @@
1
  #!/usr/bin/env python
2
- """HEST-style spatial-transcriptomics(ST) ๋ฒค์น˜๋งˆํฌ โ€” in-house Visium ์ฝ”ํ˜ธํŠธ.
3
  ๊ฐ spot์—์„œ WSI ํŒจ์น˜ ์ถ”์ถœ โ†’ FM ์ž„๋ฒ ๋”ฉ(CLS) โ†’ PCA โ†’ Ridge ํšŒ๊ท€๋กœ ์ƒ์œ„ HVG ๋ฐœํ˜„ ์˜ˆ์ธก
4
  โ†’ Pearson ์ƒ๊ด€(์œ ์ „์žํ‰๊ท ). Leave-one-patient-out CV.
5
 
@@ -20,7 +20,7 @@ from scipy.stats import pearsonr
20
  import torchvision.transforms as T
21
 
22
  ROOT = os.environ.get("OPENPATH_ROOT", os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # repo ๋ฃจํŠธ(eval/์˜ ์ƒ์œ„)
23
- DATA = os.environ.get("ST_ROOT", f"{ROOT}/data/st_bench") # in-house Visium ST ์ฝ”ํ˜ธํŠธ(๋น„๊ณต๊ฐœ; ์ฝ”๋“œ๋งŒ ๊ณต๊ฐœ)
24
  IMAGENET_MEAN = (0.485, 0.456, 0.406); IMAGENET_STD = (0.229, 0.224, 0.225)
25
 
26
 
@@ -169,7 +169,7 @@ def main():
169
 
170
  overall = float(np.mean(per_gene_corr))
171
  tag = args.tag or args.backbone
172
- print(f"[ST RESULT] backbone={tag} | LOPO mean Pearson = {overall:.4f} (folds={len(pats)}, HVG={args.k_genes})", flush=True)
173
 
174
 
175
  if __name__ == "__main__":
 
1
  #!/usr/bin/env python
2
+ """AMC-HCC-ST ๋ฒค์น˜๋งˆํฌ โ€” Asan Medical Center HCC Visium spatial-transcriptomics ์ฝ”ํ˜ธํŠธ(๋น„๊ณต๊ฐœ).
3
  ๊ฐ spot์—์„œ WSI ํŒจ์น˜ ์ถ”์ถœ โ†’ FM ์ž„๋ฒ ๋”ฉ(CLS) โ†’ PCA โ†’ Ridge ํšŒ๊ท€๋กœ ์ƒ์œ„ HVG ๋ฐœํ˜„ ์˜ˆ์ธก
4
  โ†’ Pearson ์ƒ๊ด€(์œ ์ „์žํ‰๊ท ). Leave-one-patient-out CV.
5
 
 
20
  import torchvision.transforms as T
21
 
22
  ROOT = os.environ.get("OPENPATH_ROOT", os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # repo ๋ฃจํŠธ(eval/์˜ ์ƒ์œ„)
23
+ DATA = os.environ.get("ST_ROOT", f"{ROOT}/data/st_bench") # AMC-HCC-ST ์ฝ”ํ˜ธํŠธ(๋น„๊ณต๊ฐœ; ์ฝ”๋“œ๋งŒ ๊ณต๊ฐœ)
24
  IMAGENET_MEAN = (0.485, 0.456, 0.406); IMAGENET_STD = (0.229, 0.224, 0.225)
25
 
26
 
 
169
 
170
  overall = float(np.mean(per_gene_corr))
171
  tag = args.tag or args.backbone
172
+ print(f"[AMC-HCC-ST RESULT] backbone={tag} | LOPO mean Pearson = {overall:.4f} (folds={len(pats)}, HVG={args.k_genes})", flush=True)
173
 
174
 
175
  if __name__ == "__main__":