La arquitectura que revolucionó la visión por computadora. En vez de conectar todo con todo, las CNNs deslizan pequeños filtros sobre la imagen para detectar patrones — bordes, texturas, formas.
Una imagen de 200×200 en color tiene 120.000 valores. Una capa Linear conectándolos a
1.000 neuronas necesitaría 120 millones de pesos — solo en la primera capa.
Inviable, y además ignora que los píxeles cercanos están relacionados.
Un filtro (también llamado kernel) es una cuadrícula pequeña de números, por ejemplo 3×3 (3 filas y 3 columnas). Se coloca sobre un trozo de la imagen, se multiplican los números uno por uno y se suman — eso produce un único número que mide cuánto "encaja" ese patrón en ese trozo. Un filtro aprende a detectar un patrón específico (un borde, una textura).
Las imágenes en PyTorch tienen canales: una imagen en escala de grises tiene 1 canal (solo brillo), una en color tiene 3 canales (rojo, verde, azul). La forma es (lote, canales, alto, ancho):
# imagen ficticia: lote=1, 1 canal (gris), 8x8 píxeles
img = torch.randn(1, 1, 8, 8)
conv = nn.Conv2d(in_channels=1, out_channels=4, kernel_size=3)
out = conv(img)
print(out.shape)
Fórmula del tamaño de salida de una convolución: salida = (entrada − kernel + 2·padding) / stride + 1 Con entrada=8, kernel=3, padding=0, stride=1: (8 − 3 + 2·0) / 1 + 1 = 5 + 1 = 6 Se aplica igual al alto y al ancho → 6×6. Y son 4 canales porque pusimos out_channels=4 (4 filtros). ✓
padding).
nn.MaxPool2d reduce el tamaño tomando el máximo de cada región. Resume y hace la red
más eficiente y robusta a pequeños desplazamientos:
pool = nn.MaxPool2d(2) # toma el máximo de cada bloque 2x2
print(pool(out).shape)
MaxPool2d(2) divide alto y ancho entre 2:
6 / 2 = 3 (toma el máximo de cada bloque 2×2)
Los 4 canales NO cambian (el pooling actúa dentro de cada canal).
El alto y ancho se reducen a la mitad (6→3). Los 4 canales se mantienen.
Bloques de [Conv → ReLU → Pool] que extraen patrones cada vez más complejos, y al final capas Linear para clasificar:
cnn = nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2), # bloque 1
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2), # bloque 2
nn.Flatten(), # aplanar tensor 3D a vector 1D
nn.Linear(32*7*7, 10), # 32*7*7=1568: 32 filtros × 7×7 píxeles (ver nota)
)
¿De dónde sale 32*7*7? Si la imagen de entrada es 28×28 (como el dataset MNIST de dígitos escritos a mano): bloque 1 con MaxPool2d(2) → 28/2=14. Bloque 2 con MaxPool2d(2) → 14/2=7. Con 32 filtros → 32×7×7=1568 valores que Flatten convierte a un vector para Linear.
Linear, no CNNs. Pero conocer las CNNs es esencial en tu caja de herramientas de
PyTorch — son el tema de visión por computadora.
Conv2d (filtros/kernels que se deslizan por la imagen detectando patrones locales) y MaxPool2d (reducir tamaño tomando el máximo de cada región). Apilados en bloques [Conv→ReLU→Pool] y terminando en capas Linear para clasificar. Mucho menos parámetros que conectar todo con todo.
En la próxima lección: transfer learning — reusar redes ya entrenadas en lugar de empezar de cero.