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.
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.
Durante el entrenamiento, nn.Dropout(p) pone a cero cada neurona con probabilidad
p. 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))
train() apagó 2 de 8 neuronas (las puso a 0), y (2) las
que quedaron valen 2 en vez de 1 — las escala para compensar las apagadas. En
eval() no apaga nada (usa toda la red). Por esto importa
net.train()/net.eval() que vimos en la lección 9.
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
No hay que cambiar nada más: el optimizador aplica la penalización en cada step(). Valores típicos: 1e-4 a 1e-2.
nn.BatchNorm1d normaliza la salida de una capa (media ≈ 0, desviación ≈ 1) por cada
lote. 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)
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.
net = nn.Sequential(
nn.Linear(10, 64),
nn.BatchNorm1d(64), # normaliza
nn.ReLU(),
nn.Dropout(0.3), # apaga 30%
nn.Linear(64, 1),
)
Dropout apaga neuronas al azar (robustez);
weight_decay penaliza pesos grandes (curvas suaves); BatchNorm normaliza
activaciones (estabilidad). Las tres reducen el overfitting de formas distintas y suelen usarse
juntas. En la próxima lección vemos una arquitectura especializada: las CNNs para
imágenes.