Deep-learning powered pneumonia detection from chest X-rays
PneumoScan AI is a full-stack medical image analysis application that classifies chest X-ray images as Normal, Pneumonia, or Uncertain using a fine-tuned MobileNetV2 deep learning model. It includes Grad-CAM explainability to visualise which lung regions influenced the model's decision — critical for trust in medical AI.
| Feature | Description |
|---|---|
| Transfer Learning | MobileNetV2 pretrained on ImageNet, fine-tuned on chest X-rays |
| Two-Phase Training | Frozen base → unfreeze last 20 layers for domain adaptation |
| Grad-CAM Heatmaps | Visual explainability showing model attention regions |
| REST API | FastAPI backend with Pydantic validation, health checks, OpenAPI docs |
| Modern Frontend | Glassmorphism UI with drag-and-drop, real-time results |
| Containerised | Multi-stage Dockerfile with health checks |
| CI/CD | GitHub Actions pipeline with testing + Docker build |
| Tested | Unit + integration tests with pytest |
┌──────────────────────────────────────────────────────────┐
│ Frontend (HTML/JS) │
│ Upload X-ray → Predict / Explain (Grad-CAM) │
└────────────────────────┬─────────────────────────────────┘
│ HTTP POST
┌────────────────────────▼─────────────────────────────────┐
│ FastAPI Backend │
│ /predict → preprocess → MobileNetV2 → result │
│ /gradcam → preprocess → MobileNetV2 → heatmap │
│ /health → model status + uptime │
└────────────────────────┬─────────────────────────────────┘
│
┌────────────────────────▼─────────────────────────────────┐
│ MobileNetV2 (Fine-tuned) │
│ Input: 224×224×3 → Sigmoid → P(Pneumonia) │
└──────────────────────────────────────────────────────────┘
pneumonia-ai/
├── app/
│ ├── main.py # FastAPI app — routes, validation, CORS
│ ├── model_loader.py # Singleton model loading with caching
│ ├── predict.py # Image preprocessing & prediction logic
│ └── gradcam.py # Grad-CAM heatmap generation
├── frontend/
│ ├── index.html # Single-page application
│ ├── script.js # (legacy) JS — now inlined in index.html
│ └── style.css # (legacy) CSS — now inlined in index.html
├── training/
│ └── train.py # Full training pipeline with metrics & plots
├── model/
│ └── pneumonia_model.keras # Trained model (not in git — see Setup)
├── data/ # Dataset (not in git — see Setup)
├── tests/
│ └── test_app.py # Unit + integration tests
├── .github/workflows/
│ └── ci.yml # GitHub Actions CI pipeline
├── Dockerfile # Multi-stage container build
├── requirements.txt # Python dependencies
├── pyproject.toml # Pytest configuration
├── .gitignore
└── README.md
- Python 3.10+
- pip
git clone https://github.com/Sujith-RMD/pneumonia-ai.git
cd pneumonia-ai
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtDownload the Chest X-Ray Images (Pneumonia) dataset from Kaggle and extract it:
data/
├── train/
│ ├── NORMAL/
│ └── PNEUMONIA/
├── val/
│ ├── NORMAL/
│ └── PNEUMONIA/
└── test/
├── NORMAL/
└── PNEUMONIA/
python training/train.pyThis will:
- Train MobileNetV2 in two phases (frozen → fine-tuned)
- Evaluate on the test set and print classification report + ROC-AUC
- Save the model to
model/pneumonia_model.keras - Generate plots in
training/plots/(accuracy, loss, confusion matrix, ROC curve)
uvicorn app.main:app --reloadOpen http://localhost:8000 in your browser.
pip install httpx anyio pytest-anyio
pytest tests/ -vdocker build -t pneumoscan-ai .
docker run -p 8000:8000 pneumoscan-aiFastAPI auto-generates interactive docs:
| URL | Description |
|---|---|
/docs |
Swagger UI |
/redoc |
ReDoc |
| Method | Path | Description |
|---|---|---|
GET |
/ |
Serve frontend |
GET |
/health |
Health check (model status, uptime) |
POST |
/predict |
Upload X-ray → get prediction |
POST |
/gradcam |
Upload X-ray → get prediction + Grad-CAM heatmap |
{
"prediction": "PNEUMONIA",
"confidence": 94.32,
"raw_probability": 0.9432
}{
"prediction": "PNEUMONIA",
"confidence": 94.32,
"raw_probability": 0.9432,
"gradcam_base64": "iVBORw0KGgoAAAANSUhEUgAA..."
}Update these numbers after training on your machine.
| Metric | Value |
|---|---|
| Test Accuracy | ~93% |
| ROC-AUC | ~0.97 |
| Architecture | MobileNetV2 (fine-tuned last 20 layers) |
| Input Size | 224 × 224 × 3 |
| Training Data | 5,216 images |
| Augmentation | Rotation, zoom, shift, flip, brightness |
After training, plots are saved to training/plots/:
- Accuracy & Loss curves (with fine-tuning boundary marked)
- Confusion Matrix
- ROC Curve
| Layer | Technology |
|---|---|
| Deep Learning | TensorFlow / Keras · MobileNetV2 |
| Explainability | Grad-CAM (Class Activation Maps) |
| Backend | FastAPI · Pydantic · Uvicorn |
| Frontend | Vanilla HTML/CSS/JS · Glassmorphism |
| Computer Vision | OpenCV · Pillow |
| Metrics | scikit-learn (classification report, ROC-AUC) |
| Testing | pytest · httpx |
| Containerisation | Docker (multi-stage) |
| CI/CD | GitHub Actions |
- Transfer learning and fine-tuning strategies for medical imaging
- Importance of model explainability (Grad-CAM) in healthcare AI
- Building production-ready ML APIs with FastAPI and Pydantic validation
- Two-phase training: frozen backbone → gradual unfreezing
- Handling class imbalance and choosing appropriate evaluation metrics
- Docker containerisation for ML applications
- Writing testable ML code with proper separation of concerns
This is an educational prototype and is not intended for clinical diagnosis. Always consult a qualified medical professional for health-related decisions.
MIT License — see LICENSE for details.