Spaces:
Sleeping
Sleeping
| """ | |
| PneumoOps β Hugging Face Model Hub Upload Script | |
| ================================================= | |
| Uploads both model artifacts to the HF Model Hub for versioning. | |
| Run this once after training, and again whenever you retrain. | |
| Usage: | |
| huggingface-cli login # one-time login | |
| python scripts/upload_to_hf.py | |
| Environment variables (override defaults): | |
| HF_MODEL_REPO your-username/pneumoops-chestmnist | |
| HF_TOKEN your write token (if not logged in via CLI) | |
| """ | |
| import os | |
| import json | |
| from pathlib import Path | |
| from huggingface_hub import HfApi, upload_file, create_repo | |
| # βββ Config βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ROOT = Path(__file__).resolve().parents[1] | |
| MODEL_DIR = ROOT / "models" / "chestmnist_mobilenetv3" | |
| HF_TOKEN = os.getenv("HF_TOKEN") # optional if already logged in via CLI | |
| MODEL_REPO = os.getenv("HF_MODEL_REPO", "") # e.g. "your-username/pneumoops-chestmnist" | |
| if not MODEL_REPO: | |
| print("\nβ οΈ Please set HF_MODEL_REPO environment variable, e.g.:") | |
| print(' export HF_MODEL_REPO="your-hf-username/pneumoops-chestmnist"') | |
| raise SystemExit(1) | |
| # βββ Files to upload ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ARTIFACTS = [ | |
| ("mobilenetv3_chestmnist.pth", "Model A β Baseline PyTorch checkpoint"), | |
| ("mobilenetv3_chestmnist.onnx", "Model B β Optimized ONNX artifact"), | |
| ("training_metrics.json", "Training + evaluation metrics (AUROC, AUPRC, F1)"), | |
| ("baseline_stats.json", "Pixel distribution stats for drift monitoring"), | |
| ("onnx_export_report.json", "ONNX export configuration"), | |
| ] | |
| # βββ Model Card βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| MODEL_CARD = """--- | |
| license: mit | |
| tags: | |
| - medical | |
| - image-classification | |
| - chest-xray | |
| - mlops | |
| - onnx | |
| - pytorch | |
| - mobilenetv3 | |
| datasets: | |
| - medmnist/chestmnist | |
| metrics: | |
| - roc_auc | |
| --- | |
| # PneumoOps β ChestMNIST MobileNetV3-small | |
| This repository contains **two model versions** for the PneumoOps MLOps pipeline: | |
| - **Model A (Baseline):** `mobilenetv3_chestmnist.pth` β Standard PyTorch checkpoint | |
| - **Model B (Optimized):** `mobilenetv3_chestmnist.onnx` β ONNX-exported for faster inference | |
| Both models are identical in architecture (MobileNetV3-small) and weights. | |
| The ONNX version is used for inference time optimization in A/B testing. | |
| ## Dataset | |
| **ChestMNIST** β 14-class multi-label chest X-ray classification | |
| 78,468 training images, 224Γ224 pixels, grayscale (converted to 3-channel). | |
| ## Classes (14) | |
| Atelectasis, Cardiomegaly, Effusion, Infiltration, Mass, Nodule, Pneumonia, | |
| Pneumothorax, Consolidation, Edema, Emphysema, Fibrosis, Pleural Thickening, Hernia | |
| ## Performance (Test Set) | |
| | Metric | Score | | |
| |--------|-------| | |
| | Macro AUROC | **0.808** | | |
| | Macro AUPRC | 0.210 | | |
| | Micro F1 | 0.343 | | |
| ## Usage in PneumoOps | |
| These artifacts are loaded by the FastAPI backend and selected via a weighted A/B router: | |
| - 60% of requests β PyTorch model | |
| - 40% of requests β ONNX model | |
| The backend also computes a drift score using `baseline_stats.json` to detect | |
| out-of-distribution inputs in real time. | |
| """ | |
| # βββ Main βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def main(): | |
| api = HfApi(token=HF_TOKEN) | |
| print(f"\nπ¦ Creating/verifying model repository: {MODEL_REPO}") | |
| create_repo( | |
| repo_id=MODEL_REPO, | |
| repo_type="model", | |
| exist_ok=True, | |
| token=HF_TOKEN, | |
| ) | |
| # Write model card | |
| card_path = MODEL_DIR / "README.md" | |
| card_path.write_text(MODEL_CARD, encoding="utf-8") | |
| print(" Model card written.") | |
| # Upload model card first | |
| print(f"\nβ¬οΈ Uploading artifacts to https://huggingface.co/{MODEL_REPO}") | |
| upload_file( | |
| path_or_fileobj=str(card_path), | |
| path_in_repo="README.md", | |
| repo_id=MODEL_REPO, | |
| repo_type="model", | |
| commit_message="Add model card", | |
| token=HF_TOKEN, | |
| ) | |
| # Upload all artifacts | |
| for filename, description in ARTIFACTS: | |
| local_path = MODEL_DIR / filename | |
| if not local_path.exists(): | |
| print(f" β οΈ Skipping {filename} β file not found") | |
| continue | |
| size_mb = local_path.stat().st_size / (1024 * 1024) | |
| print(f" Uploading {filename} ({size_mb:.1f} MB) β {description} ...") | |
| upload_file( | |
| path_or_fileobj=str(local_path), | |
| path_in_repo=filename, | |
| repo_id=MODEL_REPO, | |
| repo_type="model", | |
| commit_message=f"Upload {filename}", | |
| token=HF_TOKEN, | |
| ) | |
| print(f"\nβ All artifacts uploaded!") | |
| print(f" View at: https://huggingface.co/{MODEL_REPO}") | |
| if __name__ == "__main__": | |
| main() | |