LECCIÓN 11 · AVANZADO

Regularización

Las herramientas de PyTorch para combatir el overfitting que estudiaste en teoría. Dropout, weight decay y BatchNorm: cada una "limita" al modelo para que generalice mejor.

Recuerda de las lecciones anteriores: en el curso de redes neuronales viste que el overfitting ocurre cuando la red memoriza el ruido en lugar de la tendencia general. Hoy las herramientas concretas de PyTorch para combatirlo.

1. El problema

Un modelo con demasiada capacidad memoriza el ruido de los datos de entrenamiento y falla con datos nuevos. La regularización son técnicas que limitan esa memorización. Veamos las tres más usadas, con su efecto real.

2. Dropout: apagar neuronas al azar

Durante el entrenamiento, nn.Dropout(p) pone a cero cada neurona con probabilidad p (un número entre 0 y 1: p=0.5 significa 50% de posibilidades, como lanzar una moneda por cada neurona). Así la red no puede depender de ninguna neurona concreta y aprende representaciones más robustas:

drop = nn.Dropout(p=0.5)
x = torch.ones(8)

drop.train()        # en entrenamiento: apaga ~50%
print(drop(x))

drop.eval()         # en evaluación: NO apaga nada
print(drop(x))
salida realtrain: tensor([2., 2., 2., 2., 0., 2., 2., 0.]) eval : tensor([1., 1., 1., 1., 1., 1., 1., 1.])
Fíjate en dos cosas: (1) en train() apagó 2 de 8 neuronas (las puso a 0), y (2) las que quedaron valen 2 en vez de 1 — las multiplica por 2 para compensar. ¿Por qué? Si la mitad de neuronas está apagada, la suma total bajaría a la mitad. Para que la siguiente capa reciba la misma magnitud de siempre, las encendidas se escalan automáticamente. En eval() no apaga nada (usa toda la red). Por esto importa net.train()/net.eval() que vimos en la lección 9.

3. Weight decay (regularización L2): penalizar pesos grandes

Pesos grandes = curvas muy "retorcidas" que sobreajustan. El weight decay añade una penalización por pesos grandes, empujándolos hacia cero (curvas más suaves). En PyTorch es solo un argumento del optimizador:

opt = torch.optim.Adam(net.parameters(),
                       lr=0.01,
                       weight_decay=1e-4)   ← regularización L2 (1e-4 = 0.0001)
salida realoptimizador con weight_decay=1e-4 creado OK

No hay que cambiar nada más: el optimizador aplica la penalización en cada step(). Valores típicos: 1e-4 (0.0001) a 1e-2 (0.01).

4. BatchNorm: normalizar las activaciones

nn.BatchNorm1d normaliza la salida de una capa por cada lote — transforma los valores para que tengan media ≈ 0 (centrados alrededor del cero) y desviación ≈ 1 (la desviación es una medida de qué tan dispersos están los valores: si todos son casi iguales es pequeña, si están muy esparcidos es grande). Estabiliza y acelera el entrenamiento, y tiene un efecto regularizador. Veámoslo:

bn = nn.BatchNorm1d(3)
x = torch.tensor([[1.,2.,3.],
                  [4.,5.,6.],
                  [7.,8.,9.]])
out = bn(x)
salida realmedia por columna ANTES: tensor([4., 5., 6.]) media por columna DESPUÉS: tensor([0., 0., 0.]) std por columna DESPUÉS: tensor([1., 1., 1.])
✍️ A mano, columna 0 = [1, 4, 7] (fórmula: (x − media) / desviación)
1) media:        (1 + 4 + 7) / 3 = 12 / 3 = 4
2) varianza:     [(1-4)² + (4-4)² + (7-4)²] / 3
               = [ 9   +   0   +   9  ] / 3 = 18/3 = 6
3) desviación:   √6 = 2.4495
4) normalizar cada valor:
     (1 − 4) / 2.4495 = -1.2247
     (4 − 4) / 2.4495 = 0.0000
     (7 − 4) / 2.4495 = +1.2247
   → nueva media = 0, nueva desviación = 1  ✓ (las otras columnas, igual)

Cada columna (cada "feature") sale con media 0 y desviación 1, sin importar la escala que tuviera a la entrada. Eso evita que unas features dominen a otras y suaviza el paisaje de la pérdida.

5. ¿Cómo se combinan en una red?

net = nn.Sequential(
    nn.Linear(10, 64),
    nn.BatchNorm1d(64),    # normaliza
    nn.ReLU(),
    nn.Dropout(0.3),       # apaga 30%
    nn.Linear(64, 1),
)
Orden estándar en una capa: Linear → BatchNorm → activación (ReLU) → Dropout.

6. Lo que aprendiste

Lo que aprendiste hoy: tres herramientas contra el overfitting. Dropout (p=0.5 apaga ~50% de neuronas al azar durante entrenamiento, sin apagar nada en eval). Weight decay (parámetro del optimizador, valores típicos 1e-4=0.0001 a 1e-2=0.01, penaliza pesos grandes). BatchNorm (normaliza cada lote: media≈0, desviación≈1). Úsalas juntas para mejor generalización.

En la próxima lección: las CNNs — arquitectura especializada para imágenes.