
Proyecto Asadi — Sesión 5: probando el modelo con imágenes que nunca ha visto
Hace unas sesiones aparté sin explicar mucho un pequeño grupo de imágenes en una carpeta llamada imagenes_prueba_estudiantes, solo diciendo que era “para guardarlas”. Ese momento ha llegado. Igual que en Proyecto Javierre probamos el Random Forest con 5 pacientes reales que el modelo nunca había visto, hoy hacemos lo mismo con la CNN: 10 imágenes (5 benignas y 5 malignas, repartidas entre los tres subtipos que fusionamos) que nunca formaron parte ni del entrenamiento ni del examen de validación.
Por qué esto es una prueba más dura que la del examen de validación
El 20% que Keras reservaba como prueba en las sesiones anteriores sale del mismo reparto aleatorio que el 80% de entrenamiento — es fiable, pero convive con el resto del conjunto desde el principio. Estas 10 imágenes son distintas: las separé yo a mano antes de que existiera ningún entrenamiento ni ninguna prueba, así que hay una garantía extra de que el modelo no las ha visto de ninguna forma, ni siquiera de refilón.
Primero, sin el modelo: mirar y adivinar
Antes de ejecutar nada, abrid las 10 imágenes de imagenes_asadi/imagenes_prueba_estudiantes y adivinad vosotros mismos cuáles son benignas y cuáles malignas. En la Sesión 1 ya vimos que a simple vista cuesta distinguirlas — es un buen momento para comprobarlo en persona antes de ver lo que dice la red.
import os
import matplotlib.pyplot as plt
from tensorflow import keras
carpeta_prueba = "imagenes_asadi/imagenes_prueba_estudiantes"
archivos = sorted(os.listdir(carpeta_prueba))
fig, ejes = plt.subplots(2, 5, figsize=(15, 6))
for ax, nombre in zip(ejes.flat, archivos):
imagen = keras.utils.load_img(f"{carpeta_prueba}/{nombre}", target_size=(224, 224))
ax.imshow(imagen)
ax.set_title(nombre, fontsize=8)
ax.axis("off")
plt.tight_layout()
plt.show()

El modelo que vamos a usar
De los dos modelos de la Sesión 4, usamos modelo_con_peso: el que entrenamos con class_weight, porque decidimos entonces que en un contexto clínico como este merece más la pena detectar bien los casos benignos, aunque cueste algo de exactitud general. Si habéis reiniciado el cuaderno desde la Sesión 4, tenéis que volver a ejecutar las celdas que lo construyen y entrenan antes de seguir con esta.
Prediciendo imagen por imagen
import numpy as np
# Las etiquetas reales, solo para comparar después con lo que diga el modelo
etiquetas_reales = {
"WBC-Benign-001.jpg": "Benigno",
"WBC-Benign-101.jpg": "Benigno",
"WBC-Benign-201.jpg": "Benigno",
"WBC-Benign-301.jpg": "Benigno",
"WBC-Benign-500.jpg": "Benigno",
"WBC-Malignant-Early-001.jpg": "Maligno",
"WBC-Malignant-Early-100.jpg": "Maligno",
"WBC-Malignant-Pre-001.jpg": "Maligno",
"WBC-Malignant-Pre-100.jpg": "Maligno",
"WBC-Malignant-Pro-001.jpg": "Maligno",
}
aciertos = 0
for nombre_archivo, real in etiquetas_reales.items():
ruta = f"{carpeta_prueba}/{nombre_archivo}"
imagen = keras.utils.load_img(ruta, target_size=(224, 224))
array = keras.utils.img_to_array(imagen)
array = np.expand_dims(array, axis=0) # el modelo espera un "lote" de imágenes, aunque sea de una sola
probabilidad = modelo_con_peso.predict(array, verbose=0)[0][0]
prediccion = "Maligno" if probabilidad > 0.5 else "Benigno"
acierto = prediccion == real
aciertos += acierto
print(f"{nombre_archivo}: real={real}, predicho={prediccion} (prob={probabilidad:.2f}) {'✅' if acierto else '❌'}")
print(f"\nAciertos: {aciertos}/10")
keras.utils.load_img y keras.utils.img_to_array hacen para una imagen suelta lo que image_dataset_from_directory hacía automáticamente para carpetas enteras: cargarla y convertirla en números. np.expand_dims añade una dimensión extra porque el modelo siempre espera un lote de imágenes, aunque sea de tamaño 1.

[COMPLETAR CON VUESTROS DATOS REALES: aciertos = ___ /10. ¿Se equivocó en alguna imagen benigna, en alguna maligna, o en ambas?]
Cómo interpretar el resultado
10 imágenes son muy pocas para sacar conclusiones estadísticas serias — para eso ya teníamos la matriz de confusión de la Sesión 3 y 4 sobre cientos de imágenes de validación. Lo valioso de este ejercicio es otra cosa: ver al modelo enfrentarse, uno a uno, a casos concretos y nuevos, y comprobar que las predicciones son razonamientos reproducibles, no magia. Si falla en alguna imagen, no descartéis el modelo por eso — mirad más bien si esa imagen os costó adivinarla también a simple vista al principio. Un fallo en un caso genuinamente difícil dice menos sobre el modelo que un fallo en uno “obvio”.
Próximo paso
Con esto completamos el recorrido principal de la CNN: cargar los datos (Sesión 1-2), entrenar la primera red (Sesión 2), diagnosticar sus errores con la matriz de confusión (Sesión 3), corregir el desequilibrio de clases (Sesión 4) y ponerla a prueba con casos nuevos (Sesión 5). A partir de aquí queda abierto seguir ampliando el proyecto — por ejemplo, distinguiendo los tres subtipos malignos por separado en vez de agruparlos, o probando con las imágenes “Segmented” del dataset — para cuando queráis retomarlo.

Etiqueta:AIDARAC, cnn, imagenes nuevas, keras, leucemia infantil, montesteam, prediccion, proyecto asadi



