Mikecode123 commited on
Commit
559e735
·
verified ·
1 Parent(s): da5cfde

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -17
app.py CHANGED
@@ -2,6 +2,8 @@ import torch
2
  import torch.nn as nn
3
  import torchvision.models as models
4
  from fastapi import FastAPI, UploadFile, File
 
 
5
  from PIL import Image
6
  import io
7
  import torchvision.transforms as transforms
@@ -9,7 +11,18 @@ import torchvision.transforms as transforms
9
  # =========================
10
  # APP INIT
11
  # =========================
12
- app = FastAPI(title="Alzheimer Ensemble API")
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  # =========================
15
  # DEVICE
@@ -98,7 +111,8 @@ def process_image(image_bytes):
98
  return img
99
 
100
  # =========================
101
- # PREDICTION FUNCTION (FIXED)
 
102
  # =========================
103
  def predict(model, x):
104
  with torch.no_grad():
@@ -111,6 +125,7 @@ def predict(model, x):
111
  return {
112
  "prediction": CLASSES[cls],
113
  "class_id": cls,
 
114
  "confidence": float(conf.item()),
115
  "probabilities": {
116
  CLASSES[i]: float(probs[i].item())
@@ -118,6 +133,23 @@ def predict(model, x):
118
  }
119
  }
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  # =========================
122
  # ROOT ENDPOINT
123
  # =========================
@@ -128,6 +160,7 @@ def home():
128
  "models": ["121", "169", "201"],
129
  "classes": CLASSES,
130
  "endpoints": [
 
131
  "/predict/121",
132
  "/predict/169",
133
  "/predict/201",
@@ -142,27 +175,29 @@ def home():
142
  async def predict_121(file: UploadFile = File(...)):
143
  img = process_image(await file.read())
144
  result = predict(model_121, img)
145
- result["model"] = "121"
146
- return result
147
 
148
 
149
  @app.post("/predict/169")
150
  async def predict_169(file: UploadFile = File(...)):
151
  img = process_image(await file.read())
152
  result = predict(model_169, img)
153
- result["model"] = "169"
154
- return result
155
 
156
 
157
  @app.post("/predict/201")
158
  async def predict_201(file: UploadFile = File(...)):
159
  img = process_image(await file.read())
160
  result = predict(model_201, img)
161
- result["model"] = "201"
162
- return result
163
 
164
  # =========================
165
- # ENSEMBLE PREDICTION (FINAL FIXED)
 
 
166
  # =========================
167
  @app.post("/predict/ensemble")
168
  async def ensemble(file: UploadFile = File(...)):
@@ -173,8 +208,8 @@ async def ensemble(file: UploadFile = File(...)):
173
  r2 = predict(model_169, img)
174
  r3 = predict(model_201, img)
175
 
 
176
  avg_probs = {}
177
-
178
  for c in CLASSES:
179
  avg_probs[c] = (
180
  r1["probabilities"][c] +
@@ -183,14 +218,17 @@ async def ensemble(file: UploadFile = File(...)):
183
  ) / 3
184
 
185
  final_class = max(avg_probs, key=avg_probs.get)
 
 
186
 
187
- return {
188
  "prediction": final_class,
189
- "confidence": avg_probs[final_class],
 
190
  "probabilities": avg_probs,
191
- "models": {
192
- "121": r1,
193
- "169": r2,
194
- "201": r3
195
  }
196
- }
 
2
  import torch.nn as nn
3
  import torchvision.models as models
4
  from fastapi import FastAPI, UploadFile, File
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ from fastapi.responses import JSONResponse
7
  from PIL import Image
8
  import io
9
  import torchvision.transforms as transforms
 
11
  # =========================
12
  # APP INIT
13
  # =========================
14
+ app = FastAPI(title="Alzheimer Ensemble API", version="1.0")
15
+
16
+ # =========================
17
+ # CORS
18
+ # =========================
19
+ app.add_middleware(
20
+ CORSMiddleware,
21
+ allow_origins=["*"],
22
+ allow_credentials=True,
23
+ allow_methods=["*"],
24
+ allow_headers=["*"],
25
+ )
26
 
27
  # =========================
28
  # DEVICE
 
111
  return img
112
 
113
  # =========================
114
+ # PREDICTION FUNCTION
115
+ # All confidence values are returned as floats in range [0.0, 1.0]
116
  # =========================
117
  def predict(model, x):
118
  with torch.no_grad():
 
125
  return {
126
  "prediction": CLASSES[cls],
127
  "class_id": cls,
128
+ # Confidence as 0.0–1.0 decimal
129
  "confidence": float(conf.item()),
130
  "probabilities": {
131
  CLASSES[i]: float(probs[i].item())
 
133
  }
134
  }
135
 
136
+ # =========================
137
+ # HEALTH ENDPOINT
138
+ # =========================
139
+ @app.get("/health")
140
+ def health():
141
+ return {
142
+ "status": "running",
143
+ "service": "Alzheimer MRI Ensemble API",
144
+ "models_loaded": {
145
+ "densenet121": True,
146
+ "densenet169": True,
147
+ "densenet201": True,
148
+ },
149
+ "device": str(DEVICE),
150
+ "classes": CLASSES,
151
+ }
152
+
153
  # =========================
154
  # ROOT ENDPOINT
155
  # =========================
 
160
  "models": ["121", "169", "201"],
161
  "classes": CLASSES,
162
  "endpoints": [
163
+ "/health",
164
  "/predict/121",
165
  "/predict/169",
166
  "/predict/201",
 
175
  async def predict_121(file: UploadFile = File(...)):
176
  img = process_image(await file.read())
177
  result = predict(model_121, img)
178
+ result["model"] = "densenet121"
179
+ return JSONResponse(result)
180
 
181
 
182
  @app.post("/predict/169")
183
  async def predict_169(file: UploadFile = File(...)):
184
  img = process_image(await file.read())
185
  result = predict(model_169, img)
186
+ result["model"] = "densenet169"
187
+ return JSONResponse(result)
188
 
189
 
190
  @app.post("/predict/201")
191
  async def predict_201(file: UploadFile = File(...)):
192
  img = process_image(await file.read())
193
  result = predict(model_201, img)
194
+ result["model"] = "densenet201"
195
+ return JSONResponse(result)
196
 
197
  # =========================
198
+ # ENSEMBLE PREDICTION
199
+ # Returns ensemble result with individual model results
200
+ # All confidence values are 0.0-1.0
201
  # =========================
202
  @app.post("/predict/ensemble")
203
  async def ensemble(file: UploadFile = File(...)):
 
208
  r2 = predict(model_169, img)
209
  r3 = predict(model_201, img)
210
 
211
+ # Average probabilities (all already 0.0-1.0)
212
  avg_probs = {}
 
213
  for c in CLASSES:
214
  avg_probs[c] = (
215
  r1["probabilities"][c] +
 
218
  ) / 3
219
 
220
  final_class = max(avg_probs, key=avg_probs.get)
221
+ # Ensemble confidence = max averaged probability (0.0-1.0)
222
+ ensemble_confidence = avg_probs[final_class]
223
 
224
+ return JSONResponse({
225
  "prediction": final_class,
226
+ # confidence as 0.0-1.0
227
+ "confidence": ensemble_confidence,
228
  "probabilities": avg_probs,
229
+ "individual_models": {
230
+ "densenet121": r1,
231
+ "densenet169": r2,
232
+ "densenet201": r3,
233
  }
234
+ })