Mikecode123 commited on
Commit
2dfe2a7
·
verified ·
1 Parent(s): 174705b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -58
app.py CHANGED
@@ -6,34 +6,72 @@ import torch.nn as nn
6
  import numpy as np
7
 
8
  app = FastAPI(
9
- title="NeuroHealth EEG API",
10
- version="1.0"
11
  )
12
 
13
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
14
 
15
  # =========================================================
16
- # CLASS LABELS
17
  # =========================================================
18
 
19
  AD_CLASSES = ["Alzheimer", "FTD", "Control"]
20
  PD_CLASSES = ["Parkinson", "Control"]
21
 
22
  # =========================================================
23
- # EXPECTED INPUT
24
  # =========================================================
25
 
26
- INPUT_FEATURES = 95 # must reshape to (19, 5)
 
 
 
 
 
 
 
 
27
 
28
  # =========================================================
29
- # CNN MODEL (MATCHES YOUR CHECKPOINT EXACTLY)
30
  # =========================================================
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  class EEG_CNN(nn.Module):
33
  def __init__(self, output_dim):
34
  super().__init__()
35
 
36
- self.conv1 = nn.Conv1d(in_channels=19, out_channels=32, kernel_size=7)
37
  self.bn1 = nn.BatchNorm1d(32)
38
 
39
  self.conv2 = nn.Conv1d(32, 64, kernel_size=5)
@@ -50,55 +88,52 @@ class EEG_CNN(nn.Module):
50
  x = torch.relu(self.bn2(self.conv2(x)))
51
  x = torch.relu(self.bn3(self.conv3(x)))
52
 
53
- x = self.pool(x)
54
- x = x.squeeze(-1)
55
  return self.fc(x)
56
 
57
  # =========================================================
58
- # LOAD MODELS
59
  # =========================================================
60
 
61
- ad_model = EEG_CNN(3).to(DEVICE)
62
- pd_model = EEG_CNN(2).to(DEVICE)
 
 
63
 
64
- ad_model.load_state_dict(torch.load("AD_MLP.pt", map_location=DEVICE))
65
- pd_model.load_state_dict(torch.load("PD_MLP.pt", map_location=DEVICE))
 
66
 
67
- ad_model.eval()
68
- pd_model.eval()
 
 
69
 
70
- print("Models Loaded Successfully")
71
-
72
- # =========================================================
73
- # REQUEST SCHEMA
74
- # =========================================================
75
 
76
- class EEGRequest(BaseModel):
77
- features: list
78
 
79
  # =========================================================
80
- # CORE PREDICTION FUNCTION
81
  # =========================================================
82
 
83
- def predict_model(model, features):
84
- x = torch.tensor(features, dtype=torch.float32)
85
 
86
- # reshape 95 -> (19, 5)
87
- if x.numel() != 95:
88
- raise ValueError("Expected 95 features")
89
 
90
- x = x.view(19, 5) # (channels, time)
91
- x = x.unsqueeze(0) # (batch, 19, 5)
92
- x = x.to(DEVICE)
93
 
94
  with torch.no_grad():
95
- outputs = model(x)
96
- probs = torch.softmax(outputs, dim=1).cpu().numpy()[0]
97
 
98
  pred = int(np.argmax(probs))
99
- confidence = float(probs[pred])
100
-
101
- return pred, confidence, probs.tolist()
102
 
103
  # =========================================================
104
  # ROUTES
@@ -106,40 +141,58 @@ def predict_model(model, features):
106
 
107
  @app.get("/")
108
  def home():
109
- return {"message": "NeuroHealth EEG API Running"}
110
 
111
  # =========================================================
112
- # ALZHEIMER
113
  # =========================================================
114
 
115
- @app.post("/predict/alzheimer")
116
- def predict_alzheimer(request: EEGRequest):
 
117
 
118
- pred, confidence, probs = predict_model(ad_model, request.features)
 
 
 
 
 
 
 
 
 
 
119
 
120
  return {
121
- "prediction": AD_CLASSES[pred],
122
- "confidence": confidence,
123
- "probabilities": {
124
- AD_CLASSES[i]: float(probs[i])
125
- for i in range(len(AD_CLASSES))
126
- }
127
  }
128
 
129
  # =========================================================
130
- # PARKINSON
131
  # =========================================================
132
 
133
- @app.post("/predict/parkinson")
134
- def predict_parkinson(request: EEGRequest):
 
 
 
 
 
 
 
 
 
135
 
136
- pred, confidence, probs = predict_model(pd_model, request.features)
 
 
137
 
138
  return {
139
- "prediction": PD_CLASSES[pred],
140
- "confidence": confidence,
141
- "probabilities": {
142
- PD_CLASSES[i]: float(probs[i])
143
- for i in range(len(PD_CLASSES))
144
- }
145
  }
 
6
  import numpy as np
7
 
8
  app = FastAPI(
9
+ title="NeuroHealth Multi-Model EEG API",
10
+ version="2.0"
11
  )
12
 
13
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
14
 
15
  # =========================================================
16
+ # LABELS
17
  # =========================================================
18
 
19
  AD_CLASSES = ["Alzheimer", "FTD", "Control"]
20
  PD_CLASSES = ["Parkinson", "Control"]
21
 
22
  # =========================================================
23
+ # INPUT
24
  # =========================================================
25
 
26
+ class EEGRequest(BaseModel):
27
+ features: list
28
+
29
+ # =========================================================
30
+ # DEVICE
31
+ # =========================================================
32
+
33
+ def to_tensor(features):
34
+ return torch.tensor(features, dtype=torch.float32)
35
 
36
  # =========================================================
37
+ # ===================== MODELS ============================
38
  # =========================================================
39
 
40
+ # ---------------- MLP (CSV MODELS) ----------------------
41
+
42
+ INPUT_DIM = 95
43
+
44
+ class MLP(nn.Module):
45
+ def __init__(self, output_dim):
46
+ super().__init__()
47
+ self.net = nn.Sequential(
48
+ nn.Linear(INPUT_DIM, 512),
49
+ nn.BatchNorm1d(512),
50
+ nn.GELU(),
51
+ nn.Dropout(0.3),
52
+
53
+ nn.Linear(512, 256),
54
+ nn.BatchNorm1d(256),
55
+ nn.GELU(),
56
+ nn.Dropout(0.3),
57
+
58
+ nn.Linear(256, 128),
59
+ nn.GELU(),
60
+
61
+ nn.Linear(128, output_dim)
62
+ )
63
+
64
+ def forward(self, x):
65
+ return self.net(x)
66
+
67
+
68
+ # ---------------- CNN (EEG MODELS) ----------------------
69
+
70
  class EEG_CNN(nn.Module):
71
  def __init__(self, output_dim):
72
  super().__init__()
73
 
74
+ self.conv1 = nn.Conv1d(19, 32, kernel_size=7)
75
  self.bn1 = nn.BatchNorm1d(32)
76
 
77
  self.conv2 = nn.Conv1d(32, 64, kernel_size=5)
 
88
  x = torch.relu(self.bn2(self.conv2(x)))
89
  x = torch.relu(self.bn3(self.conv3(x)))
90
 
91
+ x = self.pool(x).squeeze(-1)
 
92
  return self.fc(x)
93
 
94
  # =========================================================
95
+ # LOAD ALL MODELS
96
  # =========================================================
97
 
98
+ # -------- AD MODELS --------
99
+ ad_mlp = MLP(3).to(DEVICE)
100
+ ad_mlp.load_state_dict(torch.load("AD_MLP.pt", map_location=DEVICE))
101
+ ad_mlp.eval()
102
 
103
+ ad_cnn = EEG_CNN(3).to(DEVICE)
104
+ ad_cnn.load_state_dict(torch.load("AD_eeg_cnn.pth", map_location=DEVICE))
105
+ ad_cnn.eval()
106
 
107
+ # -------- PD MODELS --------
108
+ pd_mlp = MLP(2).to(DEVICE)
109
+ pd_mlp.load_state_dict(torch.load("PD_MLP.pt", map_location=DEVICE))
110
+ pd_mlp.eval()
111
 
112
+ pd_cnn = EEG_CNN(2).to(DEVICE)
113
+ pd_cnn.load_state_dict(torch.load("PD_eeg_cnn.pth", map_location=DEVICE))
114
+ pd_cnn.eval()
 
 
115
 
116
+ print("All models loaded successfully")
 
117
 
118
  # =========================================================
119
+ # PREDICTION ENGINE
120
  # =========================================================
121
 
122
+ def predict(model, features, mode="mlp"):
123
+ x = to_tensor(features)
124
 
125
+ if mode == "mlp":
126
+ x = x.unsqueeze(0).to(DEVICE)
 
127
 
128
+ elif mode == "cnn":
129
+ x = x.view(19, 5).unsqueeze(0).to(DEVICE)
 
130
 
131
  with torch.no_grad():
132
+ out = model(x)
133
+ probs = torch.softmax(out, dim=1).cpu().numpy()[0]
134
 
135
  pred = int(np.argmax(probs))
136
+ return pred, float(probs[pred]), probs.tolist()
 
 
137
 
138
  # =========================================================
139
  # ROUTES
 
141
 
142
  @app.get("/")
143
  def home():
144
+ return {"message": "NeuroHealth Multi-Model API Running"}
145
 
146
  # =========================================================
147
+ # AD ENDPOINTS
148
  # =========================================================
149
 
150
+ @app.post("/predict/ad/mlp")
151
+ def ad_mlp_predict(req: EEGRequest):
152
+ p, c, prob = predict(ad_mlp, req.features, "mlp")
153
 
154
+ return {
155
+ "model": "AD_MLP",
156
+ "prediction": AD_CLASSES[p],
157
+ "confidence": c,
158
+ "probabilities": dict(zip(AD_CLASSES, prob))
159
+ }
160
+
161
+
162
+ @app.post("/predict/ad/eeg")
163
+ def ad_cnn_predict(req: EEGRequest):
164
+ p, c, prob = predict(ad_cnn, req.features, "cnn")
165
 
166
  return {
167
+ "model": "AD_EEG_CNN",
168
+ "prediction": AD_CLASSES[p],
169
+ "confidence": c,
170
+ "probabilities": dict(zip(AD_CLASSES, prob))
 
 
171
  }
172
 
173
  # =========================================================
174
+ # PD ENDPOINTS
175
  # =========================================================
176
 
177
+ @app.post("/predict/pd/mlp")
178
+ def pd_mlp_predict(req: EEGRequest):
179
+ p, c, prob = predict(pd_mlp, req.features, "mlp")
180
+
181
+ return {
182
+ "model": "PD_MLP",
183
+ "prediction": PD_CLASSES[p],
184
+ "confidence": c,
185
+ "probabilities": dict(zip(PD_CLASSES, prob))
186
+ }
187
+
188
 
189
+ @app.post("/predict/pd/eeg")
190
+ def pd_cnn_predict(req: EEGRequest):
191
+ p, c, prob = predict(pd_cnn, req.features, "cnn")
192
 
193
  return {
194
+ "model": "PD_EEG_CNN",
195
+ "prediction": PD_CLASSES[p],
196
+ "confidence": c,
197
+ "probabilities": dict(zip(PD_CLASSES, prob))
 
 
198
  }