ruanhelansantos commited on
Commit
a8868f6
Β·
verified Β·
1 Parent(s): cc62ae3

Upload model.py

Browse files
Files changed (1) hide show
  1. model.py +79 -0
model.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # model.py
2
+ # ECG Condition Classifier - Model Loading and Inference
3
+
4
+ from transformers import pipeline
5
+
6
+ # ── Model configuration ───────────────────────────────────────────────────────
7
+ # ViT model fine-tuned on ECG image classification
8
+ # Covers 5 cardiac conditions from the PTB-XL dataset
9
+ MODEL_NAME = "Deranged/vit-base-patch16-224-finetuned-ecg"
10
+
11
+ # Label mapping from model output to readable condition names
12
+ LABEL_MAP = {
13
+ "NORM": "Normal Sinus Rhythm",
14
+ "AFIB": "Atrial Fibrillation",
15
+ "MI": "Myocardial Infarction",
16
+ "STTC": "ST/T-Wave Change",
17
+ "CD": "Conduction Disturbance",
18
+ }
19
+
20
+ # Global classifier instance (loaded once at startup)
21
+ _classifier = None
22
+
23
+
24
+ def load_model():
25
+ """
26
+ Loads the pretrained ECG classification pipeline.
27
+ Uses CPU (device=-1) for compatibility with Hugging Face free tier.
28
+ Called once at app startup to avoid reloading on every request.
29
+ """
30
+ global _classifier
31
+ if _classifier is None:
32
+ print(f"Loading model: {MODEL_NAME}")
33
+ _classifier = pipeline(
34
+ "image-classification",
35
+ model=MODEL_NAME,
36
+ device=-1 # CPU β€” required for HF Spaces free tier
37
+ )
38
+ print("Model loaded successfully.")
39
+ return _classifier
40
+
41
+
42
+ def run_inference(image, top_k=3):
43
+ """
44
+ Runs the image classification pipeline on a preprocessed PIL image.
45
+
46
+ Args:
47
+ image: PIL Image (preprocessed by utils.py)
48
+ top_k: number of top predictions to return
49
+
50
+ Returns:
51
+ List of dicts: [{"label": str, "score": float}, ...]
52
+ Sorted by confidence score descending.
53
+ """
54
+ classifier = load_model()
55
+ results = classifier(image, top_k=top_k)
56
+
57
+ # Normalize labels to uppercase for consistent mapping
58
+ for r in results:
59
+ r["label"] = r["label"].upper().strip()
60
+
61
+ return results
62
+
63
+
64
+ def get_top_prediction(results):
65
+ """
66
+ Extracts the top prediction from inference results.
67
+
68
+ Returns:
69
+ (label: str, confidence: float, full_name: str)
70
+ """
71
+ if not results:
72
+ return "UNKNOWN", 0.0, "Unknown"
73
+
74
+ top = results[0]
75
+ label = top["label"]
76
+ confidence = round(top["score"] * 100, 1)
77
+ full_name = LABEL_MAP.get(label, label)
78
+
79
+ return label, confidence, full_name