Rahma69 commited on
Commit
1bfd5f2
·
verified ·
1 Parent(s): 85cebab

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================================
2
+ # BEST FULL PIPELINE – Brain Stroke Classification
3
+ # Dataset: Tekno21 (Normal – Ischemic – Hemorrhagic)
4
+ # Model: EfficientNet (High accuracy)
5
+ # Includes: Training + Accuracy + Error Rate + Gradio UI
6
+ # ============================================================
7
+
8
+ !pip install -q datasets torch torchvision pillow gradio efficientnet_pytorch
9
+
10
+ from datasets import load_dataset
11
+ import os
12
+ import torch
13
+ import torch.nn as nn
14
+ import torch.optim as optim
15
+ from torch.utils.data import Dataset, DataLoader
16
+ from torchvision import transforms
17
+ from efficientnet_pytorch import EfficientNet
18
+ from PIL import Image
19
+ import gradio as gr
20
+ import numpy as np
21
+ from sklearn.metrics import accuracy_score
22
+
23
+ device = "cuda" if torch.cuda.is_available() else "cpu"
24
+ print("Device:", device)
25
+
26
+ # ---------------------- LOAD DATASET ----------------------
27
+ ds = load_dataset("BTX24/tekno21-brain-stroke-dataset-multi")
28
+
29
+ labels_map = {"NORMAL": 0, "ISCHEMIC": 1, "HEMORRHAGIC": 2}
30
+
31
+ class_names = ["Normal", "Ischemic", "Hemorrhagic"]
32
+
33
+ # ---------------------- TRANSFORMS ----------------------
34
+ train_tf = transforms.Compose([
35
+ transforms.Resize((224,224)),
36
+ transforms.RandomHorizontalFlip(),
37
+ transforms.RandomRotation(10),
38
+ transforms.ColorJitter(0.2,0.2,0.2,0.1),
39
+ transforms.ToTensor(),
40
+ transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
41
+ ])
42
+
43
+ val_tf = transforms.Compose([
44
+ transforms.Resize((224,224)),
45
+ transforms.ToTensor(),
46
+ transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
47
+ ])
48
+
49
+ # ---------------------- CUSTOM DATASET CLASS ----------------------
50
+ class BrainDataset(Dataset):
51
+ def __init__(self, hf_data, transform):
52
+ self.data = hf_data
53
+ self.transform = transform
54
+
55
+ def __len__(self):
56
+ return len(self.data)
57
+
58
+ def __getitem__(self, idx):
59
+ img = Image.open(self.data[idx]["image"]).convert("RGB")
60
+ label = labels_map[self.data[idx]["label"].upper()]
61
+ return self.transform(img), label
62
+
63
+ train_data = BrainDataset(ds["train"], train_tf)
64
+ val_data = BrainDataset(ds["validation"], val_tf)
65
+
66
+ train_loader = DataLoader(train_data, batch_size=16, shuffle=True)
67
+ val_loader = DataLoader(val_data, batch_size=16)
68
+
69
+ # ---------------------- MODEL ----------------------
70
+ model = EfficientNet.from_pretrained("efficientnet-b0")
71
+ model._fc = nn.Linear(model._fc.in_features, len(class_names))
72
+ model = model.to(device)
73
+
74
+ criterion = nn.CrossEntropyLoss()
75
+ optimizer = optim.AdamW(model.parameters(), lr=1e-4)
76
+
77
+ # ---------------------- TRAINING ----------------------
78
+ EPOCHS = 5
79
+ best_acc = 0
80
+
81
+ for epoch in range(EPOCHS):
82
+ model.train()
83
+ train_correct = 0
84
+ total = 0
85
+
86
+ for imgs, labels in train_loader:
87
+ imgs, labels = imgs.to(device), labels.to(device)
88
+ optimizer.zero_grad()
89
+
90
+ out = model(imgs)
91
+ loss = criterion(out, labels)
92
+
93
+ loss.backward()
94
+ optimizer.step()
95
+
96
+ _, preds = out.max(1)
97
+ train_correct += preds.eq(labels).sum().item()
98
+ total += labels.size(0)
99
+
100
+ train_acc = 100 * train_correct / total
101
+ print(f"Epoch {epoch+1}/{EPOCHS} – Train Acc: {train_acc:.2f}%")
102
+
103
+ # Validation
104
+ model.eval()
105
+ val_preds = []
106
+ val_true = []
107
+
108
+ with torch.no_grad():
109
+ for imgs, labels in val_loader:
110
+ imgs, labels = imgs.to(device), labels.to(device)
111
+ out = model(imgs)
112
+ _, preds = out.max(1)
113
+
114
+ val_preds.extend(preds.cpu().numpy())
115
+ val_true.extend(labels.cpu().numpy())
116
+
117
+ val_acc = accuracy_score(val_true, val_preds) * 100
118
+ print(f"Validation Accuracy: {val_acc:.2f}%")
119
+
120
+ if val_acc > best_acc:
121
+ best_acc = val_acc
122
+ torch.save(model.state_dict(), "best_model.pth")
123
+ print("✔ Best Model Saved")
124
+
125
+ print(" BEST ACCURACY =", best_acc)
126
+
127
+ # ---------------------- ERROR RATE ----------------------
128
+ error_rate = 100 - best_acc
129
+ print(" ERROR RATE =", error_rate, "%")
130
+
131
+ # ---------------------- LOAD BEST MODEL ----------------------
132
+ model.load_state_dict(torch.load("best_model.pth"))
133
+ model.eval()
134
+ # ---------------------- GRADIO INTERFACE ----------------------
135
+ def predict(img):
136
+ img = val_tf(img).unsqueeze(0).to(device)
137
+ with torch.no_grad():
138
+ out = model(img)
139
+ probs = torch.softmax(out[0], dim=0).cpu().numpy()
140
+ return {class_names[i]: float(probs[i]) for i in range(len(class_names))}
141
+
142
+ iface = gr.Interface(
143
+ fn=predict,
144
+ inputs=gr.Image(type="pil"),
145
+ outputs=gr.Label(),
146
+ title="Brain Stroke Classifier (EfficientNet-B0)",
147
+ description=f"Best Validation Accuracy: {best_acc:.2f}% | Error Rate: {error_rate:.2f}%"
148
+ )
149
+
150
+ iface.launch(share=True)