How to use from the
Use from the
timm library
import timm

model = timm.create_model("hf-hub:hakim78/Cancer_pathos", pretrained=True)

Cancer_pathos

The patch classifier of Pathos Pro: metastasis detection on 96 px lymph node patches, evaluated on a test set opened once

Independent engineering project · 2026 · part of Pathos Pro, AI assistance for breast sentinel lymph nodes Pathos Pro logo: a lens over a lymph node, its tiles lit by attention

Live demo | Code | Results | Quick start | Files | Cite | English · Français

Abstract: Cancer_pathos is a ConvNeXt-Tiny classifier with a residual head (28.3 M parameters) that tells whether the centre of a 96 px haematoxylin and eosin patch of lymph node contains metastatic tissue. It reaches an AUC of 0.9979 [0.9975 ; 0.9982] on a locked PatchCamelyon test set of 33,004 patches that was never used for training, model selection or tuning. Five-fold cross-validation gives 0.9975 ± 0.0001. The repository also documents what the model looks at (Grad-CAM, counterfactual masking), how sure it is (Monte Carlo dropout) and which known cases resemble a query (FAISS). This is a research model. It is not a certified medical device and it must not be used for diagnosis.

Animation: a 96 px patch, five test-time views, the four ConvNeXt-Tiny stages, the residual head and the probability read against the 0.5 threshold

What is Cancer_pathos?

  • A patch-level tumour detector: one 96 × 96 px RGB patch in, one probability out. The label describes the central 32 × 32 px only, as in PatchCamelyon.
  • Measured on a locked test set: 70 / 15 / 15 stratified split, test opened once at the very end, 95% bootstrap confidence interval reported with the AUC.
  • Explainable: Grad-CAM maps, a check that attention sits on the labelled centre, and a counterfactual test that masks the attended pixels and measures the drop.
  • Aware of its doubt: Monte Carlo dropout flags uncertain patches. Reviewing the 10% most uncertain ones catches 20.2% of the errors.
  • One brick of a product: in Pathos Pro it supplies Grad-CAM, uncertainty and similar cases at tile level. The whole-slide verdict comes from another model, described below.

Why it matters: on sentinel lymph nodes, AI assistance raised micrometastasis sensitivity from 83.3% to 91.2% and cut the review time of micrometastases from 116 s to 61 s (Steiner et al., Am J Surg Pathol 2018). A patch model is the smallest unit of such assistance, and the place where its claims are easiest to check.

Updates

  • 11/14/2026: Model card rewritten with animations, the v2 figures and a tested loading snippet.
  • 10/12/2026: The Pathos Pro whole-slide verdict moves to H-optimus-0 with attention pooling. This patch model stays in the product for tile-level explanation.
  • 09/09/2026: Master's thesis defended.
  • 06/15/2026: v2 released: strict three-way split, five-fold cross-validation, locked test, DeLong test on the gain of test-time augmentation.
  • Earlier in 2026: v1 training run (50 epochs on about 95% of the labels). Its checkpoints are kept here for history only.

How it works

1. From a patch to a probability

  • Input: RGB patch, 96 × 96 px, ImageNet normalisation (mean [0.485, 0.456, 0.406], std [0.229, 0.224, 0.225]).
  • Backbone: timm convnext_tiny, ImageNet initialisation, no classification layer, 768-dimensional features (27.82 M parameters).
  • Head: residual MLP, 768 → 256 → 256 → 1 with batch normalisation, GELU, dropout 0.3 and a linear shortcut (460,801 parameters). One logit, then a sigmoid.
  • Test-time augmentation ×5: original, horizontal flip, vertical flip, 90° rotation and transpose. The five probabilities are averaged.

2. Training

Setting Value
Data PatchCamelyon as distributed by the Kaggle Histopathologic Cancer Detection challenge, 220,025 labelled patches, 40.50% tumour
Split 70 / 15 / 15 stratified, seed 42: 154,017 train · 33,004 validation · 33,004 locked test
Loss Focal loss, α = 0.25, γ = 2.0
Optimiser AdamW, learning rate 1e-4, weight decay 1e-5
Schedule CosineAnnealingLR, 20 epochs at most, early stopping on validation AUC with patience 4
Batch and precision 64, automatic mixed precision
Augmentation Albumentations: flips, 90° rotations, transpose, shift-scale-rotate, elastic and grid distortion, colour jitter, hue-saturation, CLAHE, noise, blur, coarse dropout
Hardware One NVIDIA Tesla T4

3. Evaluation protocol

Animation: 220,025 patches split into train, validation and a locked test; cross-validation, then the final model, then the test opened once
  • Cross-validation first: five folds on train + validation with identical hyperparameters, to measure the spread before touching the test set.
  • Then one final model, early-stopped on the validation split.
  • Then the test set, once: no threshold, epoch or hyperparameter was chosen on it.

Results

All values come from the result files in results_v2/. No value is rounded up.

Metric 5-fold cross-validation Locked test, TTA ×5 Locked test, no TTA
AUC-ROC 0.9975 ± 0.0001 0.9979 [0.9975 ; 0.9982] 0.9974
Accuracy 0.9821 ± 0.0008 0.9847 0.9827
F1 0.9778 ± 0.0010 0.9810 0.9787
Sensitivity 0.9753 ± 0.0015 0.9794 0.9779
Specificity 0.9867 ± 0.0006 0.9882 0.9860
Brier score 0.0212 ± 0.0005 0.0172 0.0183

Confusion matrix on the 33,004 test patches at threshold 0.5: 19,405 true negatives, 231 false positives, 275 false negatives, 13,093 true positives.

ROC curves over the five cross-validation folds with their confidence band Confusion matrix on the locked test set

Reliability diagram on the locked test set Bootstrap distribution of the test AUC and its 95% interval

Top: ROC over the five cross-validation folds, and confusion matrix on the locked test (counts, then share per row). Bottom: reliability diagram, and bootstrap distribution of the test AUC (2,000 resamples). Some figure labels are in French.

Test-time augmentation: the gain is statistically significant (paired DeLong test, z = 6.62, p = 3.5 × 10⁻¹¹) and small in size, +0.00045 AUC. It is kept for stability, not for performance.

Calibration: Brier score 0.0172, expected calibration error 0.0449 on the locked test.

Explainability

Grad-CAM maps on tumour and normal patches

Grad-CAM on locked-test patches: tumour on the top row, normal tissue on the bottom row.

  • Attention on the labelled centre: the centre-to-periphery attention ratio is 1.96 on tumour patches and 0.60 on normal ones (300 patches).
  • Counterfactual masking: hiding the 20% most attended pixels lowers the tumour probability by a median of 0.085 (250 patches). 44% of patches drop by more than 0.1.

Uncertainty

Triage curve: share of errors caught against share of patches reviewed, ranked by uncertainty

Share of the model's errors caught (vertical) against share of patches reviewed (horizontal), most uncertain first. The dashed line is a random review.

Monte Carlo dropout, 30 passes on 20,000 locked-test patches (346 errors):

  • Wrong predictions are 1.68 times more uncertain than correct ones (standard deviation 0.0142 against 0.0085, one-sided Mann-Whitney p = 5.6 × 10⁻⁷⁰).
  • Reviewing the 10% most uncertain patches catches 20.2% of the errors. That set holds 3.50% errors against 1.73% overall, an enrichment of ×2.02.
  • The errors concentrate near the decision threshold.

Similar cases

The 768-dimensional features are indexed with FAISS (exact flat index, cosine similarity). With a base of 20,000 training patches and 1,000 test queries, 97.9% of the five nearest neighbours share the class of the query (98.2% normal, 97.6% tumour).

What these numbers do not say

  • Patch level only. A 1.18% false-positive rate per patch adds up over the thousands of patches of a slide. This model alone does not give a slide-level answer.
  • One dataset. PatchCamelyon comes from two Dutch centres. No other centre, scanner or staining protocol was tested with this model.
  • The split is by patch, not by slide. Patches from the same slide can sit in train and in test, so the test figures and the FAISS precision are optimistic compared with a slide-level split.
  • Uncertainty covers the head only. The backbone has no stochastic depth, so the Monte Carlo dropout standard deviations are small in absolute value.
  • The only published reference on this benchmark is Veeling et al., 2018, AUC 0.963. This model was never submitted to the Kaggle leaderboard.
  • Self-reported results from a single developer, without an external audit.

Where it sits in Pathos Pro

End-to-end flow of Pathos Pro: the slide arrives, vision analyses it, the pathologist records an impression first, the copilot answers with sources, the decision is signed

Pathos Pro is a complete second-read system for breast sentinel lymph nodes: slide intake, whole-slide analysis, a viewer that records the pathologist's impression before showing any AI output, a sourced copilot and an audit journal. The slide-level verdict is not produced by this patch model. It comes from H-optimus-0 tile features pooled by gated-attention multiple instance learning:

Level Data Model Metric Value
Patch PatchCamelyon, locked test, 33,004 patches This model, TTA ×5 AUC [95% CI] 0.9979 [0.9975 ; 0.9982]
Slide CAMELYON16 test, 129 slides ABMIL + H-optimus-0, five-fold ensemble AUC 0.9949
Slide, external SLN-Breast, 130 slides, 36 positive Same ensemble, no retraining AUC [95% CI] 0.9566 [0.9019 ; 0.9964]

The slide-level weights are not in this repository. Code, design notes and the full product description are on GitHub.

Files in this repository

Path Content
models/final_model_v2_locked.pth The model described on this page (v2, raw state_dict, 113 MB). Also the one served by the demo.
results_v2/ Test metrics, cross-validation folds, DeLong and bootstrap significance, summary table
assets/ Animations and v2 figures of this page
models/best_model_epoch*.pth v1 training history, 31 checkpoints of 340 MB each. Their file names carry validation AUCs, which also drove early stopping. Do not quote them as results.
figures/ v1 figures, measured on the v1 validation split. Kept for history.

Quick start

pip install torch timm huggingface_hub
import torch, timm
import torch.nn as nn
from huggingface_hub import hf_hub_download


class ResidualHead(nn.Module):
    def __init__(self, in_features, hidden=256, dropout=0.3):
        super().__init__()
        self.fc1, self.bn1 = nn.Linear(in_features, hidden), nn.BatchNorm1d(hidden)
        self.fc2, self.bn2 = nn.Linear(hidden, hidden), nn.BatchNorm1d(hidden)
        self.fc_out, self.shortcut = nn.Linear(hidden, 1), nn.Linear(in_features, hidden)
        self.gelu, self.dropout = nn.GELU(), nn.Dropout(dropout)

    def forward(self, x):
        identity = self.shortcut(x)
        out = self.dropout(self.gelu(self.bn1(self.fc1(x))))
        out = self.gelu(self.bn2(self.fc2(out)) + identity)
        return self.fc_out(self.dropout(out))


class CancerClassifier(nn.Module):
    def __init__(self):
        super().__init__()
        self.backbone = timm.create_model("convnext_tiny", pretrained=False, num_classes=0)
        self.head = ResidualHead(self.backbone.num_features)

    def forward(self, x):
        return self.head(self.backbone(x))


model = CancerClassifier()
path = hf_hub_download("hakim78/Cancer_pathos", "models/final_model_v2_locked.pth")
model.load_state_dict(torch.load(path, map_location="cpu", weights_only=True))
model.eval()


def predict(x):
    """x: float tensor (N, 3, 96, 96), ImageNet-normalised. Returns the tumour probability, TTA x5."""
    views = [x, x.flip(-1), x.flip(-2), x.rot90(1, (-2, -1)), x.transpose(-2, -1)]
    with torch.no_grad():
        return torch.stack([torch.sigmoid(model(v)) for v in views]).mean(0)

This snippet was run against the published file: all keys match and the model counts 28,280,929 parameters.

Or try it in the browser: Cancer_pathos_demo (CPU Space, about 0.8 s per patch once warm, test-time augmentation included).

Intended use

Research and teaching on computational pathology: benchmarking, explainability studies, a feature extractor for tile-level analysis. Patches should match PatchCamelyon: haematoxylin and eosin, lymph node tissue, about 0.97 µm per pixel (10× equivalent).

Out of scope: any diagnostic use, any decision about a patient, other organs or stains, other magnifications without rescaling. This model is not a medical device and carries no CE marking.

License and Terms of Use

Weights and code are released under the MIT License, for research use. PatchCamelyon is derived from CAMELYON16 and distributed under CC0. No patient data is stored in this repository.

Acknowledgements

This work builds on PatchCamelyon (Veeling et al., 2018), the CAMELYON16 challenge, ConvNeXt (Liu et al., 2022) and timm, Grad-CAM (Selvaraju et al., 2017), and the Mahmood Lab's UNI and CLAM repositories, whose README conventions this page follows.

Reference

@software{djaalal2026pathos,
  author = {Djaalal, Hakim},
  title  = {Pathos Pro: AI assistance for breast sentinel lymph node metastasis detection},
  year   = {2026},
  url    = {https://github.com/Hakim78/histopathologic-cancer-detection}
}

Pathos Pro

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Space using hakim78/Cancer_pathos 1

Papers for hakim78/Cancer_pathos