18. Evaluación del modelo

18.1 Introducción

En el tema anterior vimos cómo entrenar un modelo en PyTorch. Aprendimos a preparar datos, definir una función de pérdida, usar un optimizador y repetir el ciclo de entrenamiento durante varias épocas.

Pero entrenar un modelo no alcanza. Después de entrenarlo necesitamos responder una pregunta fundamental:

¿Qué tan bien funciona realmente el modelo?

Responder esa pregunta es precisamente el objetivo de la evaluación del modelo. En este tema veremos cómo medir el desempeño de una red neuronal y cómo evitar conclusiones engañosas.

18.2 Qué significa evaluar un modelo

Evaluar un modelo significa analizar qué tan bien realiza la tarea para la cual fue entrenado.

Esto implica observar su comportamiento sobre datos y medir sus resultados con criterios objetivos.

Por ejemplo, podríamos querer saber:

  • Qué tan cerca están sus predicciones de los valores reales.
  • Cuántos casos clasifica correctamente.
  • Si generaliza bien a datos nuevos.
  • Si está aprendiendo de verdad o simplemente memorizando.

Evaluar no es “mirar si parece funcionar”, sino medirlo de una manera razonable.

18.3 Por qué no alcanza con mirar la pérdida de entrenamiento

Durante el entrenamiento es común observar la pérdida para ver si baja. Eso es útil, pero no basta para saber si el modelo realmente funciona bien.

Un modelo puede tener una pérdida baja sobre los datos con los que fue entrenado y, sin embargo, comportarse mal sobre datos nuevos.

Esto ocurre porque el entrenamiento y la evaluación no persiguen exactamente lo mismo:

  • El entrenamiento busca ajustar parámetros.
  • La evaluación busca medir desempeño.

Por eso, mirar solo el error de entrenamiento puede llevar a conclusiones equivocadas.

18.4 Generalización: la idea central

Uno de los conceptos más importantes en evaluación es la generalización.

Decimos que un modelo generaliza bien cuando no solo funciona con los datos que vio durante el entrenamiento, sino también con datos nuevos que no conocía.

Ese es el verdadero objetivo de la mayoría de los modelos de Machine Learning y Deep Learning: no memorizar, sino aprender patrones útiles.

18.5 Conjuntos de entrenamiento, validación y prueba

Para evaluar correctamente un modelo, normalmente no usamos un único conjunto de datos para todo.

Lo habitual es dividir los datos en tres grupos:

  • Entrenamiento: datos usados para ajustar parámetros.
  • Validación: datos usados para controlar el desempeño mientras se entrena.
  • Prueba: datos reservados para la evaluación final.

Esta separación ayuda a medir mejor qué tan bien generaliza el modelo.

18.6 El conjunto de entrenamiento

El conjunto de entrenamiento es el que usamos para enseñar al modelo. Allí ocurre el ciclo de forward, pérdida, backward y actualización de parámetros.

Como el modelo ve estos datos repetidamente, no sirve usar solo este conjunto para juzgar su calidad final.

Es parecido a practicar siempre con las mismas preguntas y luego asumir que ya dominamos todo el tema: puede ser una impresión engañosa.

18.7 El conjunto de validación

El conjunto de validación sirve para observar cómo se comporta el modelo mientras aprende, pero sobre datos que no está usando directamente para ajustar parámetros en ese momento.

Esto permite detectar problemas como:

  • Overfitting.
  • Falta de capacidad del modelo.
  • Elección inadecuada de hiperparámetros.

En muchos proyectos reales, el conjunto de validación cumple un papel muy importante para tomar decisiones durante el desarrollo.

18.8 El conjunto de prueba

El conjunto de prueba se reserva para el final. Su función es ofrecer una medición más imparcial del rendimiento del modelo ya entrenado y ajustado.

La idea es que estos datos permanezcan “intactos” hasta el momento de la evaluación final.

Si usamos constantemente el conjunto de prueba para tomar decisiones, deja de ser una referencia confiable.

18.9 Diferencia entre entrenamiento y evaluación en PyTorch

En PyTorch, entrenar y evaluar no son exactamente el mismo proceso. Cuando entrenamos, el modelo puede comportarse de una manera distinta que cuando solo queremos medir su desempeño.

Por eso existen dos modos importantes:

  • model.train() para entrenamiento.
  • model.eval() para evaluación.

Esta diferencia se vuelve especialmente importante en modelos que usan capas como Dropout o Batch Normalization.

18.10 El uso de model.eval()

Antes de evaluar un modelo, en general conviene ponerlo en modo evaluación:

modelo.eval()

Esto le indica a PyTorch que el modelo ya no está en fase de entrenamiento y que debe comportarse de forma adecuada para medir resultados.

En redes simples quizás no se note demasiado la diferencia, pero es una práctica correcta y necesaria en muchos casos reales.

18.11 El uso de torch.no_grad()

Durante la evaluación normalmente no necesitamos calcular gradientes, porque no vamos a actualizar parámetros.

Por eso, PyTorch ofrece un contexto especial:

with torch.no_grad():
    prediccion = modelo(X)

Esto hace la evaluación más eficiente y evita trabajo innecesario del sistema de autograd.

En otras palabras, cuando solo queremos medir, no tiene sentido preparar cálculos para aprender.

18.12 Un ejemplo básico de evaluación

Supongamos que ya tenemos un modelo entrenado y queremos evaluar su comportamiento sobre un conjunto de datos.

modelo.eval()
with torch.no_grad():
    predicciones = modelo(X)

Esto genera las salidas del modelo sin calcular gradientes y en modo evaluación.

Con esas predicciones ya podemos compararlas contra las salidas reales y calcular métricas.

18.13 Qué son las métricas

Las métricas son valores que resumen el desempeño del modelo.

No existe una única métrica universal. La elección depende del tipo de problema.

Por ejemplo:

  • En regresión suele interesar el error.
  • En clasificación suele interesar la cantidad de aciertos.
  • En algunos casos interesan medidas más específicas, como precisión o recall.

Lo importante es que una métrica debe ayudarnos a interpretar de forma objetiva cómo funciona el modelo.

18.14 Evaluación en problemas de regresión

Si el modelo predice valores continuos, estamos en un problema de regresión.

En estos casos es frecuente usar métricas basadas en el error entre la predicción y el valor real.

Algunas opciones comunes son:

  • Error cuadrático medio (MSE).
  • Raíz del error cuadrático medio (RMSE).
  • Error absoluto medio (MAE).

La idea general es simple: cuanto menor sea el error, mejor estará funcionando el modelo.

18.15 Usar la pérdida como medida en regresión

En ejemplos sencillos de regresión, a veces la misma función de pérdida que usamos para entrenar también puede servir como referencia para evaluar.

criterio = nn.MSELoss()
modelo.eval()
with torch.no_grad():
    pred = modelo(X)
    error = criterio(pred, y)
    print(error.item())

Aquí estamos obteniendo una medición numérica del desempeño del modelo sobre ese conjunto de datos.

18.16 Evaluación en clasificación

En problemas de clasificación, en cambio, muchas veces lo más intuitivo es saber cuántos ejemplos fueron clasificados correctamente.

Allí aparece una métrica muy conocida: la accuracy o exactitud.

La accuracy indica la proporción de predicciones correctas sobre el total de casos evaluados.

18.17 La idea de accuracy

Supongamos que evaluamos 100 ejemplos y el modelo acierta 87.

Entonces la accuracy sería:

87 / 100 = 0.87

Es decir, un 87% de aciertos.

Esta métrica es muy útil porque resulta fácil de entender, aunque no siempre alcanza por sí sola para describir bien el desempeño.

18.18 De salida numérica a clase predicha

En clasificación, el modelo muchas veces produce puntajes o probabilidades. Para calcular accuracy, normalmente necesitamos convertir esa salida en una clase concreta.

Por ejemplo, en clasificación binaria podríamos usar un umbral. En clasificación multiclase, podríamos elegir la clase con valor más alto.

La idea central es que la evaluación de clasificación suele requerir un paso adicional para traducir la salida del modelo en una decisión.

18.19 Ejemplo conceptual de accuracy

Imaginemos que las etiquetas reales son:

reales = [1, 0, 1, 1, 0]

y el modelo predice:

predichas = [1, 0, 0, 1, 0]

Comparando ambas listas, vemos que acertó 4 de 5 casos.

La accuracy sería entonces 0.8, es decir, 80%.

18.20 Más allá de accuracy

Aunque accuracy es útil, no siempre es suficiente. En algunos problemas puede dar una impresión engañosa.

Por ejemplo, si una clase aparece muchísimo más que otra, un modelo podría acertar mucho simplemente prediciendo siempre la clase más frecuente.

Por eso en algunos casos también se usan métricas como:

  • Precisión.
  • Recall.
  • F1-score.

Más adelante, cuando trabajemos más con clasificación, estas métricas cobrarán mayor importancia.

18.21 Pérdida de validación y pérdida de entrenamiento

Una práctica muy útil consiste en comparar la pérdida sobre entrenamiento con la pérdida sobre validación.

Si ambas bajan, eso suele ser una buena señal. Pero si la pérdida de entrenamiento baja mientras la de validación empeora, puede indicar overfitting.

Este tipo de observación es muy valiosa porque nos permite detectar cuándo el modelo empieza a aprender demasiado los detalles del conjunto de entrenamiento.

18.22 Qué es overfitting desde la evaluación

El overfitting ocurre cuando el modelo se adapta demasiado a los datos de entrenamiento y pierde capacidad de generalizar.

Desde el punto de vista de la evaluación, suele verse así:

  • Muy buen rendimiento en entrenamiento.
  • Peor rendimiento en validación o prueba.

Esto muestra por qué la evaluación con datos separados es tan importante.

18.23 Qué es underfitting

El caso opuesto es el underfitting. Aquí el modelo ni siquiera logra aprender bien sobre el conjunto de entrenamiento.

En evaluación, esto suele verse como un rendimiento pobre tanto en entrenamiento como en validación.

Puede deberse a un modelo demasiado simple, pocas épocas de entrenamiento o una mala configuración de hiperparámetros.

18.24 Evaluar no significa seguir actualizando

Un error conceptual frecuente es pensar que evaluar forma parte del entrenamiento en el mismo sentido que actualizar parámetros.

Durante la evaluación no queremos que el modelo aprenda, sino que muestre qué tan bien aprendió hasta ese momento.

Por eso usamos model.eval() y torch.no_grad(): queremos medir, no entrenar.

18.25 Un esquema básico de evaluación

Un flujo simple de evaluación en PyTorch podría resumirse así:

  1. Poner el modelo en modo evaluación.
  2. Desactivar gradientes.
  3. Hacer predicciones.
  4. Compararlas con los valores reales.
  5. Calcular una o más métricas.

Este esquema se adapta tanto a regresión como a clasificación, con diferencias en la métrica y en la interpretación de la salida.

18.26 Ejemplo simple de evaluación en regresión

Supongamos que ya entrenamos un modelo de regresión. La evaluación podría escribirse así:

modelo.eval()
with torch.no_grad():
    pred = modelo(X)
    error = criterio(pred, y)
    print("Error:", error.item())

Este ejemplo ya muestra los elementos esenciales de una evaluación básica.

18.27 Comparar predicciones y valores reales

Además de usar métricas agregadas, muchas veces conviene mirar directamente algunas predicciones junto con sus valores reales.

Por ejemplo, podríamos imprimir pares como estos:

real: 8.0 - predicho: 7.9
real: 10.0 - predicho: 10.3

Esto ayuda a desarrollar intuición sobre el comportamiento del modelo y detectar errores groseros que una sola métrica podría ocultar.

18.28 Evaluación cualitativa y cuantitativa

La evaluación puede verse desde dos ángulos complementarios:

  • Cuantitativa: usando métricas numéricas.
  • Cualitativa: observando ejemplos concretos y su sentido práctico.

Las métricas son imprescindibles, pero también es valioso mirar resultados reales y preguntarse si tienen sentido.

18.29 Errores comunes al evaluar un modelo

Algunos errores frecuentes son:

  • Evaluar usando los mismos datos del entrenamiento como única referencia.
  • Olvidar llamar a model.eval().
  • Olvidar usar torch.no_grad().
  • Elegir una métrica que no corresponde al problema.
  • Interpretar una sola métrica como si dijera todo sobre el modelo.

Evitar estos errores hace que la evaluación sea mucho más confiable.

18.30 Buenas prácticas para estudiantes

Si estás comenzando, estas recomendaciones suelen ayudar mucho:

  • Separar claramente entrenamiento y evaluación.
  • Usar siempre algún conjunto de datos no visto durante el entrenamiento.
  • Elegir una métrica adecuada al tipo de problema.
  • Observar tanto métricas agregadas como ejemplos concretos.
  • No sacar conclusiones apresuradas solo por un único número.

Estas prácticas te ayudarán a interpretar mejor el comportamiento real del modelo.

18.31 Un resumen del proceso de evaluación

Podemos resumir la evaluación de un modelo así:

  1. Se reserva un conjunto de datos para medir desempeño.
  2. Se pone el modelo en modo evaluación.
  3. Se desactivan gradientes con torch.no_grad().
  4. Se generan predicciones.
  5. Se comparan con los valores reales.
  6. Se calculan métricas adecuadas al problema.
  7. Se interpretan los resultados en términos de generalización.

Este proceso es esencial para saber si el modelo realmente sirve para la tarea planteada.

18.32 Código completo para ejecutar

Para poder probar todo el flujo sin tener que reconstruirlo por partes, aquí tienes un ejemplo completo y ejecutable. En este caso separamos explícitamente datos de entrenamiento y datos de prueba.

import torch
import torch.nn as nn
import torch.optim as optim

torch.manual_seed(0)

X_train = torch.tensor([[1.0], [2.0], [3.0], [4.0]])
y_train = torch.tensor([[2.0], [4.0], [6.0], [8.0]])

X_test = torch.tensor([[5.0], [6.0]])
y_test = torch.tensor([[10.0], [12.0]])

class ModeloSimple(nn.Module):
    def __init__(self):
        super().__init__()
        self.lineal = nn.Linear(1, 1)

    def forward(self, x):
        return self.lineal(x)

modelo = ModeloSimple()
criterio = nn.MSELoss()
optimizador = optim.SGD(modelo.parameters(), lr=0.01)

for epoca in range(1000):
    modelo.train()
    prediccion = modelo(X_train)
    perdida = criterio(prediccion, y_train)
    optimizador.zero_grad()
    perdida.backward()
    optimizador.step()

    if (epoca + 1) % 100 == 0:
        print(f"Epoca {epoca+1}, perdida: {perdida.item():.4f}")

modelo.eval()
with torch.no_grad():
    predicciones = modelo(X_test)
    error_final = criterio(predicciones, y_test)
    nuevo_dato = torch.tensor([[7.0]])
    prediccion_nueva = modelo(nuevo_dato)
    print("Error final en prueba:", error_final.item())
    print("Predicciones en prueba:")
    print(predicciones)
    print("Prediccion para un valor nuevo:")
    print(prediccion_nueva)

Este script permite ver en un solo bloque cómo se conectan entrenamiento, evaluación y predicción. Primero el modelo aprende con X_train e y_train, después se evalúa con X_test e y_test, y finalmente se usa para predecir un valor nuevo (7.0) que no pertenece ni al entrenamiento ni a la prueba.

18.33 Qué debes recordar de este tema

  • Evaluar un modelo significa medir su desempeño de manera objetiva.
  • No alcanza con mirar solo la pérdida de entrenamiento.
  • La evaluación debe hacerse idealmente con datos no usados directamente para entrenar.
  • model.eval() pone al modelo en modo evaluación.
  • torch.no_grad() evita calcular gradientes innecesarios.
  • Las métricas dependen del tipo de problema: regresión o clasificación.
  • La evaluación permite detectar overfitting, underfitting y problemas de generalización.
  • Una buena evaluación combina métricas numéricas con interpretación razonable de resultados.

18.34 Conclusión

La evaluación del modelo es una etapa indispensable en cualquier flujo serio de Deep Learning. Entrenar un modelo sin evaluarlo correctamente equivale a estudiar sin comprobar si realmente se aprendió.

Dominar esta etapa significa aprender a mirar el rendimiento de una red de forma crítica y objetiva, sin quedarse solo con la intuición o con una pérdida que baja durante el entrenamiento.

En el próximo tema daremos un paso más aplicado: veremos la clasificación con redes neuronales.