PathoCNN β€” PathMNIST colorectal histology classifier

A compact CNN (288,809 parameters), designed and trained from scratch for 9-class classification of 28Γ—28 H&E colorectal histology patches, released with something most model uploads don't have: a script that re-derives every headline metric from the shipped weights and data, so the numbers below are checkable, not just claimed.

  • Test accuracy 0.8712 and macro one-vs-rest AUC 0.9855 on the PathMNIST test split (7,180 patches), vs a 0.1864 majority-class baseline β€” independently reproduced from the artifacts in this repo on 2026-10-28 (see Verify it yourself).
  • The test split is CRC-VAL-HE-7K, collected at a different clinical center than the training data β€” so these numbers include a real cross-center generalization gap (validation accuracy on same-center data was 0.9629). That gap is part of the result, not a footnote.
  • Weights in three formats: model.safetensors, the training checkpoint (assets/pathocnn.pt), and ONNX (pathocnn.onnx, parity vs PyTorch measured at 5.7e-06 max logit difference).
  • Trained from scratch by Habib Ur Rehman; sibling release to SonoCNN (BreastMNIST).

Research and benchmark use only. This is a 28Γ—28 benchmark model. It is not a medical device, it has never been evaluated on clinical whole-slide data, and it must not be used for diagnosis or screening.

Verified results β€” PathMNIST test split (CRC-VAL-HE-7K, n = 7,180)

Metric Value Source
Accuracy 0.8712 (6,255/7,180) reproduced 2026-10-28
AUC (macro, one-vs-rest) 0.9855 reproduced 2026-10-28
Balanced accuracy 0.8251 reproduced 2026-10-28
Majority-class baseline 0.1864 reproduced 2026-10-28
Best validation accuracy 0.9629 (epoch 11) recorded at training time
Best validation AUC 0.9987 recorded at training time

Per-class recall on the test split (all reproduced):

Class Recall Class Recall
adipose 0.9477 smooth muscle 0.7348
background 1.0000 normal colon mucosa 0.8516
debris 0.7817 cancer-associated stroma 0.3848
lymphocytes 0.9101 colorectal adenocarcinoma epithelium 0.9667
mucus 0.8483

Read the weak row honestly: the model largely fails on cancer-associated stroma β€” it recalls only 162 of 421 stroma patches, and reads 155 of them as debris. Debris is the model's error sink: debris precision is just 0.4417, meaning most "debris" predictions are wrong (they are mostly stroma and smooth muscle). The clinically most important class, adenocarcinoma epithelium, is also the best detected (recall 0.9667). Accuracy's 95% confidence interval on 7,180 patches is roughly Β±0.8 points (β‰ˆ0.863–0.879). The full 9Γ—9 confusion matrix and per-class precision are in assets/evaluation_results.json; the training-time record is in assets/pathocnn_metrics.json; they agree exactly on every headline number.

Context, not a claim of parity: the MedMNIST v2 paper's reference ResNet-18 (11.7M parameters, ~40Γ— larger) reports 0.907 accuracy / 0.983 AUC on this split, and ResNet-50 reports 0.911 / 0.990. PathoCNN's AUC sits in that band; its accuracy trails by ~3.6 points, which is the price of the small model and shows up almost entirely in the stroma/debris/muscle confusions above.

Quickstart

pip install "git+https://github.com/habib-analyst/pathocnn.git"
from pathocnn import load_model, predict

model = load_model("model.safetensors")   # or assets/pathocnn.pt
result = predict(model, "assets/demo_samples/8_colorectal_adenocarcinoma_epithelium.png")
# {'label': 'colorectal adenocarcinoma epithelium', 'confidence': 0.999,
#  'probabilities': {...9 classes...}}

Preprocessing contract (identical to training): RGB β†’ resize to 28Γ—28 if needed β†’ /255 β†’ normalize per channel with the PathMNIST train-split mean/std ([0.74055, 0.53298, 0.70583] / [0.12368, 0.17676, 0.12443]). Labels are the MedMNIST v2 PathMNIST order 0–8 (see config.json).

ONNX: pathocnn.onnx takes the same normalized (N, 3, 28, 28) float tensor and returns logits.

Verify it yourself

python examples/verify_metrics.py

This re-evaluates the shipped weights on the bundled test split (assets/pathmnist_test.npz) and compares against the training-time metrics file. On 2026-10-28 it printed ALL HEADLINE METRICS REPRODUCED β€” accuracy, AUC, the full confusion matrix, and every per-class recall matched exactly. One protocol warning the script and training code both encode: the train-split normalization statistics must be computed with chunked float64 accumulation. A single float32 NumPy reduction over ~90k images silently returns wrong channel means on this dataset (measured: 0.23778 for every channel instead of 0.74055/0.53298/0.70583) β€” the kind of silent error that makes "reproductions" fail for reasons nobody can see.

python examples/predict_demo.py   # one patch per class + first misclassifications
python -m pytest -q               # 8 tests: formats agree, metrics files agree, parity

The demo is honest about the weak spot: of the nine first-of-class test patches, seven are classified correctly, and the two misses β€” smooth muscle and cancer-associated stroma β€” are both confidently read as debris (95.4% and 99.7%). The demo prints them, and the test suite pins them.

Model details

  • Architecture: 3 conv blocks (32β†’64β†’128 channels, BatchNorm, ReLU, max-pool, dropout) + 2-layer MLP head, designed for this release in the same compact family as SonoCNN. 288,809 trainable parameters; 1.2 MB in safetensors.
  • Training: from scratch on the PathMNIST train split (89,996 patches), 12 epochs, AdamW (lr 2e-3, weight decay 1e-4, OneCycle cosine schedule), batch 256, plain cross-entropy (the train split's max/min class ratio is 1.63, so no class weighting), seed 42, checkpoint selected by best validation accuracy (epoch 11 of 12). Training took 1,990 s (~33 min) on a 2-core CPU. The exact script is examples/train.py.
  • Augmentation: random dihedral transforms (90Β° rotations and flips) on the training split only. Histology patches have no canonical orientation, so the full D4 group is label-preserving here. No color jitter β€” H&E stain color carries class signal and was left alone.

What PathoCNN is not

  • Not a clinical tool. It classifies 28Γ—28 benchmark patches, not whole slides or patients, and its weakest class (cancer-associated stroma, 38.5% recall) is a tissue type a real workflow cares about. The cross-center drop from 0.9629 (validation) to 0.8712 (test) is what domain shift does to small models; expect worse on any other center.
  • Not state of the art. Larger reference models score ~0.91 accuracy on this split. This release exists because its numbers are verified and its failure modes are documented, not because it tops a leaderboard.
  • Not trained on private or clinical data. Only the public PathMNIST benchmark (below).
  • Confidences are not calibrated. Softmax outputs are frequently extreme (several demo patches score a rounded 100.0%), including on the confidently-wrong stromaβ†’debris errors. Treat them as rankings, not probabilities of being right.

Data and attribution

PathMNIST is part of MedMNIST v2 (Yang et al., MedMNIST v2 β€” A large-scale lightweight benchmark for 2D and 3D biomedical image classification, Scientific Data 2023). It derives from the NCT-CRC-HE-100K dataset of 100,000 H&E histology patches (Kather et al., 2019), split 9:1 into train/validation, with CRC-VAL-HE-7K as the external-center test set. The dataset is licensed CC BY 4.0; assets/pathmnist_test.npz (the official test split only) is redistributed here for metric reproduction, with attribution. The source file used for training is Zenodo record 10519652, md5 a8b06965200029087d5bd730944a56c1. The MIT license of this repository covers the code and the trained weights, not the dataset.

Files

File Contents
model.safetensors Release weights (safetensors)
pathocnn.onnx ONNX export (logits)
config.json Architecture + preprocessing config
src/pathocnn/ model.py (architecture), infer.py (loading + prediction API)
examples/train.py The exact training script that produced the weights
examples/predict_demo.py Per-class demo + first misclassifications, printed honestly
examples/verify_metrics.py Full metric reproduction from the artifacts
assets/pathocnn.pt Training checkpoint (state dict + training record)
assets/pathocnn_metrics.json Training-time metrics record
assets/evaluation_results.json Independently reproduced metrics (2026-10-28)
assets/pathmnist_test.npz PathMNIST official test split (CC BY 4.0, see attribution)
assets/demo_samples/ First test patch of each class (28Γ—28 PNGs)

License

MIT for code and weights (see LICENSE). Dataset under CC BY 4.0 as above.

Downloads last month
105
Safetensors
Model size
289k params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Spaces using habib-analyst/pathocnn 4