rkonan commited on
Commit
29ffeab
·
1 Parent(s): 084ab60

nouvelle version

Browse files
app/__pycache__/main.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/main.cpython-312.pyc and b/app/__pycache__/main.cpython-312.pyc differ
 
app/__pycache__/voting.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/voting.cpython-312.pyc and b/app/__pycache__/voting.cpython-312.pyc differ
 
app/main.py CHANGED
@@ -34,10 +34,16 @@ class ImagePayload(BaseModel):
34
  async def predict(request: Request,
35
  file: UploadFile = File(None),
36
  payload: Union[ImagePayload, None] = None,
37
- mode: str = Query("single", enum=["single", "voting"], description="Mode de prédiction"),
38
- show_heatmap: bool = Query(False, description="Afficher la heatmap")):
 
 
 
39
  logger.info("🔁 Requête reçue")
40
  logger.info(f"✅ Mode : {mode}")
 
 
 
41
  try:
42
  # Cas 1 : multipart avec fichier
43
  if file is not None:
@@ -59,7 +65,7 @@ async def predict(request: Request,
59
 
60
  # Appel de ta logique de prédiction
61
  logger.debug("🔍 Appel du vote multi-modèles...")
62
- prediction = await soft_voting(model_configs,image_bytes,mode,show_heatmap)
63
 
64
  # Pour l’instant : réponse simulée
65
  return prediction
 
34
  async def predict(request: Request,
35
  file: UploadFile = File(None),
36
  payload: Union[ImagePayload, None] = None,
37
+ mode: str = Query("single", enum=["single", "voting","automatic"], description="Mode de prédiction"),
38
+ show_heatmap: bool = Query(False, description="Afficher la heatmap"),
39
+ default_model: str = Query("efficientnetv2m", enum=["efficientnetv2m", "resnet50"], description="Model par défaut")
40
+ ):
41
+
42
  logger.info("🔁 Requête reçue")
43
  logger.info(f"✅ Mode : {mode}")
44
+ logger.info(f"✅ Default model : {default_model}")
45
+ logger.info(f"✅ Show heatmap : {show_heatmap}")
46
+
47
  try:
48
  # Cas 1 : multipart avec fichier
49
  if file is not None:
 
65
 
66
  # Appel de ta logique de prédiction
67
  logger.debug("🔍 Appel du vote multi-modèles...")
68
+ prediction = await soft_voting(model_configs,image_bytes,mode,show_heatmap,default_model)
69
 
70
  # Pour l’instant : réponse simulée
71
  return prediction
app/voting.py CHANGED
@@ -51,7 +51,164 @@ def compute_js_divergence(all_probs):
51
 
52
  # Si js_divergence > 0.1 → Désaccord modéré
53
 
54
- async def soft_voting(model_configs,image_bytes: bytes,mode,show_heatmap):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  logger.info("🔁 Début du vote multi-modèles")
56
  all_probs = []
57
  models = []
 
51
 
52
  # Si js_divergence > 0.1 → Désaccord modéré
53
 
54
+ async def soft_voting(model_configs, image_bytes: bytes, mode, show_heatmap, default_model):
55
+ logger.info("🔁 Début de la prédiction multi-modèles")
56
+
57
+ all_probs = []
58
+ models = []
59
+ models_predictions = []
60
+ models_confidences = []
61
+ models_entropies = []
62
+ models_uncertainties = []
63
+ models_heatmaps = []
64
+
65
+ # On commence toujours par le modèle par défaut
66
+ default_config = next((config for config in model_configs if config["model_name"].lower() == default_model.lower()), None)
67
+
68
+ if default_config is None:
69
+ logger.error(f"❌ Modèle par défaut '{default_model}' introuvable dans les configurations.")
70
+ return None
71
+
72
+ async with aiohttp.ClientSession() as session:
73
+ # Prédiction avec le modèle par défaut
74
+ logger.info(f"🚀 Prédiction avec le modèle par défaut : {default_model}")
75
+ prediction = predict_with_model(default_config, image_bytes, show_heatmap)
76
+
77
+ all_probs.append(prediction["preds"])
78
+ logger.info(f" predicted_class: {prediction["predicted_class"]}")
79
+ models_predictions.append(prediction["predicted_class"])
80
+ models_confidences.append(prediction["confidence"])
81
+ models_entropies.append(prediction["entropy"])
82
+ models_uncertainties.append(prediction["is_uncertain_model"])
83
+ models.append(default_config["model_name"])
84
+
85
+ if show_heatmap:
86
+ heatmap = prediction.get("heatmap")
87
+ if heatmap and len(heatmap) > 0:
88
+ models_heatmaps.append(heatmap)
89
+ else:
90
+ logger.warning(f"⚠️ Heatmap vide ou invalide pour le modèle {default_config['model_name']}")
91
+
92
+ if not all_probs:
93
+ logger.warning("⚠️ Aucune prédiction reçue, vérifie les APIs appelées.")
94
+ raise Exception("No predictions received.")
95
+
96
+ mean_probs = np.mean(all_probs, axis=0)
97
+ final_class = int(np.argmax(mean_probs))
98
+ final_confidence = float(mean_probs[final_class])
99
+ entropy=float(compute_entropy_safe(mean_probs))
100
+ jsd_score = float(compute_js_divergence(all_probs))
101
+
102
+
103
+ logger.debug(f"🧠 Moyenne des probabilités : {mean_probs.tolist()}")
104
+
105
+
106
+ # Mode 'single' : on s'arrête ici
107
+ if mode == "single":
108
+ is_global_uncertain=models_uncertainties[0]
109
+ logger.info("🛑 Mode 'single' activé, utilisation uniquement du modèle par défaut.")
110
+
111
+ logger.info(f"✅ Prediction terminé : classe={final_class}"
112
+ f"confiance={final_confidence:.4f}\n"
113
+ f"entropy={entropy:.4f}\n"
114
+ f"jsd_score={jsd_score:.4f}\n"
115
+ f"is_global_uncertain={is_global_uncertain}\n"
116
+ )
117
+ return {
118
+ "predicted_class": final_class,
119
+ "confidence": final_confidence,
120
+ "entropy":entropy,
121
+ "jsd_score":jsd_score,
122
+ "models": models,
123
+ "is_global_uncertain":is_global_uncertain,
124
+ "models_predictions": models_predictions,
125
+ "models_confidences": models_confidences,
126
+ "models_entropies":models_entropies,
127
+ "models_uncertainties":models_uncertainties,
128
+ "models_heatmaps": models_heatmaps
129
+
130
+ }
131
+
132
+ # Si mode == 'automatic' et confiance suffisante, on s'arrête
133
+ if mode == "automatic" and prediction["confidence"] >= 0.90:
134
+ is_global_uncertain=models_uncertainties[0]
135
+ logger.info(f"✅ Confiance élevée ({prediction['confidence']:.2f}), pas besoin de voter.")
136
+ logger.info(f"✅ Prediction terminé : classe={final_class}"
137
+ f"confiance={final_confidence:.4f}\n"
138
+ f"entropy={entropy:.4f}\n"
139
+ f"jsd_score={jsd_score:.4f}\n"
140
+ f"is_global_uncertain={is_global_uncertain}\n"
141
+ )
142
+ return {
143
+ "predicted_class": final_class,
144
+ "confidence": final_confidence,
145
+ "entropy":entropy,
146
+ "jsd_score":jsd_score,
147
+ "models": models,
148
+ "is_global_uncertain":is_global_uncertain,
149
+ "models_predictions": models_predictions,
150
+ "models_confidences": models_confidences,
151
+ "models_entropies":models_entropies,
152
+ "models_uncertainties":models_uncertainties,
153
+ "models_heatmaps": models_heatmaps
154
+
155
+ }
156
+
157
+ # Sinon, on continue avec tous les autres modèles (voting ou automatic avec faible confiance)
158
+ logger.info(f"🔍 Mode '{mode}' : Prédictions complémentaires en cours.")
159
+
160
+ for config in model_configs:
161
+ if config["model_name"].lower() == default_model.lower():
162
+ continue # On a déjà traité le modèle par défaut
163
+
164
+ prediction = predict_with_model(config, image_bytes, show_heatmap)
165
+
166
+ all_probs.append(prediction["preds"])
167
+ models_predictions.append(prediction["predicted_class"])
168
+ models_confidences.append(prediction["confidence"])
169
+ models_entropies.append(prediction["entropy"])
170
+ models_uncertainties.append(prediction["is_uncertain_model"])
171
+ models.append(config["model_name"])
172
+
173
+
174
+
175
+ if show_heatmap:
176
+ heatmap = prediction.get("heatmap")
177
+ if heatmap and len(heatmap) > 0:
178
+ models_heatmaps.append(heatmap)
179
+ else:
180
+ logger.warning(f"⚠️ Heatmap vide ou invalide pour le modèle {config['model_name']}")
181
+
182
+ mean_probs = np.mean(all_probs, axis=0)
183
+ final_class = int(np.argmax(mean_probs))
184
+ final_confidence = float(mean_probs[final_class])
185
+ entropy=float(compute_entropy_safe(mean_probs))
186
+ jsd_score = float(compute_js_divergence(all_probs))
187
+
188
+ is_global_uncertain = any(models_uncertainties) and jsd_score > shannon_threashold
189
+ logger.info(f"✅ Prediction terminé : classe={final_class}"
190
+ f"confiance={final_confidence:.4f}\n"
191
+ f"entropy={entropy:.4f}\n"
192
+ f"jsd_score={jsd_score:.4f}\n"
193
+ f"is_global_uncertain={is_global_uncertain}\n"
194
+ )
195
+ return {
196
+ "predicted_class": final_class,
197
+ "confidence": final_confidence,
198
+ "entropy":entropy,
199
+ "jsd_score":jsd_score,
200
+ "models": models,
201
+ "is_global_uncertain":is_global_uncertain,
202
+ "models_predictions": models_predictions,
203
+ "models_confidences": models_confidences,
204
+ "models_entropies":models_entropies,
205
+ "models_uncertainties":models_uncertainties,
206
+ "models_heatmaps": models_heatmaps
207
+
208
+ }
209
+
210
+
211
+ async def soft_voting_v1(model_configs,image_bytes: bytes,mode,show_heatmap,default_model):
212
  logger.info("🔁 Début du vote multi-modèles")
213
  all_probs = []
214
  models = []