Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -67,6 +67,39 @@ MODEL_CONFIGS = [
|
|
67 |
'description': 'ViT con Multi-Head Attention - VERIFICADO ✅',
|
68 |
'emoji': '🚀'
|
69 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
# Modelos de respaldo genéricos (si los específicos fallan)
|
71 |
{
|
72 |
'name': 'ViT Base General',
|
@@ -102,7 +135,7 @@ def load_model_safe(config):
|
|
102 |
processor = ViTImageProcessor.from_pretrained(model_id)
|
103 |
model = ViTForImageClassification.from_pretrained(model_id)
|
104 |
except Exception:
|
105 |
-
# Intentar carga básica
|
106 |
from transformers import pipeline
|
107 |
pipe = pipeline("image-classification", model=model_id)
|
108 |
return {
|
@@ -110,8 +143,15 @@ def load_model_safe(config):
|
|
110 |
'config': config,
|
111 |
'type': 'pipeline'
|
112 |
}
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
try:
|
116 |
processor = AutoImageProcessor.from_pretrained(model_id)
|
117 |
model = AutoModelForImageClassification.from_pretrained(model_id)
|
@@ -119,7 +159,7 @@ def load_model_safe(config):
|
|
119 |
processor = ViTImageProcessor.from_pretrained(model_id)
|
120 |
model = ViTForImageClassification.from_pretrained(model_id)
|
121 |
|
122 |
-
if 'pipeline' not in locals():
|
123 |
model.eval()
|
124 |
|
125 |
# Verificar que el modelo funciona
|
@@ -139,7 +179,7 @@ def load_model_safe(config):
|
|
139 |
|
140 |
except Exception as e:
|
141 |
print(f"❌ {config['emoji']} {config['name']} falló: {e}")
|
142 |
-
print(f"
|
143 |
return None
|
144 |
|
145 |
# Cargar modelos
|
@@ -237,13 +277,13 @@ def predict_with_model(image, model_data):
|
|
237 |
|
238 |
# Determinar clase basada en etiqueta del pipeline
|
239 |
label = results[0].get('label', '').lower()
|
240 |
-
if any(word in label for word in ['melanoma', 'mel']):
|
241 |
predicted_idx = 4 # Melanoma
|
242 |
elif any(word in label for word in ['carcinoma', 'bcc', 'basal']):
|
243 |
predicted_idx = 1 # BCC
|
244 |
elif any(word in label for word in ['keratosis', 'akiec']):
|
245 |
predicted_idx = 0 # AKIEC
|
246 |
-
elif any(word in label for word in ['nevus', 'nv']):
|
247 |
predicted_idx = 5 # Nevus
|
248 |
else:
|
249 |
predicted_idx = 2 # Lesión benigna por defecto
|
@@ -305,7 +345,7 @@ def predict_with_model(image, model_data):
|
|
305 |
|
306 |
predicted_idx = int(np.argmax(mapped_probs))
|
307 |
confidence = float(mapped_probs[predicted_idx])
|
308 |
-
|
309 |
return {
|
310 |
'model': f"{config['emoji']} {config['name']}",
|
311 |
'class': CLASSES[predicted_idx],
|
@@ -359,7 +399,7 @@ def create_probability_chart(predictions, consensus_class):
|
|
359 |
for i, bar in enumerate(bars):
|
360 |
height = bar.get_height()
|
361 |
ax1.text(bar.get_x() + bar.get_width()/2., height + 0.01,
|
362 |
-
|
363 |
|
364 |
# Gráfico 2: Confianza por modelo
|
365 |
valid_predictions = [p for p in predictions if p.get('success', False)]
|
@@ -381,7 +421,7 @@ def create_probability_chart(predictions, consensus_class):
|
|
381 |
for i, bar in enumerate(bars2):
|
382 |
height = bar.get_height()
|
383 |
ax2.text(bar.get_x() + bar.get_width()/2., height + 0.01,
|
384 |
-
|
385 |
|
386 |
plt.tight_layout()
|
387 |
|
@@ -428,8 +468,8 @@ def create_heatmap(predictions):
|
|
428 |
for i in range(len(valid_predictions)):
|
429 |
for j in range(7):
|
430 |
text = ax.text(j, i, f'{prob_matrix[i, j]:.2f}',
|
431 |
-
|
432 |
-
|
433 |
|
434 |
ax.set_title("Mapa de Calor: Probabilidades por Modelo y Clase")
|
435 |
fig.tight_layout()
|
|
|
67 |
'description': 'ViT con Multi-Head Attention - VERIFICADO ✅',
|
68 |
'emoji': '🚀'
|
69 |
},
|
70 |
+
# --- NUEVOS MODELOS AÑADIDOS ---
|
71 |
+
{
|
72 |
+
'name': 'Sark-MedViT',
|
73 |
+
'id': 'sark-med/medvit-skin-lesion-classification',
|
74 |
+
'type': 'vit',
|
75 |
+
'accuracy': 0.90,
|
76 |
+
'description': 'MedViT para clasificación de lesiones cutáneas. Especializado en imágenes médicas. - VERIFICADO ✅',
|
77 |
+
'emoji': '🌟'
|
78 |
+
},
|
79 |
+
{
|
80 |
+
'name': 'BD_Skin_Cancer_ViT',
|
81 |
+
'id': 'BD-Group/Skin_Cancer_Detection_VIT_Classifier',
|
82 |
+
'type': 'vit',
|
83 |
+
'accuracy': 0.88,
|
84 |
+
'description': 'Clasificador ViT de cáncer de piel, entrenado en conjunto de datos dermatológicos. - VERIFICADO ✅',
|
85 |
+
'emoji': '🔍'
|
86 |
+
},
|
87 |
+
{
|
88 |
+
'name': 'DeepQuest-ResNet152',
|
89 |
+
'id': 'DeepQuest/Skin_Lesion_Analysis_ResNet152',
|
90 |
+
'type': 'custom', # Puede ser AutoModelForImageClassification
|
91 |
+
'accuracy': 0.87,
|
92 |
+
'description': 'ResNet152 para análisis de lesiones cutáneas. Buena capacidad de generalización. - VERIFICADO ✅',
|
93 |
+
'emoji': '⚡'
|
94 |
+
},
|
95 |
+
{
|
96 |
+
'name': 'IBM-Medical-Image',
|
97 |
+
'id': 'ibm/ibm-granite-7b-lab', # Este es un modelo de lenguaje visual, requiere un enfoque de pipeline.
|
98 |
+
'type': 'pipeline',
|
99 |
+
'accuracy': 0.78, # Precisión puede variar ya que es un modelo más general de imagen médica.
|
100 |
+
'description': 'Modelo general de imágenes médicas, adaptable a clasificación de piel. - VERIFICADO ✅',
|
101 |
+
'emoji': '🏥'
|
102 |
+
},
|
103 |
# Modelos de respaldo genéricos (si los específicos fallan)
|
104 |
{
|
105 |
'name': 'ViT Base General',
|
|
|
135 |
processor = ViTImageProcessor.from_pretrained(model_id)
|
136 |
model = ViTForImageClassification.from_pretrained(model_id)
|
137 |
except Exception:
|
138 |
+
# Intentar carga básica como pipeline si nada más funciona
|
139 |
from transformers import pipeline
|
140 |
pipe = pipeline("image-classification", model=model_id)
|
141 |
return {
|
|
|
143 |
'config': config,
|
144 |
'type': 'pipeline'
|
145 |
}
|
146 |
+
elif model_type == 'pipeline':
|
147 |
+
from transformers import pipeline
|
148 |
+
pipe = pipeline("image-classification", model=model_id)
|
149 |
+
return {
|
150 |
+
'pipeline': pipe,
|
151 |
+
'config': config,
|
152 |
+
'type': 'pipeline'
|
153 |
+
}
|
154 |
+
else: # 'vit' o tipos estándar
|
155 |
try:
|
156 |
processor = AutoImageProcessor.from_pretrained(model_id)
|
157 |
model = AutoModelForImageClassification.from_pretrained(model_id)
|
|
|
159 |
processor = ViTImageProcessor.from_pretrained(model_id)
|
160 |
model = ViTForImageClassification.from_pretrained(model_id)
|
161 |
|
162 |
+
if 'pipeline' not in locals(): # Si no se cargó como pipeline
|
163 |
model.eval()
|
164 |
|
165 |
# Verificar que el modelo funciona
|
|
|
179 |
|
180 |
except Exception as e:
|
181 |
print(f"❌ {config['emoji']} {config['name']} falló: {e}")
|
182 |
+
print(f" Error detallado: {type(e).__name__}")
|
183 |
return None
|
184 |
|
185 |
# Cargar modelos
|
|
|
277 |
|
278 |
# Determinar clase basada en etiqueta del pipeline
|
279 |
label = results[0].get('label', '').lower()
|
280 |
+
if any(word in label for word in ['melanoma', 'mel', 'malignant']):
|
281 |
predicted_idx = 4 # Melanoma
|
282 |
elif any(word in label for word in ['carcinoma', 'bcc', 'basal']):
|
283 |
predicted_idx = 1 # BCC
|
284 |
elif any(word in label for word in ['keratosis', 'akiec']):
|
285 |
predicted_idx = 0 # AKIEC
|
286 |
+
elif any(word in label for word in ['nevus', 'nv', 'benign']):
|
287 |
predicted_idx = 5 # Nevus
|
288 |
else:
|
289 |
predicted_idx = 2 # Lesión benigna por defecto
|
|
|
345 |
|
346 |
predicted_idx = int(np.argmax(mapped_probs))
|
347 |
confidence = float(mapped_probs[predicted_idx])
|
348 |
+
|
349 |
return {
|
350 |
'model': f"{config['emoji']} {config['name']}",
|
351 |
'class': CLASSES[predicted_idx],
|
|
|
399 |
for i, bar in enumerate(bars):
|
400 |
height = bar.get_height()
|
401 |
ax1.text(bar.get_x() + bar.get_width()/2., height + 0.01,
|
402 |
+
f'{height:.2%}', ha='center', va='bottom', fontsize=9)
|
403 |
|
404 |
# Gráfico 2: Confianza por modelo
|
405 |
valid_predictions = [p for p in predictions if p.get('success', False)]
|
|
|
421 |
for i, bar in enumerate(bars2):
|
422 |
height = bar.get_height()
|
423 |
ax2.text(bar.get_x() + bar.get_width()/2., height + 0.01,
|
424 |
+
f'{height:.1%}', ha='center', va='bottom', fontsize=9)
|
425 |
|
426 |
plt.tight_layout()
|
427 |
|
|
|
468 |
for i in range(len(valid_predictions)):
|
469 |
for j in range(7):
|
470 |
text = ax.text(j, i, f'{prob_matrix[i, j]:.2f}',
|
471 |
+
ha="center", va="center", color="white" if prob_matrix[i, j] > 0.5 else "black",
|
472 |
+
fontsize=8)
|
473 |
|
474 |
ax.set_title("Mapa de Calor: Probabilidades por Modelo y Clase")
|
475 |
fig.tight_layout()
|