Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -52,6 +52,23 @@ MODEL_CONFIGS = {
|
|
52 |
'description': 'Modelo ISIC 2024 con SMOTE para desequilibrio de clases',
|
53 |
'emoji': '⚖️'
|
54 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
],
|
56 |
"generales": [
|
57 |
{
|
@@ -292,28 +309,34 @@ def predict_with_model(image, model_data):
|
|
292 |
|
293 |
probabilities = F.softmax(logits, dim=-1).cpu().numpy()[0]
|
294 |
|
295 |
-
|
|
|
296 |
mapped_probs = probabilities
|
297 |
-
elif len(probabilities) ==
|
298 |
-
mapped_probs = np.ones(7) / 7
|
299 |
-
# Ajuste heurístico para modelos generales:
|
300 |
-
mapped_probs[5] += 0.1
|
301 |
-
mapped_probs[2] += 0.05
|
302 |
-
mapped_probs = mapped_probs / np.sum(mapped_probs)
|
303 |
-
|
304 |
-
elif len(probabilities) == 2: # Binary classification
|
305 |
mapped_probs = np.zeros(7)
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
mapped_probs[
|
310 |
-
|
311 |
-
mapped_probs[
|
312 |
-
|
313 |
-
|
314 |
-
mapped_probs[
|
315 |
-
|
316 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
mapped_probs = np.ones(7) / 7
|
318 |
|
319 |
predicted_idx = int(np.argmax(mapped_probs))
|
@@ -510,6 +533,10 @@ def analizar_lesion(img):
|
|
510 |
class_votes[class_name] += 1
|
511 |
confidence_sum[class_name] += confidence
|
512 |
|
|
|
|
|
|
|
|
|
513 |
consensus_class = max(class_votes.keys(), key=lambda x: class_votes[x])
|
514 |
avg_confidence = confidence_sum[consensus_class] / class_votes[consensus_class]
|
515 |
|
@@ -736,7 +763,8 @@ def create_interface():
|
|
736 |
gr.Markdown(f"""
|
737 |
---
|
738 |
**Estado del Sistema:**
|
739 |
-
- ✅ Modelos
|
|
|
740 |
- 🎯 Precisión promedio estimada: {np.mean(list(model_performance.values())):.1%}
|
741 |
- ⚠️ **Este sistema es solo para apoyo diagnóstico. Consulte siempre a un profesional médico.**
|
742 |
""")
|
@@ -747,7 +775,8 @@ if __name__ == "__main__":
|
|
747 |
print(f"\n🚀 Sistema listo!")
|
748 |
# Calcular el número total de modelos posibles
|
749 |
total_possible_models = sum(len(configs) for configs in MODEL_CONFIGS.values())
|
750 |
-
print(f"📊 Modelos
|
|
|
751 |
print(f"🎯 Estado: {'✅ Operativo' if loaded_models else '❌ Sin modelos'}")
|
752 |
|
753 |
demo = create_interface()
|
|
|
52 |
'description': 'Modelo ISIC 2024 con SMOTE para desequilibrio de clases',
|
53 |
'emoji': '⚖️'
|
54 |
},
|
55 |
+
# --- NUEVOS MODELOS ESPECIALIZADOS AÑADIDOS ---
|
56 |
+
{
|
57 |
+
'name': 'ViT ISIC Binary',
|
58 |
+
'id': 'ahishamm/vit-base-binary-isic-sharpened-patch-32',
|
59 |
+
'type': 'vit',
|
60 |
+
'accuracy': 0.89, # Reported accuracy
|
61 |
+
'description': 'ViT para clasificación binaria de lesiones ISIC (benigno/maligno)',
|
62 |
+
'emoji': '🔬'
|
63 |
+
},
|
64 |
+
{
|
65 |
+
'name': 'ViT ISIC Multi-class',
|
66 |
+
'id': 'ahishamm/vit-base-isic-patch-16',
|
67 |
+
'type': 'vit',
|
68 |
+
'accuracy': 0.79, # Reported accuracy
|
69 |
+
'description': 'ViT para clasificación multi-clase de lesiones ISIC',
|
70 |
+
'emoji': '🔍'
|
71 |
+
}
|
72 |
],
|
73 |
"generales": [
|
74 |
{
|
|
|
309 |
|
310 |
probabilities = F.softmax(logits, dim=-1).cpu().numpy()[0]
|
311 |
|
312 |
+
# --- Mapeo de probabilidades según el número de clases de salida del modelo ---
|
313 |
+
if len(probabilities) == 7: # Modelos ya entrenados para 7 clases de piel
|
314 |
mapped_probs = probabilities
|
315 |
+
elif len(probabilities) == 2: # Modelos binarios (e.g., maligno/benigno)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
mapped_probs = np.zeros(7)
|
317 |
+
# Asumimos que la clase 0 es benigna y la 1 es maligna en un modelo binario
|
318 |
+
if probabilities[1] > 0.5: # Predicción de maligno
|
319 |
+
# Distribuimos la probabilidad maligna entre los tipos malignos conocidos, dando más peso al melanoma
|
320 |
+
mapped_probs[4] = probabilities[1] * 0.5 # Melanoma
|
321 |
+
mapped_probs[1] = probabilities[1] * 0.3 # BCC
|
322 |
+
mapped_probs[0] = probabilities[1] * 0.2 # AKIEC
|
323 |
+
else: # Predicción de benigno
|
324 |
+
# Distribuimos la probabilidad benigna entre los tipos benignos conocidos, dando más peso al nevus
|
325 |
+
mapped_probs[5] = probabilities[0] * 0.6 # Nevus (más común)
|
326 |
+
mapped_probs[2] = probabilities[0] * 0.2 # BKL
|
327 |
+
mapped_probs[3] = probabilities[0] * 0.1 # DF
|
328 |
+
mapped_probs[6] = probabilities[0] * 0.1 # VASC
|
329 |
+
mapped_probs = mapped_probs / np.sum(mapped_probs) # Normalizar para que sumen 1
|
330 |
+
elif len(probabilities) == 1000: # Modelos generales como los de ImageNet (1000 clases)
|
331 |
+
mapped_probs = np.ones(7) / 7 # Empezamos con distribución uniforme
|
332 |
+
# Ajuste heurístico: Asignamos un poco más de peso a clases benignas por defecto
|
333 |
+
# Esto es una simplificación, ya que mapear 1000 clases a 7 es muy complejo sin un mapping explícito.
|
334 |
+
# Se busca que los modelos generales no "alarmen" sin un entrenamiento específico en piel.
|
335 |
+
mapped_probs[5] += 0.1 # Aumentar Nevus (NV) ligeramente
|
336 |
+
mapped_probs[2] += 0.05 # Aumentar Lesión queratósica benigna (BKL) ligeramente
|
337 |
+
mapped_probs = mapped_probs / np.sum(mapped_probs) # Re-normalizar
|
338 |
+
else: # Otros casos de dimensiones de salida no esperadas: distribución uniforme
|
339 |
+
print(f"Advertencia: Dimensión de salida inesperada para {config['name']} ({len(probabilities)} clases). Usando distribución uniforme.")
|
340 |
mapped_probs = np.ones(7) / 7
|
341 |
|
342 |
predicted_idx = int(np.argmax(mapped_probs))
|
|
|
533 |
class_votes[class_name] += 1
|
534 |
confidence_sum[class_name] += confidence
|
535 |
|
536 |
+
# Manejar el caso donde no hay votos por alguna razón (aunque predictions ya valida que hay)
|
537 |
+
if not class_votes:
|
538 |
+
return "<h3>❌ Error en el Consenso</h3><p>No se pudieron consolidar los votos de los modelos.</p>"
|
539 |
+
|
540 |
consensus_class = max(class_votes.keys(), key=lambda x: class_votes[x])
|
541 |
avg_confidence = confidence_sum[consensus_class] / class_votes[consensus_class]
|
542 |
|
|
|
763 |
gr.Markdown(f"""
|
764 |
---
|
765 |
**Estado del Sistema:**
|
766 |
+
- ✅ Modelos configurados para carga: {total_possible_models} ({len(MODEL_CONFIGS['especializados'])} especializados, {len(MODEL_CONFIGS['generales'])} generales).
|
767 |
+
- 🚀 Modelos cargados exitosamente: {len(loaded_models)}
|
768 |
- 🎯 Precisión promedio estimada: {np.mean(list(model_performance.values())):.1%}
|
769 |
- ⚠️ **Este sistema es solo para apoyo diagnóstico. Consulte siempre a un profesional médico.**
|
770 |
""")
|
|
|
775 |
print(f"\n🚀 Sistema listo!")
|
776 |
# Calcular el número total de modelos posibles
|
777 |
total_possible_models = sum(len(configs) for configs in MODEL_CONFIGS.values())
|
778 |
+
print(f"📊 Modelos configurados para carga: {total_possible_models} ({len(MODEL_CONFIGS['especializados'])} especializados, {len(MODEL_CONFIGS['generales'])} generales).")
|
779 |
+
print(f"🚀 Modelos cargados exitosamente: {len(loaded_models)}")
|
780 |
print(f"🎯 Estado: {'✅ Operativo' if loaded_models else '❌ Sin modelos'}")
|
781 |
|
782 |
demo = create_interface()
|