Mikecode123 commited on
Commit
195e2c1
·
verified ·
1 Parent(s): 356237d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -24
app.py CHANGED
@@ -5,19 +5,31 @@ import torch
5
  import torch.nn as nn
6
  import numpy as np
7
 
 
 
 
 
8
  app = FastAPI(
9
  title="NeuroHealth EEG API",
10
- version="3.1"
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
  # REQUEST MODEL
@@ -27,7 +39,7 @@ class EEGRequest(BaseModel):
27
  features: list
28
 
29
  # =========================================================
30
- # ✔ TRUE MODEL (MATCHES YOUR TRAINED STATE_DICT)
31
  # =========================================================
32
 
33
  class EEG_MLP(nn.Module):
@@ -36,13 +48,15 @@ class EEG_MLP(nn.Module):
36
 
37
  self.net = nn.Sequential(
38
  nn.Linear(input_dim, 256),
39
- nn.BatchNorm1d(256),
40
  nn.ReLU(),
41
 
 
 
42
  nn.Linear(256, 128),
43
- nn.BatchNorm1d(128),
44
  nn.ReLU(),
45
 
 
 
46
  nn.Linear(128, output_dim)
47
  )
48
 
@@ -50,44 +64,81 @@ class EEG_MLP(nn.Module):
50
  return self.net(x)
51
 
52
  # =========================================================
53
- # LOAD MODELS (CRITICAL: INPUT DIM = 76)
54
  # =========================================================
55
 
56
  INPUT_DIM = 76
57
 
 
 
 
 
 
 
 
 
 
58
  ad_model = EEG_MLP(INPUT_DIM, 3).to(DEVICE)
59
- ad_model.load_state_dict(torch.load("AD_eeg_cnn.pth", map_location=DEVICE))
 
 
 
 
 
 
 
60
  ad_model.eval()
61
 
 
 
 
 
62
  pd_model = EEG_MLP(INPUT_DIM, 2).to(DEVICE)
63
- pd_model.load_state_dict(torch.load("PD_eeg_cnn.pth", map_location=DEVICE))
 
 
 
 
 
 
 
64
  pd_model.eval()
65
 
66
- print("Models loaded successfully with correct architecture")
 
 
67
 
68
  # =========================================================
69
- # PREDICTION ENGINE
70
  # =========================================================
71
 
72
- def predict(model, features, classes):
73
- x = torch.tensor(features, dtype=torch.float32)
 
 
 
 
74
 
75
  if x.numel() != INPUT_DIM:
76
- raise ValueError(f"Expected {INPUT_DIM} features, got {x.numel()}")
 
 
77
 
78
  x = x.unsqueeze(0).to(DEVICE)
79
 
80
  with torch.no_grad():
81
  outputs = model(x)
82
- probs = torch.softmax(outputs, dim=1).cpu().numpy()[0]
 
83
 
84
- pred = int(np.argmax(probs))
85
 
86
  return {
87
- "prediction": classes[pred],
88
- "confidence": float(probs[pred]),
89
  "probabilities": {
90
- classes[i]: float(probs[i]) for i in range(len(classes))
 
91
  }
92
  }
93
 
@@ -98,14 +149,31 @@ def predict(model, features, classes):
98
  @app.get("/")
99
  def home():
100
  return {
101
- "message": "NeuroHealth EEG API Running",
102
- "input_dim": INPUT_DIM
 
 
 
 
 
 
 
 
 
103
  }
104
 
105
  @app.post("/predict/ad")
106
  def predict_ad(req: EEGRequest):
107
- return predict(ad_model, req.features, AD_CLASSES)
 
 
 
 
108
 
109
  @app.post("/predict/pd")
110
  def predict_pd(req: EEGRequest):
111
- return predict(pd_model, req.features, PD_CLASSES)
 
 
 
 
 
5
  import torch.nn as nn
6
  import numpy as np
7
 
8
+ # =========================================================
9
+ # APP
10
+ # =========================================================
11
+
12
  app = FastAPI(
13
  title="NeuroHealth EEG API",
14
+ version="4.0"
15
  )
16
 
17
+ DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
18
 
19
  # =========================================================
20
  # LABELS
21
  # =========================================================
22
 
23
+ AD_CLASSES = [
24
+ "Alzheimer",
25
+ "FTD",
26
+ "Control"
27
+ ]
28
+
29
+ PD_CLASSES = [
30
+ "Parkinson",
31
+ "Control"
32
+ ]
33
 
34
  # =========================================================
35
  # REQUEST MODEL
 
39
  features: list
40
 
41
  # =========================================================
42
+ # MODEL ARCHITECTURE
43
  # =========================================================
44
 
45
  class EEG_MLP(nn.Module):
 
48
 
49
  self.net = nn.Sequential(
50
  nn.Linear(input_dim, 256),
 
51
  nn.ReLU(),
52
 
53
+ nn.BatchNorm1d(256),
54
+
55
  nn.Linear(256, 128),
 
56
  nn.ReLU(),
57
 
58
+ nn.BatchNorm1d(128),
59
+
60
  nn.Linear(128, output_dim)
61
  )
62
 
 
64
  return self.net(x)
65
 
66
  # =========================================================
67
+ # SETTINGS
68
  # =========================================================
69
 
70
  INPUT_DIM = 76
71
 
72
+ AD_MODEL_PATH = "AD_eeg_cnn_ad_ftd_cn.pt"
73
+ PD_MODEL_PATH = "PD_eeg_cnn.pth"
74
+
75
+ # =========================================================
76
+ # LOAD MODELS
77
+ # =========================================================
78
+
79
+ print("Loading AD model...")
80
+
81
  ad_model = EEG_MLP(INPUT_DIM, 3).to(DEVICE)
82
+
83
+ ad_model.load_state_dict(
84
+ torch.load(
85
+ AD_MODEL_PATH,
86
+ map_location=DEVICE
87
+ )
88
+ )
89
+
90
  ad_model.eval()
91
 
92
+ print("AD model loaded successfully")
93
+
94
+ print("Loading PD model...")
95
+
96
  pd_model = EEG_MLP(INPUT_DIM, 2).to(DEVICE)
97
+
98
+ pd_model.load_state_dict(
99
+ torch.load(
100
+ PD_MODEL_PATH,
101
+ map_location=DEVICE
102
+ )
103
+ )
104
+
105
  pd_model.eval()
106
 
107
+ print("PD model loaded successfully")
108
+
109
+ print("All models loaded")
110
 
111
  # =========================================================
112
+ # PREDICTION FUNCTION
113
  # =========================================================
114
 
115
+ def predict(model, features, class_names):
116
+
117
+ x = torch.tensor(
118
+ features,
119
+ dtype=torch.float32
120
+ )
121
 
122
  if x.numel() != INPUT_DIM:
123
+ raise ValueError(
124
+ f"Expected {INPUT_DIM} features but received {x.numel()}"
125
+ )
126
 
127
  x = x.unsqueeze(0).to(DEVICE)
128
 
129
  with torch.no_grad():
130
  outputs = model(x)
131
+ probs = torch.softmax(outputs, dim=1)
132
+ probs = probs.cpu().numpy()[0]
133
 
134
+ pred_idx = int(np.argmax(probs))
135
 
136
  return {
137
+ "prediction": class_names[pred_idx],
138
+ "confidence": float(probs[pred_idx]),
139
  "probabilities": {
140
+ class_names[i]: float(probs[i])
141
+ for i in range(len(class_names))
142
  }
143
  }
144
 
 
149
  @app.get("/")
150
  def home():
151
  return {
152
+ "status": "running",
153
+ "device": str(DEVICE),
154
+ "input_features": INPUT_DIM,
155
+ "ad_classes": AD_CLASSES,
156
+ "pd_classes": PD_CLASSES
157
+ }
158
+
159
+ @app.get("/health")
160
+ def health():
161
+ return {
162
+ "status": "healthy"
163
  }
164
 
165
  @app.post("/predict/ad")
166
  def predict_ad(req: EEGRequest):
167
+ return predict(
168
+ ad_model,
169
+ req.features,
170
+ AD_CLASSES
171
+ )
172
 
173
  @app.post("/predict/pd")
174
  def predict_pd(req: EEGRequest):
175
+ return predict(
176
+ pd_model,
177
+ req.features,
178
+ PD_CLASSES
179
+ )