13

El big bang del deep learning

¿Por qué funcionó en 2012 lo que no funcionaba en 1990?

10 min

El big bang del deep learning

Con voz. Puedes pausar y saltar a cualquier paso.

Lección completa

Subtítulos

La retropropagación se publicó en 1986 y las redes convolucionales leían códigos postales en 1989. Pero el despegue del deep learning, las redes de muchas capas, llegó en 2012. ¿Qué cambió?

Voz

Sin voz: la lección avanza sola con subtítulos.

La voz de esta lección está en preparación: por ahora avanza sola con subtítulos.

0:00 / 0:00

Qué lograrás

  • Explicar por qué el deep learning despegó hacia 2012: datos masivos, cómputo con GPUs y unos trucos de entrenamiento.
  • Predecir cuándo una GPU supera a una CPU al multiplicar matrices y por qué su ventaja crece con el tamaño del problema.
  • Explicar qué hace una conexión residual con el gradiente y por qué permite apilar muchas más capas.

Ideas clave

  1. El despegue del deep learning no vino de una idea nueva, sino de tres ingredientes que coincidieron: datos masivos, cómputo y trucos de entrenamiento.
  2. ImageNet puso millones de fotos etiquetadas al alcance de todos, y el concurso ILSVRC midió el progreso con una vara común: el error top-5.
  3. Una GPU multiplica matrices con miles de núcleos a la vez, justo el trabajo del entrenamiento; su ventaja crece con el tamaño del problema.
  4. AlexNet (2012) bajó el error top-5 del segundo lugar, 26.2 %, a 15.3 % con ReLU, dropout y dos GPU; la memoria de la GPU ya limitaba el tamaño de la red.
  5. Una conexión residual, y = x + F(x), da al gradiente un camino directo y permitió redes de más de cien capas; el cómputo de los mayores entrenamientos se duplicó cada pocos meses.

Lo que mucha gente cree

Creencia común El deep learning despegó en 2012 porque por fin alguien inventó una idea revolucionaria.

Lo correcto La retropropagación y las convoluciones ya existían desde los años ochenta y noventa, e incluso entrenar en GPU se había probado antes. Lo que cambió fue la escala: millones de imágenes etiquetadas, GPUs y unos pocos trucos (ReLU, dropout, atajos residuales).

Compruébalo

Cuatro preguntas. Sin nota ni cuenta: sirven para ver si la idea quedó.

Concepto¿Por qué una GPU encaja tan bien con el entrenamiento de redes neuronales?
CálculoSi cada capa reduce el gradiente a la mitad al retropropagarlo, ¿qué fracción del gradiente de la salida llega diez capas hacia atrás?
ConceptoEn un bloque residual, la salida es y = x + F(x). ¿Qué ventaja da ese «+ x» al retropropagar?
AplicaciónUn proveedor presume un error de 3.6 % en ImageNet y propone usar su modelo de visión para inspeccionar piezas de tu fábrica. ¿Qué haces primero?

Por dentroPara quien quiere las fórmulas y el código. No hace falta para seguir el curso.

Los números de 2012

Del artículo de AlexNet (Krizhevsky, Sutskever y Hinton, 2012): ocho capas con pesos (cinco convolucionales y tres densas), unos 60 millones de parámetros, unas 650 000 neuronas, más de 1.2 millones de imágenes de entrenamiento y entre cinco y seis días en dos GPU GTX 580 de 3 GB. La entrada tiene 150 528 valores (224×224×3224\times224\times3). Dos detalles del mismo artículo: en su figura 1, una red de cuatro capas en CIFAR-10 llegó a 25 % de error de entrenamiento seis veces más rápido con ReLU que con tanh (los autores aclaran que el efecto varía con la arquitectura), y el dropout, con probabilidad 0.5 en las dos primeras capas densas, se usó porque sin él la red sufría un sobreajuste considerable, a costa de duplicar más o menos las iteraciones necesarias.

Modelo en ILSVRC 2012 Error top-5
SIFT + vectores de Fisher (segundo lugar) 26.2 %
1 red convolucional (validación) 18.2 %
5 redes promediadas 16.4 %
7 redes, 2 de ellas preentrenadas con 15 M de imágenes 15.3 %

Por eso la cifra «15.3 %» viene de un conjunto de siete redes y de datos extra; con solo los datos del concurso fueron 16.4 %. Aun así, la diferencia con el segundo lugar es enorme.

Multiplicar matrices: por qué gana la GPU

El producto C=ABC=AB de dos matrices n×nn\times n es

Cij=∑k=1nAikBkj.C_{ij}=\sum_{k=1}^{n}A_{ik}B_{kj}.

Son n2n^2 celdas independientes y cada una cuesta nn multiplicaciones-suma: n3n^3 en total, es decir, 2n32n^3 operaciones de coma flotante (FLOP: una suma o una multiplicación con decimales). Con PP núcleos que hacen una multiplicación-suma por paso, el número ideal de pasos es

T(n,P)=⌈n2P⌉n,T(n,8)T(n,P)  ⟶  P8 cuando n2≫P.T(n,P)=\left\lceil \frac{n^2}{P}\right\rceil n,\qquad \frac{T(n,8)}{T(n,P)}\;\longrightarrow\;\frac{P}{8}\ \text{cuando }n^2\gg P.

Con P=512P=512 (GTX 580) la ventaja ideal tope es 64; con P=3584P=3584 (RTX 3060), 448. Es un conteo ideal: ignora el ancho de banda de memoria, el costo de mover datos a la GPU y que cada núcleo de GPU es más lento que uno de CPU. Las medidas reales de Raina, Madhavan y Ng (2009), con una GPU GTX 280 contra una CPU de dos núcleos, fueron entre 12.9 y 72.6 veces según el tamaño del modelo.

La velocidad pico de un chip es nuˊcleos×2×reloj\text{núcleos}\times 2\times\text{reloj}: 512×2×1.544 GHz≈1.58512\times2\times1.544\ \text{GHz}\approx1.58 TFLOP/s para la GTX 580 (cifra que usa OpenAI) y, por la misma cuenta, unos 12.7 TFLOP/s para la RTX 3060.

El costo de entrenar AlexNet

Según la estimación de Amodei y Hernandez (OpenAI, 2018), el pase hacia delante cuesta unos 0.75×1090.75\times10^{9} multiplicaciones-suma por imagen; entrenar incluye 2 operaciones por multiplicación-suma, el paso hacia atrás (factor 3) y unas 90 vueltas al conjunto:

1.2×106⋅90⋅0.75×109⋅2⋅3≈4.9×1017 FLOP.1.2\times10^{6}\cdot 90\cdot 0.75\times10^{9}\cdot 2\cdot 3\approx 4.9\times10^{17}\ \text{FLOP}.

Es coherente con dos GTX 580 durante 5.5 días al 33 % de su pico, que es lo que supone OpenAI: 2⋅1.58×1012⋅5.5⋅86 400⋅0.33≈5×10172\cdot1.58\times10^{12}\cdot5.5\cdot86\,400\cdot0.33\approx5\times10^{17}. Desde 2012 (de AlexNet a AlphaGo Zero, a finales de 2017), OpenAI midió que el cómputo de los mayores entrenamientos se duplicaba cada 3.4 meses; estimaciones posteriores (Sevilla et al., 2022) dan alrededor de 6 meses para la era del deep learning. En ambos casos, el crecimiento es exponencial.

El gradiente a través de las capas

En una pila simple, hl=tanh⁡(Wlhl−1)h_l=\tanh(W_l h_{l-1}) y el gradiente retrocede como

∂L∂hl−1=Wl⊤(tanh⁡′(zl)⊙∂L∂hl),\frac{\partial L}{\partial h_{l-1}}=W_l^{\top}\Big(\tanh'(z_l)\odot\frac{\partial L}{\partial h_l}\Big),

así que su norma se multiplica por un factor, cada capa, de aproximadamente σ⋅tanh⁡′‾\sigma\cdot\overline{\tanh'}. Con la inicialización «estándar» de la época, n Var[W]=1/3n\,\mathrm{Var}[W]=1/3 (Glorot y Bengio, 2010, ec. 15), el factor queda alrededor de 0.5; en el juguete de la lección sale ≈ 0.55 y 0.5540≈4×10−110.55^{40}\approx 4\times10^{-11}.

Con atajo, xl+1=xl+F(xl)x_{l+1}=x_l+F(x_l) y, según He et al. (2016, ec. 5),

∂E∂xl=∂E∂xL(I+∂∂xl∑i=lL−1F(xi)).\frac{\partial E}{\partial x_l}=\frac{\partial E}{\partial x_L}\Big(I+\frac{\partial}{\partial x_l}\sum_{i=l}^{L-1}F(x_i)\Big).

El término II lleva el gradiente de la salida a cualquier capa sin pasar por ningún peso. En el juguete, además, cada bloque suma su aporte y la norma crece un poco (entre 2 y 18 con 40 capas, según la semilla).

Lo que el juguete no dice

La red del juguete no está entrenada, no usa normalización y todas sus capas son iguales. En redes reales, la inicialización y la normalización por lotes mantienen sanas las señales. De hecho, He et al. (2015, §4.1 y figura 1) argumentan que la dificultad de entrenar redes simples profundas no parece deberse a gradientes que se desvanecen: sus redes simples tenían gradientes de norma sana y, aun así, la de 34 capas tenía más error de entrenamiento que la de 18, y la de 56 más que la de 20 en CIFAR-10. Lo llamaron el problema de la degradación. Su hipótesis es que es más fácil que un bloque aprenda F≈0F\approx0 (identidad) que ajustar una identidad con capas no lineales; los propios autores dejan esa explicación como pregunta abierta. Lo medido es claro: con atajos, las redes de 50, 101 y 152 capas mejoraron con la profundidad. La ResNet-152 (11.3 mil millones de multiplicaciones-suma) cuesta menos que una VGG-19 (19.6 mil millones); sola logró 4.49 % de error top-5 en validación, y un conjunto de seis modelos, 3.57 % en prueba.

En código

import numpy as np

def grad_norms(depth, residual, width=16, seed=0):
    rng = np.random.default_rng(seed)
    W = rng.normal(0, np.sqrt(1/3) / np.sqrt(width), size=(depth, width, width))
    h = rng.normal(size=width)
    cache = []
    for l in range(depth):                        # pase hacia delante
        t = np.tanh(W[l] @ h)
        cache.append(t)
        h = h + t if residual else t
    g = np.ones(width) / np.sqrt(width)           # gradiente de norma 1 en la salida
    norms = [np.linalg.norm(g)]
    for l in reversed(range(depth)):              # retropropagación
        branch = W[l].T @ (g * (1 - cache[l] ** 2))
        g = g + branch if residual else branch    # con atajo, el gradiente pasa intacto y se suma la rama
        norms.append(np.linalg.norm(g))
    return norms                                  # norms[k]: norma tras k capas hacia atrás

for res in (False, True):
    n = grad_norms(40, res)
    print("con atajos" if res else "sin atajos", f"tras 10 capas: {n[10]:.2e}   tras 40: {n[40]:.2e}")
# sin atajos tras 10 capas: 5.30e-03   tras 40: 1.16e-10
# con atajos tras 10 capas: 2.51e+00   tras 40: 1.48e+01

Los números exactos dependen de la semilla y del generador aleatorio (el archivo gradients.py de la lección también comprueba la retropropagación contra diferencias finitas); el orden de magnitud no. Y el conteo ideal de la carrera:

from math import ceil

def pasos(n, nucleos):          # n² celdas independientes; cada una cuesta n multiplicaciones-suma
    return ceil(n * n / nucleos) * n

print(pasos(64, 8), pasos(64, 512), pasos(64, 3584))   # CPU de 8 núcleos, GTX 580, RTX 3060
# 32768 512 128

Lo que viene

Las conexiones residuales y la normalización reaparecen en cada bloque del transformer (lección 22). La lección 14 pasa de ver a representar significado con embeddings. Las cuentas de FLOPs, datos y costo se formalizan en la lección 24, y la memoria de la GPU, que ya limitaba a AlexNet, manda en la lección 25.

Lente de decisión

Qué significa esta idea si tu trabajo es decidir, no programar.

  • Cuando alguien diga «nuestro modelo es mejor», pregunta qué cambió: más datos (¿de quién y con qué licencia?), más cómputo (¿cuántas horas de GPU y a qué costo?) o un mejor método. Son los tres motores del progreso moderno.
  • Un resultado en un benchmark público describe una tarea concreta, no la tuya: un error de 3.57 % en ImageNet no dice cuánto fallará con tus fotos. Pide una prueba con tus propios datos y con el costo real de cada tipo de error.
  • El cómputo es una partida de presupuesto y de acceso: GPUs que se compran o se alquilan por hora, con memoria limitada. Entrenar desde cero un modelo grande está fuera del alcance de casi todas las organizaciones; lo habitual es partir de uno ya preentrenado.
  • Más profundo o más grande no es automáticamente mejor: sin las ideas adecuadas (normalización, atajos), una red profunda ni siquiera entrena bien. Pide resultados con datos no vistos, no solo el número de parámetros o de capas.

Términos de la lección

Transcripción completa
ComentariosConversación pública de esta lección: dudas, datos por revisar, ideas.

Los comentarios viven en GitHub Discussions, en el repositorio público del curso; para escribir se necesita una cuenta de GitHub. Se cargan desde giscus.app al abrir esta sección. Las personas que revisan el curso los leen, y si un cambio se acepta, se aplica en los dos idiomas. Abrir el hilo en GitHub

Fuentes