A publication-ready, interpretable, and deployable machine learning system for predicting molecular subtype switching in metastatic breast cancer using multi-omics data.
Approximately 30% of metastatic breast cancer patients experience a change in molecular subtype between their primary and metastatic tumors — a phenomenon called subtype switching (Piccart et al., 2021; Nature Medicine). This is clinically critical because:
| Switching event | Clinical consequence |
|---|---|
| ER+ → ER− | Hormone therapy (tamoxifen, aromatase inhibitors) becomes ineffective |
| HER2+ → HER2− | Trastuzumab/pertuzumab loses efficacy |
| Any → TNBC | Opens immunotherapy eligibility (pembrolizumab if PD-L1+) |
Current standard of care: repeat metastatic biopsy — invasive, expensive, not always feasible (e.g., bone metastases, coagulopathy, patient refusal).
Our model answers: "Given this patient's primary tumor profile, should we urgently prioritize a metastatic biopsy before starting treatment?"
- Metastatic biopsies are often unavailable or unaffordable
- Empirical treatment without subtype knowledge leads to ~30% unnecessary toxicity
- A validated switching-risk model could guide rational empiric treatment selection
- This system runs on CPU-only hardware (laptops, Raspberry Pi clusters)
Source: Breast International Group (BIG) — AURORA study
Reference: Piccart et al. (2021). Mutational landscape of metastatic breast cancer. Nature Medicine, 27, 1. doi:10.1038/s41591-021-01462-7
| Data modality | Size | Description |
|---|---|---|
| Clinical metadata | ~400 patients | Age, treatment, tumor grade, receptor status |
| RNA-seq (transcriptomics) | 500 genes selected | Log2(CPM+1) normalized |
| DNA methylation (EPIC array) | 1000 CpG sites | Beta values [0, 1] |
Data access: Requires DUA with BIG. This repository uses a faithful synthetic
generator (see src/data/synthetic_generator.py) for reproducible development.
# 1. Clone and install
git clone https://github.com/yourusername/Breast-Cancer-Classification.git
cd Breast-Cancer-Classification
pip install -r requirements.txt
# 2. Train the full pipeline (generates data, trains all models, logs to MLflow)
make train
# 3. Launch the clinical decision support app
make app # Streamlit UI → http://localhost:8501
# 4. Or launch the REST API
make api # FastAPI → http://localhost:8000/docs
# 5. View experiment tracking
make mlflow-ui # MLflow → http://localhost:5000┌─────────────────────────────────────────────────────────────────┐
│ AURORA ML PIPELINE │
│ │
│ [Data Layer] │
│ AURORALoader → SyntheticGenerator (or real AURORA files) │
│ │ │
│ [Preprocessing Layer] │
│ ClinicalPreprocessor RNAseqPreprocessor MethylationPrep │
│ (impute+OHE+scale) (log2+PCA 50) (clip+PCA 30) │
│ │ │ │ │
│ [Feature Engineering] │
│ MultiModalFeatureEngineer │
│ (concat + PAM50 scores + derived + MI selection → ~100 feat) │
│ │ │
│ [Model Layer] │
│ LogisticRegression RandomForest XGBoost(Optuna) LateFusion │
│ (SMOTE inside CV) (balanced) (tree_method=hist) (stacking)│
│ │ │
│ [Evaluation Layer] │
│ ROC-AUC PR-AUC F1 Sensitivity Specificity MCC SHAP │
│ │ │
│ [Deployment Layer] │
│ FastAPI REST API ←→ Streamlit Clinical UI │
│ │ │
│ [MLOps Layer] │
│ MLflow (tracking + registry) DVC (data versioning) Docker │
└─────────────────────────────────────────────────────────────────┘
subtype_switch (binary):
- 0 — same molecular subtype in primary and metastatic tumor
- 1 — different molecular subtype (30% prevalence in AURORA)
Molecular subtypes defined by PAM50 classifier applied to RNA-seq: Luminal A, Luminal B, HER2-enriched, Triple Negative.
Clinical features (leakage-safe — no metastatic receptor status):
- Age at diagnosis, Ki67 proliferation index, tumor grade, tumor size
- Primary ER/PR/HER2 status, time to metastasis, metastatic site
- Treatment history (chemo, hormone, targeted therapy)
- Derived: aggressiveness score, treatment pressure index
Transcriptomics features (RNA-seq):
- Log2(CPM+1) normalization
- Variance filtering (threshold 0.1)
- 50 principal components capturing major expression programs
- PAM50 gene scores (50 clinically validated subtype genes)
Epigenomics features (DNA methylation):
- Beta-value clipping [0.01, 0.99] to remove probe noise
- Variance filtering (threshold 0.05)
- 30 principal components
Feature selection: Mutual information (non-parametric, handles mixed types) → top 100 features selected for final model.
- SMOTE (Synthetic Minority Over-sampling Technique) applied inside each CV fold only
- This is critical: applying SMOTE before splitting causes data leakage
- k_neighbors=5, sampling_strategy='auto'
| Model | Rationale |
|---|---|
| Logistic Regression | Linear baseline; interpretable coefficients; fast |
| Random Forest | Non-linear baseline; robust to outliers; stable feature importance |
| XGBoost + Optuna | State-of-art gradient boosting; CPU-native (hist algorithm) |
| Late Fusion (stacking) | Modality-specific encoders; handles missing modalities gracefully |
Optuna (Bayesian optimization, TPE sampler) with 50 trials, 5-fold stratified CV, optimizing ROC-AUC. Search space: n_estimators, max_depth, learning_rate, subsample, colsample_bytree, min_child_weight, gamma, L1/L2 regularization.
Priority metrics for clinical AI (following FDA AI/ML guidance):
- Sensitivity (Recall): miss as few switchers as possible
- AUC-ROC: threshold-independent discrimination
- AUC-PR: more informative under class imbalance
- Matthews Correlation Coefficient: balanced for imbalanced datasets
- Brier Score: calibration (are probabilities reliable?)
Threshold selection: Youden's J statistic (maximizes sensitivity + specificity jointly)
TreeExplainer SHAP values computed on held-out test set:
- Global: mean |SHAP| ranks biological drivers of switching
- Per-patient: waterfall plots for individual clinical decisions
- Feature groups color-coded (clinical / PAM50 / RNA-seq PC / methylation PC)
Results on real AURORA data will differ. Synthetic data reflects biological signal structure but not full clinical complexity.
| Model | AUC-ROC | AUC-PR | F1 | Sensitivity | Specificity | MCC |
|---|---|---|---|---|---|---|
| Logistic Regression | ~0.72 | ~0.55 | ~0.60 | ~0.68 | ~0.74 | ~0.40 |
| Random Forest | ~0.78 | ~0.61 | ~0.64 | ~0.70 | ~0.80 | ~0.46 |
| XGBoost (Optuna) | ~0.82 | ~0.67 | ~0.68 | ~0.74 | ~0.85 | ~0.52 |
| Late Fusion | ~0.80 | ~0.64 | ~0.66 | ~0.72 | ~0.83 | ~0.49 |
Run make train and check reports/model_comparison.csv for actual results.
make mlflow-ui # http://localhost:5000Every run logs: hyperparameters, CV metrics, test metrics, ROC/PR curves, SHAP plots.
dvc init
dvc run -n generate_data # version the synthetic (or real) data
dvc repro # reproduce full pipeline
dvc push # push to remote storage (S3/GDrive/etc.)# Full pipeline is deterministic with seed=42
python scripts/train.py # generates same results every timedocker build -t aurora-bc .
docker-compose up # API + Streamlit + MLflow# Health check
GET http://localhost:8000/health
# Single patient prediction
POST http://localhost:8000/predict
Content-Type: application/json
{
"age_at_diagnosis": 52,
"primary_er_status": 1,
"primary_pr_status": 1,
"primary_her2_status": 0,
"ki67_primary": 15,
"tumor_grade": 2,
"tumor_size_cm": 2.5,
"time_to_metastasis_months": 24,
"metastatic_site": "liver",
"number_of_metastatic_sites": 1,
"chemotherapy": 1,
"hormone_therapy": 1,
"targeted_therapy": 0,
"line_of_therapy": 1,
"ecog_ps": 0
}Full API documentation: http://localhost:8000/docs (Swagger UI)
Breast-Cancer-Classification/
├── configs/config.yaml # All hyperparameters and paths
├── src/
│ ├── data/
│ │ ├── synthetic_generator.py # AURORA-faithful data synthesis
│ │ └── aurora_loader.py # Unified data loader
│ ├── preprocessing/
│ │ ├── clinical_preprocessor.py # Leakage-safe clinical pipeline
│ │ └── omics_preprocessor.py # RNA-seq + methylation PCA
│ ├── features/
│ │ └── feature_engineer.py # Multi-modal fusion + MI selection
│ ├── models/
│ │ ├── baseline_models.py # LR, RF, XGB + Optuna tuner
│ │ └── multimodal_fusion.py # Late fusion (stacking)
│ ├── evaluation/
│ │ └── evaluator.py # Metrics + SHAP + plots
│ └── pipeline/
│ └── train_pipeline.py # End-to-end orchestration
├── api/
│ ├── main.py # FastAPI REST API
│ └── schemas.py # Pydantic request/response models
├── app/
│ └── streamlit_app.py # Clinical decision support UI
├── scripts/
│ └── train.py # CLI entry point
├── tests/
│ └── test_preprocessing.py # Unit tests
├── Dockerfile
├── docker-compose.yml
├── dvc.yaml
├── Makefile
└── requirements.txt
-
Bias & Fairness: AURORA enrolled patients primarily from Europe and North America. Performance on African/Asian cohorts is unknown and likely lower. Models should be validated locally before clinical deployment in low-resource settings.
-
Clinical use limitations: This is a decision-support tool, not a diagnostic device. All predictions must be interpreted by a qualified oncologist. The model should never replace clinical judgment or available biopsy data.
-
Data privacy: Patient data must be de-identified before use. This system processes data locally — no patient data is sent to external servers.
-
Model transparency: SHAP values and feature importance are provided for every prediction. "Black box" deployment in healthcare is insufficient.
-
Failure modes: The model is least reliable in:
- Patients with missing Ki67 or tumor size data
- Rare subtypes (HER2E primary, n<50 in training)
- Patients who received novel agents (CDK4/6 inhibitors) not well-represented in AURORA
If you use this system in research, please cite:
@misc{sentongo2024aurora,
title={Predicting Molecular Subtype Switching in Metastatic Breast Cancer
Using Multi-Omics Machine Learning},
author={Sentongo, Paul},
year={2024},
url={https://github.com/sentongo-web/Breast-Cancer-Classification}
}
@article{piccart2021aurora,
title={Mutational landscape of metastatic breast cancer},
author={Piccart, Martine and others},
journal={Nature Medicine},
year={2021},
doi={10.1038/s41591-021-01462-7}
}MIT License. See LICENSE for details.
Built by Paul Sentongo as part of a PhD application portfolio demonstrating clinical AI, MLOps, and healthcare data science expertise.