Spaces:
Sleeping
Sleeping
File size: 5,295 Bytes
2e552e9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | """
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()
|