Spaces:
Sleeping
Sleeping
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()
|