DL Specialization · C2W2
Curso 2 · Semana 2 · Improving Deep Neural Networks

Algoritmos de Optimización

Cómo entrenar redes neuronales mucho más rápido: descenso de gradiente por mini-lotes, promedios exponencialmente ponderados, Momentum, RMSprop, Adam, decaimiento de la tasa de aprendizaje y la verdadera geometría de los óptimos locales en alta dimensión.

Fuente · Andrew Ng — deeplearning.ai Nivel · Intermedio Módulos · 8 + código NumPy Quiz · 30 preguntas
Material audiovisual

Vídeos de la semana (canal oficial DeepLearningAI)

Los 10 vídeos de C2W2 publicados por deeplearning.ai en YouTube, en el orden del curso. Cada módulo incluye además la tarjeta de su vídeo (miniatura clicable) justo bajo el título de la sección: al pulsarla se abre el vídeo en YouTube.

Cómo estudiar: pulsa la tarjeta y ve el vídeo primero (10–15 min), luego trabaja el módulo de la guía con los cálculos a mano, y cierra con las preguntas del quiz de ese tema. Nota: en YouTube el último vídeo aparece rotulado como "C2W3L10" por un error del canal, pero corresponde a esta semana (The Problem of Local Optima).
Módulo 01

Descenso de gradiente por mini-lotes (Mini-batch Gradient Descent)

C2W2L01Mini Batch Gradient DescentAndrew Ng · deeplearning.ai · YouTube
C2W2L01Mini Batch Gradient Descent — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Entender por qué el descenso de gradiente por lotes (batch) es lento con datasets grandes.
  • Dominar la notación X{t}, Y{t} y distinguirla de x(i) y z[l].
  • Implementar una época (epoch) completa de mini-batch gradient descent.
  • Comprender por qué avanza aunque cada paso use solo una fracción de los datos.

1.1 El problema: la vectorización no basta

En el Curso 1 aprendimos que la vectorización permite procesar los m ejemplos de entrenamiento sin bucles explícitos: apilamos las columnas en X = [x⁽¹⁾ x⁽²⁾ … x⁽ᵐ⁾] de dimensión (nₓ, m) e Y de dimensión (1, m).

Pero ¿qué pasa si m = 5.000.000 de ejemplos? El descenso de gradiente clásico (batch gradient descent) debe procesar los 5 millones de ejemplos completos — forward y backward — antes de dar un solo paso de actualización. Es como si tuvieras que leer una biblioteca entera antes de poder corregir tu primera frase. El entrenamiento se vuelve extremadamente lento.

Idea clave: el mini-batch gradient descent permite empezar a progresar antes de haber procesado todo el conjunto de entrenamiento. Cada pequeño lote produce una actualización de los parámetros.

1.2 Construcción de los mini-lotes y notación

Dividimos el conjunto de entrenamiento en lotes más pequeños, por ejemplo de 1.000 ejemplos cada uno. Con m = 5.000.000 obtenemos 5.000 mini-lotes:

Partición en mini-lotes (tamaño 1000) X{1} = [x⁽¹⁾ … x⁽¹⁰⁰⁰⁾],   X{2} = [x⁽¹⁰⁰¹⁾ … x⁽²⁰⁰⁰⁾],   … ,   X{5000}

Lo mismo para las etiquetas: Y{1}, Y{2}, …, Y{5000}. El mini-lote t es el par (X{t}, Y{t}), con X{t} de dimensión (nₓ, 1000) e Y{t} de dimensión (1, 1000).

NotaciónSignificadoEjemplo
x⁽ⁱ⁾ — paréntesisi-ésimo ejemplo de entrenamientox⁽¹⁰⁰⁰⁾
z[l] — corchetesvalor de la capa l de la redz[2]
X{t} — llavest-ésimo mini-loteX{5000}

1.3 El algoritmo: una época de entrenamiento

Una época (epoch) es una pasada completa por el conjunto de entrenamiento. Con batch GD, una época = 1 actualización. Con mini-batch GD y 5.000 mini-lotes, una época = 5.000 actualizaciones. Hagamos la contabilidad con números concretos para fijar la idea:

Escenario (m = 5.000.000, size = 1.000)CálculoPasos de gradiente
Batch GD — 1 época1 pasada = 1 update1
Mini-batch GD — 1 época5.000.000 / 1.0005.000
Batch GD — 10 épocas10 × 110
Mini-batch GD — 10 épocas10 × 5.00050.000

Con el mismo coste computacional (10 pasadas por los datos), mini-batch GD ha corregido los parámetros 50.000 veces mientras batch GD solo lo hizo 10. Por eso aprende tanto más rápido en la práctica. Dentro del bucle todo es idéntico al descenso de gradiente que ya conoces, pero aplicado a X{t}, Y{t}:

1

Propagación hacia delante sobre X{t}

Z[1] = W[1]·X{t} + b[1], A[1] = g[1](Z[1]), … hasta A[L]. Sigue vectorizado: procesa 1.000 ejemplos a la vez.

2

Calcular el coste del mini-lote

J{t} = (1/1000) Σ L(ŷ⁽ⁱ⁾, y⁽ⁱ⁾) + (λ/(2·1000)) Σ‖W[l]‖²_F — nota que se normaliza por el tamaño del mini-lote, no por m.

3

Retropropagación

Backprop para calcular dW[l], db[l] usando únicamente (X{t}, Y{t}).

4

Actualizar parámetros

W[l] := W[l] − α·dW[l],   b[l] := b[l] − α·db[l]. ¡Un paso de gradiente con solo 1.000 ejemplos!

pseudocódigo — una época de mini-batch GD
for t in range(1, 5001):          # 5000 mini-lotes
    # Forward prop sobre X{t}  (vectorizado, 1000 ejemplos)
    Z1 = W1 @ X_t + b1
    A1 = g(Z1)
    ...
    AL = g(ZL)
    # Coste del mini-lote
    J_t = (1/1000) * sum(L(AL, Y_t)) + reg
    # Backprop y actualización
    dW, db = backprop(X_t, Y_t, cache)
    W = W - alpha * dW
    b = b - alpha * db

1.4 Ejemplo numérico completo: un paso de mini-batch a mano

Para ver exactamente qué ocurre en los pasos 1–4, tomemos un micro-ejemplo totalmente calculable: una regresión logística (red de 1 capa, activación sigmoide) con nₓ = 2 características y un mini-lote de 4 ejemplos. Los mecanismos son idénticos a los de un mini-lote de 1.000 — solo cambia el número de columnas.

Datos del mini-lote t y parámetros actuales X{t} = ⎡ 1   2   0  −1 ⎤
⎣ 0   1   3    2 ⎦
(2×4)   ·   Y{t} = [1  1  0  0] (1×4)

W = [0.5  −0.5] (1×2)   ·   b = 0   ·   α = 0.1
1

Forward: Z = W·X{t} + b, luego A = σ(Z)

Cada columna de Z es el producto de W por la columna correspondiente de X{t} — los 4 ejemplos se procesan a la vez (vectorización):
z⁽¹⁾ = 0.5·1 + (−0.5)·0 = 0.5  ·  z⁽²⁾ = 0.5·2 + (−0.5)·1 = 0.5  ·  z⁽³⁾ = 0.5·0 + (−0.5)·3 = −1.5  ·  z⁽⁴⁾ = 0.5·(−1) + (−0.5)·2 = −1.5
Aplicando σ(z) = 1/(1+e⁻ᶻ): σ(0.5) = 0.6225, σ(−1.5) = 0.1824 ⇒ A = [0.6225  0.6225  0.1824  0.1824]. Las predicciones ya "apuntan" bien: altas donde y=1, bajas donde y=0, pero aún lejos de 1 y 0.

2

Coste del mini-lote: J{t} = −(1/4) Σ [y·ln(a) + (1−y)·ln(1−a)]

Pérdida por ejemplo:
ej. 1 y 2 (y=1): −ln(0.6225) = 0.4741 cada uno  ·  ej. 3 y 4 (y=0): −ln(1−0.1824) = −ln(0.8176) = 0.2014 cada uno.
J{t} = (0.4741 + 0.4741 + 0.2014 + 0.2014) / 4 = 1.3510 / 4 = 0.3377. Nota el divisor: 4 (tamaño del mini-lote), no m.

3

Backprop: dZ = A − Y, luego dW = (1/4)·dZ·X{t}ᵀ, db = media(dZ)

dZ = [0.6225−1,  0.6225−1,  0.1824−0,  0.1824−0] = [−0.3775  −0.3775  0.1824  0.1824]
dw₁ = ¼·[(−0.3775)(1) + (−0.3775)(2) + (0.1824)(0) + (0.1824)(−1)] = ¼·(−1.3149) = −0.3287
dw₂ = ¼·[(−0.3775)(0) + (−0.3775)(1) + (0.1824)(3) + (0.1824)(2)] = ¼·(0.5345) = +0.1336
db = ¼·(−0.3775 − 0.3775 + 0.1824 + 0.1824) = ¼·(−0.3902) = −0.0976

4

Actualización: θ := θ − α·dθ

w₁ := 0.5 − 0.1·(−0.3287) = 0.5329 (sube: la característica 1 es alta cuando y=1, tiene sentido reforzarla)
w₂ := −0.5 − 0.1·(0.1336) = −0.5134 (baja: la característica 2 es alta cuando y=0)
b := 0 − 0.1·(−0.0976) = 0.0098
¡Un paso de gradiente completado usando solo este mini-lote! El bucle continúa con (X{t+1}, Y{t+1}) partiendo de estos parámetros ya mejorados — así se encadenan las 5.000 actualizaciones de una época.

Verificación — ¿de verdad mejoró? Recalculando el coste sobre el mismo mini-lote con los parámetros nuevos: Z = [0.5427, 0.5622, −1.5304, −1.5499] ⇒ A = [0.6325, 0.6370, 0.1779, 0.1751] ⇒ J = 0.3244 < 0.3377. El paso redujo el coste, como debe ser (y con el matiz del módulo 2: sobre otro mini-lote J{t} podría subir puntualmente sin que nada vaya mal).
verificación en numpy — reproduce el ejemplo
import numpy as np
X_t = np.array([[1, 2, 0, -1], [0, 1, 3, 2]])   # (2, 4): 4 ejemplos en columnas
Y_t = np.array([[1, 1, 0, 0]])
W, b, alpha = np.array([[0.5, -0.5]]), 0.0, 0.1
mt = X_t.shape[1]                              # tamaño del mini-lote = 4

Z = W @ X_t + b                                # [[ 0.5  0.5 -1.5 -1.5]]
A = 1/(1 + np.exp(-Z))                        # [[0.6225 0.6225 0.1824 0.1824]]
J = -np.mean(Y_t*np.log(A) + (1-Y_t)*np.log(1-A))
print(J)                                       # 0.3377  ← paso 2 ✓

dZ = A - Y_t
dW = (dZ @ X_t.T)/mt                           # [[-0.3287  0.1336]] ← paso 3 ✓
db = np.mean(dZ)                               # -0.0976
W, b = W - alpha*dW, b - alpha*db              # [[0.5329 -0.5134]], 0.0098 ← paso 4 ✓

1.5 Detalles prácticos que caen en el examen

Resultado práctico: cuando el dataset es grande, el mini-batch gradient descent es mucho más rápido que el batch gradient descent. Prácticamente todo el deep learning moderno se entrena así.
Módulo 02

Entendiendo el mini-batch GD y la elección del tamaño

C2W2L02Understanding Mini-BatchGradient DescentAndrew Ng · deeplearning.ai · YouTube
C2W2L02Understanding Mini-Batch Gradient Descent — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Interpretar la curva de coste ruidosa del mini-batch GD.
  • Comparar los tres extremos: batch (size = m), estocástico (size = 1) y mini-batch.
  • Aplicar las reglas prácticas para elegir el tamaño del mini-lote (potencias de 2).

2.1 La curva de coste: suave vs. ruidosa

Con batch GD, el coste J debe disminuir en cada iteración; si alguna vez sube, algo está mal (p. ej., α demasiado grande). Con mini-batch GD, la curva de J{t} es ruidosa: baja en tendencia, pero oscila. Es normal, porque cada punto se calcula sobre un mini-lote distinto — algunos son "fáciles" (coste bajo) y otros contienen ejemplos difíciles o mal etiquetados (coste alto).

Batch gradient descent # iteraciones coste J Mini-batch gradient descent mini-lote # (t) coste J{t} tendencia ↓
fig 2.1 — Batch GD: descenso suave y monótono. Mini-batch GD: descenso ruidoso pero con tendencia decreciente; cada oscilación refleja la "dificultad" del mini-lote t.

2.2 Los dos extremos del tamaño del mini-lote

TamañoNombreVentajasInconvenientes
size = mBatch GDPasos de bajo ruido, convergencia estable hacia el mínimoDemasiado tiempo por iteración si m es grande
size = 1Estocástico (SGD)Progresa tras cada ejemploPierde toda la aceleración de la vectorización; extremadamente ruidoso, nunca converge — deambula alrededor del mínimo
1 < size < mMini-batchLo mejor de ambos: vectorización + progreso frecuenteIntroduce el hiperparámetro "tamaño de mini-lote"; oscila cerca del mínimo (se mitiga con LR decay)
mínimo batch (size=m): directo, poco ruido SGD (size=1): muy ruidoso, no converge mini-batch: ruido moderado, rápido
fig 2.2 — Trayectorias sobre los contornos del coste. SGD deambula sin converger; batch GD es estable pero caro; mini-batch avanza rápido con oscilación aceptable.

2.3 Reglas prácticas para elegir el tamaño

Consejo de Andrew Ng: el tamaño del mini-lote es un hiperparámetro más: prueba varias potencias de 2 y busca el que haga el descenso de gradiente más eficiente.

⚑ Claves para el examen

  • Notación: paréntesis (i) = ejemplo, corchetes [l] = capa, llaves {t} = mini-lote.
  • 1 época con 5.000 mini-lotes ⇒ 5.000 pasos de gradiente (batch GD daría solo 1).
  • J{t} ruidoso pero decreciente en tendencia = comportamiento normal del mini-batch GD.
  • size = m → batch GD; size = 1 → SGD (pierde vectorización y no converge).
  • m ≤ 2000 → batch GD; si no, 64–512 (potencias de 2) y que quepa en memoria.
Módulo 03

Promedios exponencialmente ponderados (EWA)

Objetivos de aprendizaje

  • Calcular vt = β·vt−1 + (1−β)·θt e interpretar cada término.
  • Relacionar β con la ventana efectiva de promedio ≈ 1/(1−β) días.
  • Entender por qué se llama "exponencial": los pesos decaen geométricamente.
  • Implementarlo en una sola línea con memoria O(1).

3.1 Motivación: la temperatura en Londres

Antes de Momentum, RMSprop y Adam necesitamos su ingrediente básico. Andrew Ng usa la temperatura diaria de Londres: θ₁ = 40°F, θ₂ = 49°F, θ₃ = 45°F, …, θ₁₈₀ = 60°F, θ₁₈₁ = 56°F… Los datos son ruidosos día a día, pero queremos ver la tendencia estacional. La solución es una media móvil que se actualiza así:

Promedio exponencialmente ponderado vt = β·vt−1 + (1 − β)·θt ,    v₀ = 0

Con β = 0.9: v₁ = 0.9·v₀ + 0.1·θ₁, v₂ = 0.9·v₁ + 0.1·θ₂, etc. Cada vt mezcla 90 % de historia con 10 % de dato nuevo. El resultado (línea roja) sigue la tendencia suavizada de las temperaturas.

3.2 Interpretación de β: la ventana de promedio

Ventana efectiva vt ≈ promedio sobre   1 / (1 − β)   días
β1/(1−β)Comportamiento de la curva
0.9≈ 10 díasLínea roja — equilibrio típico: suaviza el ruido y sigue la tendencia.
0.98≈ 50 díasLínea verde — mucho más suave, pero desplazada a la derecha: se adapta con retraso (latencia) porque da poco peso (0.02) al dato actual.
0.5≈ 2 díasLínea amarilla — muy ruidosa, reacciona rapidísimo a los cambios pero apenas filtra outliers.
días temperatura — β=0.90 (≈10 días) — β=0.98 (≈50 días, retrasada) — β=0.50 (≈2 días, ruidosa)
fig 3.1 — Temperatura diaria (puntos azules) y tres EWA. Mayor β ⇒ curva más suave pero con más latencia; menor β ⇒ reacción rápida pero ruidosa.

3.3 ¿Por qué "exponencial"? Expandiendo la recurrencia

Expandamos v₁₀₀ con β = 0.9:

v₁₀₀ = 0.1·θ₁₀₀ + 0.1·(0.9)·θ₉₉ + 0.1·(0.9)²·θ₉₈ + 0.1·(0.9)³·θ₉₇ + …

Cada día anterior recibe un peso multiplicado por 0.9 adicional: los pesos forman una exponencial decreciente. Es un promedio ponderado donde el pasado se "olvida" geométricamente. Además, la suma de todos los coeficientes es ≈ 1 (salvo el sesgo inicial que veremos en el módulo 4).

¿De dónde sale 1/(1−β)? Se usa la aproximación (1−ε)^(1/ε) ≈ 1/e ≈ 0.35 con ε = 1−β. Con β = 0.9: 0.9¹⁰ ≈ 0.35 — tras ~10 días el peso ha caído a ~1/e (≈ un tercio) del inicial, así que "contribuyen significativamente" los últimos ~10 días. Con β = 0.98: 0.98⁵⁰ ≈ 1/e ⇒ ventana ≈ 50 días.

3.4 Implementación: una línea, memoria O(1)

La gran ventaja frente a una media móvil clásica de ventana k (que exige guardar los últimos k valores): el EWA solo necesita una variable que se sobrescribe. Por eso se usa masivamente en machine learning.

implementación del EWA
v_theta = 0                          # inicialización
for t in range(1, T+1):
    theta_t = obtener_dato(t)        # p.ej. temperatura del día t
    v_theta = beta * v_theta + (1 - beta) * theta_t
    # v_theta ≈ promedio de los últimos 1/(1-beta) valores

⚑ Claves para el examen

  • Fórmula central: vt = β·vt−1 + (1−β)·θt.
  • Ventana efectiva ≈ 1/(1−β): β=0.9→10, β=0.98→50, β=0.5→2.
  • ↑β ⇒ más suave + más latencia (se desplaza a la derecha); ↓β ⇒ más ruido + más reactivo.
  • Los pesos decaen exponencialmente; (1−ε)^(1/ε) ≈ 1/e justifica la regla 1/(1−β).
  • Ventaja computacional: 1 línea de código y memoria O(1).
Módulo 04

Corrección de sesgo (Bias Correction)

C2W2L05Bias Correction ofExponentially Weighted AveragesAndrew Ng · deeplearning.ai · YouTube
C2W2L05Bias Correction of Exponentially Weighted Averages — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Identificar por qué el EWA arranca con valores demasiado bajos (v₀ = 0).
  • Aplicar la corrección vt / (1 − βᵗ) y verificarla numéricamente.
  • Saber cuándo importa (Adam, fase inicial) y cuándo se ignora en la práctica.

4.1 El problema: el arranque frío

Como inicializamos v₀ = 0, los primeros valores del EWA quedan sesgados hacia abajo. Con β = 0.98 y θ₁ = 40°F: v₁ = 0.98·0 + 0.02·40 = 0.8 — ¡una pésima estimación de 40! Y v₂ = 0.98·v₁ + 0.02·θ₂ = 0.0196·θ₁ + 0.02·θ₂: los coeficientes suman solo 0.0396, muy lejos de 1. En la gráfica, la curva arranca pegada al suelo (curva morada) en vez de seguir los datos (curva verde).

días fase inicial sesgada — con corrección: vₜ/(1−βᵗ) — sin corrección (v₀=0)
fig 4.1 — Con β=0.98, la curva sin corregir (morada) arranca casi en cero; la corrección (verde) elimina el sesgo. Para t grande, βᵗ→0 y ambas curvas coinciden.

4.2 La solución: dividir por (1 − βᵗ)

Estimación corregida vtcorr = vt / (1 − βᵗ)

Verificación numérica (t = 2, β = 0.98): 1 − β² = 1 − 0.9604 = 0.0396. Entonces v₂/0.0396 = (0.0196·θ₁ + 0.02·θ₂)/0.0396 — los coeficientes ahora suman exactamente 1: se convierte en un promedio ponderado legítimo de θ₁ y θ₂, eliminando el sesgo.

Para t grande, βᵗ → 0, así que 1 − βᵗ → 1 y la corrección deja de tener efecto: solo actúa durante el arranque, que es exactamente donde hace falta.

En la práctica: muchos practicantes no aplican la corrección al usar EWA solo (prefieren "aguantar" el arranque). Pero Adam sí la incorpora de serie para v y para s — es una de sus señas de identidad.

⚑ Claves para el examen

  • Origen del sesgo: v₀ = 0 ⇒ primeras estimaciones demasiado pequeñas.
  • Corrección: dividir por (1 − βᵗ); con t=2 y β=0.98 el divisor es 0.0396.
  • La corrección solo importa al principio; para t grande es ≈ 1.
  • Adam aplica bias correction; Momentum/RMSprop suelen omitirla.
Módulo 05

Descenso de gradiente con Momentum

C2W2L06Gradient Descent With MomentumAndrew Ng · deeplearning.ai · YouTube
C2W2L06Gradient Descent With Momentum — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Explicar cómo el EWA de los gradientes amortigua las oscilaciones.
  • Escribir las ecuaciones de actualización con vdW, vdb.
  • Usar la analogía física (bola, velocidad, fricción) y el valor por defecto β = 0.9.

5.1 El problema: oscilaciones que frenan el aprendizaje

Imagina un coste con contornos elípticos alargados (muy común: distintas escalas entre parámetros). El descenso de gradiente oscila arriba-abajo en la dirección corta (vertical, digamos b) mientras avanza lentamente en la dirección larga (horizontal, digamos W). Esas oscilaciones:

— GD estándar: oscila (limita α) — con Momentum: oscilaciones amortiguadas W → ↑ b : las oscilaciones verticales se cancelan al promediar
fig 5.1 — Los gradientes verticales alternan de signo ⇒ su promedio ≈ 0; los horizontales apuntan siempre al mínimo ⇒ su promedio se refuerza. Momentum acelera la dirección útil.

5.2 El algoritmo

Idea: en lugar de actualizar con el gradiente crudo, actualizamos con su promedio exponencialmente ponderado. En la iteración t (sobre el mini-lote actual):

Momentum — actualización vdW = β·vdW + (1−β)·dW   |   vdb = β·vdb + (1−β)·db

W := W − α·vdW   |   b := b − α·vdb

Por qué funciona: en la dirección vertical los gradientes alternan signo (+, −, +, −…) y el promedio tiende a cero — la oscilación se amortigua. En la dirección horizontal todos apuntan al mínimo y el promedio se mantiene grande — el avance se acelera. Resultado: trayectoria más directa y posibilidad de usar α mayor.

5.3 Analogía física y detalles de implementación

La bola que rueda: imagina el coste como un cuenco. dW/db actúan como la aceleración, vdW/vdb como la velocidad acumulada, y β (<1) como la fricción que evita que la bola acelere sin límite. La bola gana "momento" cuesta abajo — de ahí el nombre.

momentum — numpy
v_dW = np.zeros_like(W); v_db = np.zeros_like(b)
for t in range(num_iteraciones):
    dW, db = backprop_minibatch(X_t, Y_t)   # gradientes del mini-lote actual
    v_dW = beta * v_dW + (1 - beta) * dW
    v_db = beta * v_db + (1 - beta) * db
    W -= alpha * v_dW
    b -= alpha * v_db                        # beta = 0.9 funciona muy bien

⚑ Claves para el examen

  • Momentum = EWA aplicado a los gradientes: v = β·v + (1−β)·dθ; θ := θ − α·v.
  • Amortigua oscilaciones verticales (promedian a 0) y acelera la dirección consistente.
  • Permite usar una tasa de aprendizaje α mayor sin divergir.
  • β = 0.9 es el valor por defecto; bias correction rara vez se usa en Momentum.
  • Analogía: dW = aceleración, v = velocidad, β = fricción.
Módulo 06

RMSprop (Root Mean Square propagation)

C2W2L07RMSPropAndrew Ng · deeplearning.ai · YouTube
C2W2L07RMSProp — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Entender el promedio de los cuadrados de los gradientes: SdW, Sdb.
  • Explicar la actualización adaptativa: dividir por √S frena las direcciones ruidosas.
  • Saber por qué se añade ε ≈ 10⁻⁸ al denominador.

6.1 La idea: frenar donde hay oscilación, acelerar donde no

Mismo escenario que Momentum: oscilamos en b (vertical) y avanzamos lento en W (horizontal). Observación clave: las derivadas son grandes en la dirección que oscila (db grande) y pequeñas en la que progresa (dW pequeña). RMSprop explota esto: mide el "tamaño típico" de cada componente del gradiente y divide por él.

RMSprop — en cada iteración t (mini-lote actual) SdW = β₂·SdW + (1−β₂)·dW²   |   Sdb = β₂·Sdb + (1−β₂)·db²

W := W − α · dW / (√SdW + ε)   |   b := b − α · db / (√Sdb + ε)

El cuadrado dW² es elemento a elemento (element-wise). Análisis del efecto:

— GD: db grande ⇒ zigzag vertical — RMSprop: ÷√S_db frena lo vertical, ÷√S_dW impulsa lo horizontal
fig 6.1 — RMSprop normaliza cada componente del gradiente por su magnitud típica (RMS): las direcciones con derivadas grandes se frenan; las de derivadas pequeñas avanzan más.

6.2 Detalles importantes

Error típico: confundir Momentum con RMSprop. Momentum promedia los gradientes (dW) y actualiza con v. RMSprop promedia los cuadrados (dW²) y actualiza con dW/√S. Son mecanismos distintos y complementarios.

⚑ Claves para el examen

  • SdW = β₂·SdW + (1−β₂)·dW² (cuadrado element-wise).
  • Actualización: W := W − α·dW/(√SdW + ε), con ε ≈ 10⁻⁸ por estabilidad numérica.
  • Derivada grande ⇒ divisor grande ⇒ paso pequeño (y viceversa): tasa efectiva adaptativa por parámetro.
  • Permite α mayor sin divergencia en la dirección oscilante.
Módulo 07

Adam: Momentum + RMSprop + corrección de sesgo

C2W2L08Adam Optimization AlgorithmAndrew Ng · deeplearning.ai · YouTube
C2W2L08Adam Optimization Algorithm — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Escribir el algoritmo Adam completo paso a paso.
  • Memorizar los hiperparámetros por defecto: β₁=0.9, β₂=0.999, ε=10⁻⁸.
  • Saber qué se ajusta (α) y qué casi nunca se toca (β₁, β₂, ε).

7.1 Por qué Adam

Muchos algoritmos de optimización propuestos en la literatura funcionaban bien solo en problemas concretos. Adam (Adaptive Moment Estimation) es de los pocos que demostró funcionar de forma robusta en una gran variedad de arquitecturas de deep learning, y por eso se convirtió en el estándar. Conceptualmente es simple: toma el v de Momentum, el S de RMSprop, corrige el sesgo de ambos y combina las dos actualizaciones.

7.2 El algoritmo completo

Inicializar vdW=0, SdW=0, vdb=0, Sdb=0. En la iteración t, calcular dW, db sobre el mini-lote actual y:

1

Primer momento (Momentum, β₁)

vdW = β₁·vdW + (1−β₁)·dW  ·  vdb = β₁·vdb + (1−β₁)·db

2

Segundo momento (RMSprop, β₂)

SdW = β₂·SdW + (1−β₂)·dW²  ·  Sdb = β₂·Sdb + (1−β₂)·db²

3

Corrección de sesgo (¡Adam sí la aplica!)

dW = vdW/(1−β₁ᵗ)  ·  ŜdW = SdW/(1−β₂ᵗ)   (igual para db)

4

Actualización combinada

W := W − α · v̂dW / (√ŜdW + ε)  ·  b := b − α · v̂db / (√Ŝdb + ε)

7.3 Elección de hiperparámetros

HiperparámetroValor recomendado¿Se ajusta?Rol
αSí, siempre — es el que hay que tunearTasa de aprendizaje
β₁0.9Casi nuncaEWA de dW (primer momento)
β₂0.999Casi nuncaEWA de dW² (segundo momento) — valor propuesto por los autores del paper de Adam
ε10⁻⁸No afecta apenasEstabilidad numérica del denominador
Nombre y curiosidad: Adam = Adaptive moment estimation. dW es el "primer momento" y dW² el "segundo momento" estadístico — de ahí el nombre. (Y no, no se llama así por Adam Coates, como bromea Andrew Ng en la clase.)
adam — numpy (una iteración)
t += 1
v_dW = beta1*v_dW + (1-beta1)*dW;   v_db = beta1*v_db + (1-beta1)*db
S_dW = beta2*S_dW + (1-beta2)*dW**2; S_db = beta2*S_db + (1-beta2)*db**2
# corrección de sesgo
v_dW_c = v_dW/(1-beta1**t);  v_db_c = v_db/(1-beta1**t)
S_dW_c = S_dW/(1-beta2**t);  S_db_c = S_db/(1-beta2**t)
# actualización
W -= alpha * v_dW_c/(np.sqrt(S_dW_c)+eps)
b -= alpha * v_db_c/(np.sqrt(S_db_c)+eps)   # eps = 1e-8

⚑ Claves para el examen

  • Adam = Momentum (v, β₁) + RMSprop (S, β₂) + corrección de sesgo en ambos.
  • Defaults sagrados: β₁ = 0.9, β₂ = 0.999, ε = 10⁻⁸; α sí se ajusta.
  • Actualización: θ := θ − α·v̂/(√Ŝ + ε).
  • Adam = Adaptive moment estimation; robusto en casi cualquier arquitectura.
Módulo 08

Decaimiento de la tasa de aprendizaje (Learning Rate Decay)

C2W2L09Learning Rate DecayAndrew Ng · deeplearning.ai · YouTube
C2W2L09Learning Rate Decay — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Justificar por qué reducir α con el tiempo ayuda al mini-batch GD a converger.
  • Aplicar la fórmula principal α = α₀ / (1 + decay_rate × epoch_num).
  • Conocer las variantes: exponencial, raíz, escalonada y manual.

8.1 La intuición

Con mini-lotes y α fijo, el ruido de cada lote hace que el algoritmo nunca converja del todo: acaba deambulando en una zona amplia alrededor del mínimo. Si en cambio α se reduce gradualmente, al principio das pasos grandes (aprendizaje rápido) y al final pasos diminutos que te dejan oscilando en una región muy estrecha junto al mínimo. Puedes "permitirte" pasos pequeños al final porque ya estás cerca.

8.2 Fórmula principal y ejemplo numérico

Decaimiento por época α = α₀ / (1 + decay_rate × epoch_num)

Recuerda: 1 época = 1 pasada por todos los datos. Ejemplo con α₀ = 0.2 y decay_rate = 1:

ÉpocaCálculoα
10.2 / (1+1·1)0.100
20.2 / (1+1·2)0.067
30.2 / (1+1·3)0.050
40.2 / (1+1·4)0.040

Tanto α₀ como decay_rate son hiperparámetros que se ajustan.

8.3 Otros métodos de decaimiento

Exponencial

α = 0.95^epoch · α₀ — decae rápidamente de forma multiplicativa.

Raíz

α = (k/√epoch)·α₀ o α = (k/√t)·α₀ con t = número de mini-lote.

Escalonada (discrete staircase)

α se reduce a la mitad cada cierto número de épocas — escalera descendente.

Manual

Si entrenas pocos modelos durante horas/días: observas y bajas α a mano. Sorprendentemente común.

pasos grandes al inicio → pasos pequeños cerca del mínimo α fijo: deambula sin converger
fig 8.1 — Con α fijo (rojo), el ruido de los mini-lotes mantiene al algoritmo dando vueltas lejos del mínimo. Con decay (verde), los pasos se encogen y quedan confinados a una región estrecha.
Prioridades de tuning: para Andrew Ng, el LR decay ayuda pero está por debajo en prioridad respecto a elegir bien un α fijo. Es uno más de los hiperparámetros a explorar (tema de la semana 3).

⚑ Claves para el examen

  • Motivo: con α fijo, el ruido del mini-batch impide converger; con decay, la oscilación final es diminuta.
  • Fórmula estrella: α = α₀/(1 + decay_rate·epoch); memoriza el ejemplo 0.2 → 0.1, 0.067, 0.05, 0.04.
  • Variantes: exponencial (0.95^epoch·α₀), k/√epoch, escalonada, manual.
  • α₀ y decay_rate son hiperparámetros.
Módulo 09

El problema de los óptimos locales… que no lo es tanto

C2W2L10The Problem of Local OptimaAndrew Ng · deeplearning.ai · YouTube
C2W2L10The Problem of Local Optima — Andrew Ng · deeplearning.aiVer en YouTube ↗

Objetivos de aprendizaje

  • Actualizar la intuición: en alta dimensión los puntos de gradiente cero suelen ser puntos de silla, no mínimos locales.
  • Entender por qué (argumento probabilístico 2⁻²⁰⁰⁰⁰).
  • Identificar el verdadero enemigo: los plateaus, y cómo ayudan Momentum/RMSprop/Adam.

9.1 La intuición antigua (y equivocada)

En los primeros tiempos del deep learning se temía que el descenso de gradiente quedara atrapado en mínimos locales malos — la imagen mental era un paisaje 2D lleno de valles. Pero esa intuición viene de dibujar J en 2-3 dimensiones, y no se traslada a redes con 20.000 o millones de parámetros.

9.2 Puntos de silla: el argumento probabilístico

Para que un punto de gradiente cero sea un mínimo local, la función debe curvarse hacia arriba (∪) en todas las direcciones. Con 20.000 dimensiones, si cada dirección se curva hacia arriba o hacia abajo con probabilidad ~½, la probabilidad de que todas sean ∪ es del orden de 2⁻²⁰⁰⁰⁰ — prácticamente imposible. Lo abrumadoramente probable es que unas direcciones curven hacia arriba y otras hacia abajo: un punto de silla (saddle point), llamado así porque la superficie recuerda a una silla de montar.

dirección w₁: curva ∪ (sube) dirección w₂: curva ∩ (baja) ∇J = 0 pero NO es mínimo = punto de silla (saddle point) P(mínimo local con n=20000 dim) ~ 2⁻²⁰⁰⁰⁰ ≈ 0
fig 9.1 — En un punto de silla el gradiente es cero, pero la función sube en unas direcciones y baja en otras. En alta dimensión, casi todos los puntos críticos son de este tipo.

9.3 El verdadero problema: los plateaus

Un plateau es una región extensa donde el gradiente es casi cero durante mucho tiempo. El algoritmo avanza lentísimo por la meseta hasta que por fin encuentra la pendiente y "cae" por el lado. Conclusiones de Andrew Ng:

⚑ Claves para el examen

  • En alta dimensión, un punto con ∇J = 0 es casi siempre un punto de silla, no un mínimo local (prob. ~2⁻ⁿ).
  • "Unlikely to get stuck in a bad local optima" — cita literal de la diapositiva.
  • El problema real son los plateaus (gradiente ≈ 0 durante mucho tiempo) porque hacen lento el aprendizaje.
  • Adam/RMSprop/Momentum aceleran la travesía de los plateaus.
Laboratorio

Implementación completa en NumPy: comparando los optimizadores

Este script autocontenido implementa mini-batch GD, Momentum, RMSprop y Adam sobre una regresión logística simple, para que compares las curvas de coste tú mismo (ideal para Google Colab):

optimizadores.py — comparación práctica
import numpy as np

def crear_minibatches(X, Y, batch_size=64, seed=0):
    """Baraja y particiona (X, Y) en mini-lotes X{t}, Y{t}."""
    rng = np.random.default_rng(seed)
    m = X.shape[1]
    perm = rng.permutation(m)                 # barajar es esencial
    X_s, Y_s = X[:, perm], Y[:, perm]
    lotes = []
    for k in range(0, m, batch_size):
        lotes.append((X_s[:, k:k+batch_size], Y_s[:, k:k+batch_size]))
    return lotes                               # el último puede ser más pequeño

def gradientes(W, b, X_t, Y_t):
    """Forward + backward de regresión logística sobre el mini-lote."""
    mt = X_t.shape[1]
    Z = W @ X_t + b
    A = 1/(1 + np.exp(-Z))
    coste = -np.mean(Y_t*np.log(A+1e-12) + (1-Y_t)*np.log(1-A+1e-12))
    dZ = A - Y_t
    return (dZ @ X_t.T)/mt, np.mean(dZ), coste

def entrenar(X, Y, metodo="adam", alpha=0.05, epocas=30,
             beta1=0.9, beta2=0.999, eps=1e-8, decay=0.0):
    nx = X.shape[0]
    W = np.zeros((1, nx)); b = 0.0
    vW = np.zeros_like(W); vb = 0.0       # momentum
    SW = np.zeros_like(W); Sb = 0.0       # rmsprop
    t, historial = 0, []
    for ep in range(1, epocas+1):
        a = alpha/(1 + decay*ep)             # learning rate decay
        for X_t, Y_t in crear_minibatches(X, Y, 64, seed=ep):
            t += 1
            dW, db, J = gradientes(W, b, X_t, Y_t)
            if metodo == "gd":
                W -= a*dW; b -= a*db
            elif metodo == "momentum":
                vW = beta1*vW + (1-beta1)*dW; vb = beta1*vb + (1-beta1)*db
                W -= a*vW; b -= a*vb
            elif metodo == "rmsprop":
                SW = beta2*SW + (1-beta2)*dW**2; Sb = beta2*Sb + (1-beta2)*db**2
                W -= a*dW/(np.sqrt(SW)+eps); b -= a*db/(np.sqrt(Sb)+eps)
            elif metodo == "adam":
                vW = beta1*vW + (1-beta1)*dW;    vb = beta1*vb + (1-beta1)*db
                SW = beta2*SW + (1-beta2)*dW**2; Sb = beta2*Sb + (1-beta2)*db**2
                vWc, vbc = vW/(1-beta1**t), vb/(1-beta1**t)   # bias correction
                SWc, Sbc = SW/(1-beta2**t), Sb/(1-beta2**t)
                W -= a*vWc/(np.sqrt(SWc)+eps); b -= a*vbc/(np.sqrt(Sbc)+eps)
            historial.append(J)
    return W, b, historial

# --- demo: dataset sintético ---
rng = np.random.default_rng(42)
X = rng.normal(size=(2, 4000))
Y = (X[0:1] + 2*X[1:2] > 0).astype(float)
for m in ["gd", "momentum", "rmsprop", "adam"]:
    _, _, h = entrenar(X, Y, metodo=m)
    print(f"{m:>9}: coste final = {np.mean(h[-20:]):.4f}")
Experimento sugerido: grafica historial con matplotlib para los cuatro métodos y observa: (1) la curva ruidosa característica del mini-batch, (2) cómo Adam converge más rápido, (3) el efecto de decay=0.5 sobre la oscilación final.
Autoevaluación

Quiz — 30 preguntas

Responde cada pregunta. Verde = correcta, rojo = incorrecta (se muestra la explicación). Tu puntuación aparece al final.