LECCIÓN 6 · CONSTRUIR Y ENTRENAR

Activaciones y funciones de pérdida

Dos piezas que ya conoces del curso de redes, ahora en su versión PyTorch: las activaciones (la chispa no-lineal) y las pérdidas (cómo se mide el error). Saber elegir la pérdida correcta es media batalla.

Recuerda de la lección anterior: nn.Linear crea una capa con pesos y bias. nn.Module agrupa capas en un modelo. Usas net(x) para predecir y net.parameters() para el optimizador. Hoy añadimos los dos ingredientes que faltaban: activaciones (no-linealidad) y funciones de pérdida (medir el error).

1. Activaciones

PyTorch las ofrece como funciones (torch.relu) o como capas (nn.ReLU()). Apliquémoslas a un mismo vector para ver su efecto:

z = torch.tensor([-2.0, -0.5, 0.0, 0.5, 2.0])
torch.relu(z)
torch.sigmoid(z)
torch.tanh(z)
salida realrelu : tensor([0.0000, 0.0000, 0.0000, 0.5000, 2.0000]) sigm : tensor([0.1192, 0.3775, 0.5000, 0.6225, 0.8808]) tanh : tensor([-0.9640, -0.4621, 0.0000, 0.4621, 0.9640])
Regla práctica: ReLU en capas ocultas; en la salida depende de la tarea. Para multiclase se usa softmax — una función que convierte varios números en probabilidades que suman 1 (p.ej. [0.7, 0.2, 0.1] para tres clases). En la práctica, la función de pérdida CrossEntropy lo aplica internamente, así que no tienes que añadirlo tú.

2. MSELoss — para regresión (predecir un número)

Error cuadrático medio: el promedio de (predicción − objetivo)².

pred   = torch.tensor([2.5, 0.0, 2.0])
target = torch.tensor([3.0, -0.5, 2.0])
loss_fn = nn.MSELoss()
loss_fn(pred, target)
salida realMSE: 0.16667
✍️ A mano: pred=[2.5, 0.0, 2.0], target=[3.0, -0.5, 2.0]
1) error de cada elemento (pred − target):
     2.5 − 3.0  = -0.5
     0.0 − (-0.5) = 0.5
     2.0 − 2.0  = 0.0
2) elevar cada error al cuadrado:
     (-0.5)² = 0.25
     ( 0.5)² = 0.25
     ( 0.0)² = 0.00
3) promediar (sumar y dividir entre 3):
     (0.25 + 0.25 + 0.00) / 3 = 0.50 / 3 = 0.16667

Úsala cuando la salida es un valor continuo (precio, temperatura… nuestro proyecto tabular).

3. CrossEntropyLoss — para clasificación (elegir una clase)

La pérdida estrella en clasificación. Recibe los logits — los números crudos que salen de la última capa, antes de convertirlos en probabilidades (pueden ser negativos, mayores que 1, cualquier valor) — y el índice de la clase correcta (0, 1, 2…). Castiga mucho estar seguro y equivocado:

logits = torch.tensor([[2.0, 0.5, 0.1]])   # puntajes para 3 clases
ce = nn.CrossEntropyLoss()

ce(logits, torch.tensor([0]))   # clase correcta = 0 (la de mayor logit)
ce(logits, torch.tensor([2]))   # clase correcta = 2 (la de menor logit)
salida realclase correcta = 0 (acierta) → 0.3168 clase correcta = 2 (falla) → 2.2168
✍️ A mano: qué hace CrossEntropy por dentro (softmax + −log)
Logits = [2.0, 0.5, 0.1]

PASO 1 — softmax (convierte logits en probabilidades):
   a) exponenciar cada logit:
        e^2.0 = 7.389056
        e^0.5 = 1.648721
        e^0.1 = 1.105171
   b) sumar:  7.389056 + 1.648721 + 1.105171 = 10.142948
   c) dividir cada uno entre la suma:
        p₀ = 7.389056 / 10.142948 = 0.728492
        p₁ = 1.648721 / 10.142948 = 0.162549
        p₂ = 1.105171 / 10.142948 = 0.108960

PASO 2 — tomar −ln de la probabilidad de la clase correcta:
   clase 0:  −ln(0.728492) = 0.3168    ✓  (prob alta → pérdida baja)
   clase 2:  −ln(0.108960) = 2.2168    ✓  (prob baja → pérdida alta)
🔑 Dos sorpresas importantes de CrossEntropyLoss:
1. Le pasas los logits crudos, NO les apliques softmax tú — la pérdida lo hace por dentro (hacerlo dos veces es un bug clásico).
2. El objetivo es el índice de la clase (0, 1, 2…), no un "vector one-hot" (un vector con un 1 en la posición de la clase y ceros en el resto, como [0,0,1] para la clase 2 — CrossEntropyLoss no quiere eso, solo quiere el número 2).

Fíjate cómo cuando el modelo "apuesta" por la clase correcta la pérdida es baja (0.32), y cuando apuesta fuerte por la equivocada se dispara (2.22).

4. Lo que aprendiste

TareaSalida de la redPérdida
Regresión (un número)1 neurona, sin activaciónnn.MSELoss
Clasificación binaria1 neurona + sigmoidnn.BCELoss
Clasificación multiclaseN neuronas (logits)nn.CrossEntropyLoss
Lo que aprendiste hoy: las activaciones (ReLU en capas ocultas, sigmoid o softmax en la salida) dan el poder no-lineal. Las pérdidas miden el error: MSELoss para regresión, CrossEntropyLoss para clasificación (pásale logits crudos e índice de clase, no vector one-hot). Ya tienes modelo + pérdida.

Falta quién ajuste los pesos: el optimizador, y el bucle de entrenamiento — la próxima lección.