El Proceso de Entrenamiento de una Red Neuronal

El Proceso de Entrenamiento de una Red Neuronal
Introducción
El entrenamiento de una red neuronal es un ciclo de optimización cuyo objetivo es ajustar los parámetros del modelo (pesos y sesgos) para minimizar su error.
Este proceso se fundamenta en tres pilares matemáticos:
- 📉 Función de Costo
- ⬇️ Descenso de Gradiente
- 🔄 Retropropagación
1 La Función de Costo: Cuantificación del Error
La función de costo J(w,b) cuantifica cuán equivocadas están las predicciones del modelo.
Analogía
Como una balanza desequilibrada: el objetivo es ajustarla hasta alcanzar el equilibrio (error mínimo).
Fórmula General
1J(w,b) = (1/m) · Σ L(y⁽ⁱ⁾, a[L]⁽ⁱ⁾)
Componentes:
- m: Número total de ejemplos de entrenamiento
- L: Función de pérdida (un ejemplo)
- y⁽ⁱ⁾: Etiqueta verdadera
- a[L]⁽ⁱ⁾: Predicción del modelo
Error Cuadrático Medio (MSE)
1L(y, ŷ) = (y − ŷ)²
python1import numpy as np 2 3def costo_mse(y_true, y_pred): 4 m = len(y_true) 5 return (1/m) * np.sum((y_true - y_pred)**2) 6 7# Ejemplo 8y_true = np.array([1, 0, 1, 1, 0]) 9y_pred = np.array([0.9, 0.1, 0.8, 0.7, 0.2]) 10print(f"Costo: {costo_mse(y_true, y_pred):.4f}")
Objetivo: Encontrar W y b que minimicen J(w,b).
2 Descenso del Gradiente: El Algoritmo de Optimización
El Descenso de Gradiente Estocástico (SGD) es el algoritmo más utilizado para minimizar la función de costo.
Analogía: Descenso de una Montaña
Imagina que estás en una montaña con niebla densa. Para bajar:
- Sientes la pendiente del terreno
- Das un paso en la dirección más inclinada hacia abajo
- Repites hasta llegar al valle
Matemáticamente: Moverse en la dirección opuesta al gradiente.
Variante Moderna: Mini-Batch Gradient Descent
Actualiza parámetros usando un pequeño lote de muestras:
- Más eficiente que procesar todo el dataset
- Más estable que usar un solo ejemplo
Pasos del Algoritmo
python1# Pseudocódigo 2def entrenar_red(X, y, epochs, learning_rate): 3 # 1. Inicialización 4 W, b = inicializar_parametros_aleatorios() 5 6 for epoch in range(epochs): 7 for batch in crear_mini_batches(X, y): 8 # 2. Cálculo del gradiente 9 gradientes = calcular_gradientes(batch, W, b) 10 11 # 3. Actualización de parámetros 12 W = W - learning_rate * gradientes['dW'] 13 b = b - learning_rate * gradientes['db'] 14 15 return W, b
Ecuaciones de Actualización
1w⁽ⁱ⁺¹⁾ = w⁽ⁱ⁾ − α · (∂J/∂w) 2b⁽ⁱ⁺¹⁾ = b⁽ⁱ⁾ − α · (∂J/∂b)
α = tasa de aprendizaje (learning rate)
- Muy pequeña → Convergencia lenta
- Muy grande → Puede no converger
python1# Ejemplo de actualización 2W_nuevo = W_actual - 0.01 * gradiente_W 3b_nuevo = b_actual - 0.01 * gradiente_b
3 Retropropagación: Cálculo Eficiente de Gradientes
La backpropagation calcula los gradientes aplicando la regla de la cadena del cálculo diferencial.
Concepto Clave: El Error δ[l]
1δ[l] = (∂J/∂a[l]) ⊙ σ'(z[l])
- ⊙: Producto de Hadamard (elemento a elemento)
- σ'(z[l]): Derivada de la función de activación
Algoritmo de Backpropagation
python1def backpropagation(X, y, cache): 2 m = X.shape[1] 3 L = len(cache) # Número de capas 4 5 # 1. Calcular error en la capa de salida 6 delta_L = cache['A_L'] - y 7 8 # 2. Propagar hacia atrás 9 gradientes = {} 10 for l in reversed(range(1, L+1)): 11 # Gradientes de pesos y sesgos 12 gradientes[f'dW{l}'] = (1/m) * np.dot(delta, cache[f'A{l-1}'].T) 13 gradientes[f'db{l}'] = (1/m) * np.sum(delta, axis=1, keepdims=True) 14 15 # Error de la capa anterior 16 if l > 1: 17 delta = np.dot(cache[f'W{l}'].T, delta) * sigmoid_derivative(cache[f'Z{l-1}']) 18 19 return gradientes
Derivada de la Sigmoide
python1def sigmoid_derivative(z): 2 s = sigmoid(z) 3 return s * (1 - s)
Propagación hacia Atrás - Paso a Paso
1Capa de Salida (L) ─────────────────┐ 2 ↑ │ 3 │ Calcular δ[L] │ 4 │ │ 5Capa Oculta 2 ──────────────────────┤ 6 ↑ │ 7 │ δ[L-1] = W[L]ᵀ·δ[L] ⊙ σ' │ Backprop 8 │ │ 9Capa Oculta 1 ──────────────────────┤ 10 ↑ │ 11 │ δ[L-2] = W[L-1]ᵀ·δ[L-1] │ 12 │ │ 13Capa de Entrada ────────────────────┘
Cálculo de Gradientes Finales
Para los pesos:
1∂J/∂W[l] = δ[l] · a[l−1]ᵀ
Para los sesgos:
1∂J/∂b[l] = δ[l]
El Ciclo Completo de Aprendizaje
python1def ciclo_entrenamiento(X, y, arquitectura, epochs, alpha): 2 # Inicializar parámetros 3 parametros = inicializar_red(arquitectura) 4 5 for epoch in range(epochs): 6 # 1. FORWARD PROPAGATION 7 cache = forward_propagation(X, parametros) 8 9 # 2. CALCULAR COSTO 10 costo = calcular_costo(cache['A_L'], y) 11 12 # 3. BACKWARD PROPAGATION 13 gradientes = backpropagation(X, y, cache) 14 15 # 4. ACTUALIZAR PARÁMETROS 16 parametros = actualizar_parametros(parametros, gradientes, alpha) 17 18 if epoch % 100 == 0: 19 print(f"Epoch {epoch}: Costo = {costo:.4f}") 20 21 return parametros
Visualización del Proceso
1┌─────────────────────────────────────────────────────┐ 2│ CICLO DE ENTRENAMIENTO │ 3├─────────────────────────────────────────────────────┤ 4│ │ 5│ 1. Forward Pass │ 6│ X → Z1 → A1 → Z2 → A2 → ... → Ŷ │ 7│ │ 8│ 2. Calcular Pérdida │ 9│ L = (Y - Ŷ)² │ 10│ │ 11│ 3. Backward Pass │ 12│ ∂L/∂Ŷ → ∂L/∂W[L] → ... → ∂L/∂W[1] │ 13│ │ 14│ 4. Actualizar Parámetros │ 15│ W = W - α·∂L/∂W │ 16│ │ 17│ 5. Repetir hasta convergencia │ 18│ │ 19└─────────────────────────────────────────────────────┘
Consejos Prácticos
Elegir la Tasa de Aprendizaje
python1# Prueba diferentes valores 2learning_rates = [0.001, 0.01, 0.1, 1.0] 3 4for lr in learning_rates: 5 modelo = entrenar(X, y, learning_rate=lr) 6 print(f"LR={lr}: Costo Final={modelo.costo:.4f}")
Monitorear el Entrenamiento
python1import matplotlib.pyplot as plt 2 3def plot_training(historial_costos): 4 plt.plot(historial_costos) 5 plt.xlabel('Época') 6 plt.ylabel('Costo') 7 plt.title('Evolución del Costo durante el Entrenamiento') 8 plt.show()
Referencias
- Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep learning. MIT Press.
- Mazur, M. (2015). A Step by Step Backpropagation Example.
- Ng, A. (2017). Neural Networks and Deep Learning. Coursera.
Anterior: ← Fundamentos del Deep Learning
Próximo: Aplicación Práctica con Keras →