YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

LungCV v3 - Multi-label Chest X-ray Classifier with OOD Rejection

Multi-label chest X-ray finding classifier. Each finding group is scored independently (sigmoid, not softmax), so a film can score high on several findings at once, and films where every score sits below the uncertainty threshold are flagged as uncertain instead of being forced into a class. An energy/distance-based OOD detector additionally flags films that fall far from the training distribution.

Research prototype only - not a medical diagnosis. Trained and evaluated on public research datasets only.

Model

  • Backbone: DenseNet121 (ImageNet weights, frozen backbone + trained head)
  • Head: GlobalAveragePooling -> Dropout(0.3) -> Dense(4, sigmoid)
  • Loss: binary cross-entropy per finding (multi-label formulation)
  • Input: 224x224, grayscale replicated to 3 channels, CLAHE-harmonized tiles
  • Trained: 22 epochs (early stopping), balanced 3,000/class, patient-wise splits

Results (validation, threshold 0.5)

Finding Precision Recall F1
COVID 0.820 0.707 0.759
NORMAL 0.832 0.690 0.754
PNEUMONIA 0.874 0.696 0.775
TB 0.961 0.886 0.922
  • Argmax accuracy: 82.9% | macro-F1: 0.829
  • OOD threshold (95th percentile of train distances): 16.27
  • Familiar validation films flagged OOD: 5.3% (consistent with the threshold calibration)

Note on the numbers: sigmoid per-finding scoring at a fixed 0.5 threshold is a harder bar than softmax argmax - films the model is unsure about simply score below 0.5 (that is the intended uncertainty behavior), which lowers reported recall.

Files

  • best_model.keras - the model (29.7 MB)
  • class_names.json - output order: ["COVID", "NORMAL", "PNEUMONIA", "TB"]
  • preprocessing_config.json - the demo contract (CLAHE, thresholds, class order)
  • metrics.json - full metrics
  • ood_centroids.json - per-class feature centroids for OOD scoring
  • confusion_matrix.png - argmax confusion matrix

Preprocessing contract

  1. Convert to grayscale
  2. CLAHE (clipLimit=2.0, tileGridSize=(8,8)) - strips scanner intensity fingerprints
  3. Resize to 224x224 (LANCZOS)
  4. Replicate to 3 channels
  5. keras DenseNet preprocess_input (scales to [-1, 1])

No border cropping (crop_borders: 0).

OOD detection

For a new film: extract GAP features, compute the Euclidean distance to the nearest class centroid in ood_centroids.json. Distance above the threshold (16.27) means "outside the training distribution" - the film should be reported as unrecognized, not classified.

Data provenance (7 public sources)

Kermany chest X-ray pneumonia, NIH ChestX-ray14, COVID-19 Radiography Database, COVID-QU-Ex, TB Chest X-ray database, Shenzhen TB, Montgomery TB. Patient-wise 70/15/15 splits - no patient appears in more than one split.

Downloads last month
24
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support