CerviScan AI β€” EfficientNet-B0 Cervical Cytology Classifier

5-class Pap smear cell classifier (EfficientNet-B0, timm backbone + custom head, ~4.3M parameters) trained on the SIPaKMeD dataset for AI-assisted cervical cancer screening in resource-limited settings.

Classes

Dyskeratotic Β· Koilocytotic Β· Metaplastic Β· Parabasal Β· Superficial-Intermediate

Results

80/20 stratified split Β· 810 validation images Β· seed 42

Cell type Category Precision Recall F1 Support
Dyskeratotic Abnormal 0.9878 0.9939 0.9908 163
Koilocytotic HPV-related 0.9752 0.9515 0.9632 165
Metaplastic Abnormal 0.9750 0.9811 0.9781 159
Parabasal Normal 1.0000 1.0000 1.0000 157
Superficial-Intermediate Normal 0.9821 0.9940 0.9880 166

Overall accuracy: 98.40% Β· macro F1: 0.9840

Binary triage view (Normal vs Abnormal)

The deployment decision is binary β€” flag for human review or clear:

Metric Value
Triage accuracy 99.51% (806/810)
Abnormal sensitivity 99.38% (484/487)
Normal specificity 99.69% (322/323)
Missed abnormal cells 3 of 487 (0.62%)

Of the 13 total 5-class errors, 10 are harmless abnormal-subtype swaps (still routed to human review) and 1 is a false alarm β€” only 3 abnormal cells escaped as normal. Koilocytotic ↔ Metaplastic is the dominant confusion pair, consistent with published SIPaKMeD benchmarks.

Files

File Size Purpose
cervical_b0_fp16.onnx 8.32 MB Browser inference (onnxruntime-web) β€” verified 98.40% on the full validation set
cervical_b0.onnx 16.53 MB fp32 fallback β€” verified, parity 1.3e-07 vs PyTorch
cervical_model.pth 16.83 MB Self-describing checkpoint (weights + class order + normalization stats + architecture)

Usage

import numpy as np
import onnxruntime as ort
from PIL import Image

MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32)
STD  = np.array([0.229, 0.224, 0.225], dtype=np.float32)
CLASSES = ["Dyskeratotic", "Koilocytotic", "Metaplastic", "Parabasal",
           "Superficial-Intermediate"]

img = Image.open("cell.png").convert("RGB").resize((224, 224))
x = (np.asarray(img, dtype=np.float32) / 255.0 - MEAN) / STD
x = x.transpose(2, 0, 1)[None]  # HWC -> CHW, add batch dim

sess = ort.InferenceSession("cervical_b0_fp16.onnx",
                            providers=["CPUExecutionProvider"])
logits = sess.run(None, {sess.get_inputs()[0].name: x})[0]
probs = np.exp(logits) / np.exp(logits).sum()
print(CLASSES[int(probs.argmax())], f"{probs.max():.1%}")

Training details

  • Architecture: timm efficientnet_b0 (num_classes=0) + head:Dropout(0.4) β†’ Linear(1280β†’256) β†’ ReLU β†’ Dropout(0.2) β†’ Linear(256β†’5)
  • Data: SIPaKMeD, 4,049 isolated cell images, 80/20 stratified split
  • Augmentation: random horizontal flip, random rotation (Β±30Β°), color jitter (0.2)
  • Optimization: AdamW (lr 1e-4, weight decay 1e-4), cosine annealing,batch size 32, early stopping (patience 7) on validation accuracy

Limitations & disclaimer

Trained and validated on isolated cells from a single public dataset (SIPaKMeD); performance on whole slides, different scanners, stains, or clinical populations is untested. Research prototype β€” not a medical device. Class order and normalization statistics are embedded in the checkpoint for verification.

Dataset citation

SIPaKMeD β€” Pap smear cell images: https://www.kaggle.com/datasets/akshaykrishnan/sipakmed5

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