Loading…
Loading…
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.
model.safetensors, the training checkpoint (assets/pathocnn.pt), and ONNX (pathocnn.onnx, parity vs PyTorch measured at 5.7e-06 max logit difference).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.
| 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.
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.
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.
examples/train.py.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.
| 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) |
MIT for code and weights (see LICENSE). Dataset under CC BY 4.0 as above.