Entrenamiento de red neuronal para detectar neumonía

Resumen

Detectar neumonía con un modelo de deep learning implica entrenar una red neuronal para que reconozca patrones en radiografías, igual que lo haría un radiólogo. Para lograrlo, necesitas tres piezas clave durante el entrenamiento: la función de pérdida, el optimizador y el scheduler. Aquí te explico cómo encajan y cómo se traduce todo a código.

¿Qué es la función de pérdida y por qué usar CrossEntropyLoss?

La función de pérdida, o loss, mide qué tan mal predice tu modelo. El objetivo es minimizarla en cada iteración, porque eso significa que el modelo está aprendiendo a clasificar mejor.

Para este proyecto se usa CrossEntropyLoss [01:00], una opción ideal cuando quieres detectar si una radiografía corresponde a neumonía o no, y además te deja la puerta abierta para sumar más clases en el futuro (otras enfermedades, por ejemplo).

Internamente, CrossEntropyLoss aplica la función softmax sobre los logits, que son los valores sin normalizar que salen del flatten de la red. La softmax convierte esos números en probabilidades. En el ejemplo de la clase, las probabilidades resultantes fueron 0.24, 0.590 y 0.0986, una por cada categoría posible.

¿Qué son los logits en una red neuronal? Son los valores crudos sin normalizar que salen de la última capa, antes de aplicar softmax. Representan la salida del flatten y se transforman en probabilidades dentro de la función de pérdida.

Si la etiqueta correcta corresponde a la clase 1, se aplica una función logarítmica sobre la probabilidad de esa clase y se obtiene un valor de loss de 0.4170 [02:30]. Ese número es el que el modelo busca reducir epoch tras epoch.

¿Cómo se calcula CrossEntropyLoss en código?

En PyTorch el flujo es directo: importas torch, defines tus logits, indicas la clase real y pasas ambos a la función. Al ejecutar, obtienes las probabilidades junto con el valor de loss.

python import torch import torch.nn as nn

logits = torch.tensor([[1.2, 2.5, 0.3]]) clase_real = torch.tensor([1])

criterio = nn.CrossEntropyLoss() loss = criterio(logits, clase_real)

La clase real puede representar normal, neumonía u otra enfermedad. El número que pasas como etiqueta indica a qué categoría pertenece ese vector característico.

¿Qué hacen el optimizador y el scheduler durante el entrenamiento?

El optimizador actualiza los pesos de la red para que aprenda en cada iteración. Entre los más populares están SGD, Adam y RMSProp [03:45]. Para este caso de clasificación multiclase se usa SGD, aunque cuando dudes cuál elegir, Adam suele recomendarse por su buen costo computacional.

El scheduler ajusta dinámicamente el learning rate, esa tasa que define qué tan grandes son los pasos del aprendizaje. Su misión es ayudar al modelo a converger mejor y más rápido.

¿Qué es el learning rate? Es el tamaño del paso con el que el modelo ajusta sus pesos en cada iteración. Suele empezar en valores chicos como 0.001, y el scheduler lo va reduciendo para afinar el aprendizaje.

En la implementación, el scheduler se configura para que cada 7 epochs multiplique el learning rate por 0.1. Si arrancas con 0.001, al llegar al epoch 7 pasa a 0.0001, y al epoch 14 baja a 0.00001. Ese ajuste fino evita que el modelo dé saltos demasiado grandes cuando ya está cerca del óptimo.

No te abrumes con la matemática: en la práctica suele bastar con los valores por defecto que recomienda la documentación.

¿Cómo se estructura la función de entrenamiento en PyTorch?

La función de entrenamiento recibe la arquitectura de la red, la función de loss, el optimizador, el scheduler y la cantidad de epochs. Dentro, ocurren varios pasos clave que vale la pena conocer.

  • Se captura el tiempo de inicio y fin para medir cuánto demoró todo el proceso.
  • Se guardan los mejores pesos, porque el modelo mejora epoch tras epoch y solo te interesa quedarte con el más fuerte.
  • Cada epoch tiene dos fases: entrenamiento (model.train()) y validación (model.eval()), lo que ayuda a gestionar mejor la memoria.
  • Se iteran las imágenes del epoch, se llevan los gradientes a cero y se calcula la loss.
  • En la fase de entrenamiento entra la etapa de optimización, donde el optimizador reduce los valores de la loss.
  • Se hace una deep copy del modelo cuando supera el mejor accuracy registrado.

El accuracy mide los aciertos del modelo: si la radiografía es de neumonía y el modelo predice neumonía, suma un acierto. Si predice normal, no cuenta. La métrica final es la cantidad de aciertos sobre el total de muestras.

¿Qué resultados obtienes al entrenar el modelo?

En la ejecución de la clase, el entrenamiento duró 6 minutos [06:30]. Epoch tras epoch, la loss fue disminuyendo y el accuracy creciendo, llegando a un máximo del 76%. En la industria, valores por encima del 70% se consideran un buen punto de partida para un clasificador médico básico.

Después del entrenamiento puedes usar una función de visualización que pasa imágenes del set de validación al modelo y muestra sus predicciones: neumonía, normal, neumonía, etc. Es la prueba visual de que el modelo aprendió a leer patrones en las radiografías.

Una vez entrenado, ya puedes guardarlo y empezar a hacer predicciones con tus propias imágenes. ¿Has entrenado modelos de clasificación de imágenes? Cuéntame qué accuracy lograste y qué optimizador usaste.