27  Retropropagación

La retropropagación es un método para calcular el gradiente necesario para ajustar los pesos de una red multicapa. Este método se incrusta dentro del descenso por gradiente y lo habilita para entrenar las redes multicapa. En su forma teórica, el método utiliza el error de la capa de salida y propaga este error hacia atrás, capa a capa hasta la capa de entrada.

Siendo este método una extensión del descenso por gradiente. Partimos del hecho que los pesos se actualizan de la misma forma iterativa, siendo el incremento del peso proporcional a la tasa de aprendizaje y al gradiente del error. A diferencia de la ecuación () definida previamente, en este caso, la el gradiente se calcula con respecto al peso independientemente de la capa. Observe la ecuación (#eq:descenso_backprop).

$$

w^{new} = w^{old} + (-1) _{w}E $$

Calcular el gradiente implica determinar las derivadas parciales con respecto del peso en cuestión. Supongamos que se desea calcular el gradiente para un peso \((i,j)\), de la capa \(t\); escrito como \(w_{t,i,j}\). El peso dentro de la red se ilustra en la figura 2.

Ilustración del peso \(w_{t,i,j}\). El peso conecta la \(i\)-ésima neurona de la capa \(t-1\) con la neurona \(j\)-ésima de la capa \(t\).

$$

H_t = A_{t-1} W_t + B $$

$$

A_t = f(H_t)$$

El gradiente para este peso se determina usando la regla de la cadena. Acortando la escritura de la derivada escribiríamos:

$$

= , $$

donde el término \(\frac{\partial E}{\partial h_{t,i}}\) está indicado y se tendría que desplegar de acuerdo con la regla de la cadena. Por otro lado, usando la expansión de la ecuación (#eq:h_backprop) podríamos resolver el segundo término.

$$

= ( k a{t-1,k} w_{t,k,j} + b_{t,j} )$$

Dado que tenemos una derivada parcial, el único término donde no se hace cero la derivada es donde \(k\) iguala a \(i\), por tanto:

$$

= a_{t-1}$$

Reemplazando en la ecuación (#eq:parcial_backprop),

$$

= a_{t-1}, $$

De forma general, el peso \(w_{t,i,j}\) se actualizaría como:

$$

w_{t,i,j} = w_{t,i,j} + (-1) a_{t-1} $$

De lo anterior podemos observar nuevamente que se requiere un proceso iterativo que actualizará al peso. Además que se tendrá que calcular en cada iteración la derivada del error con respecto del valor \(h\). Si bien el método es correcto, estudiaremos en la siguiente sección una reconfiguración para evitar cálculos repetitivos y mejorar la eficiencia de la retropropagación.

27.1 Retropropagación eficiente

Como vimos en la sección previa, la retropropagación nos permite calcular la contribución de cada peso al error, y con base en ello ajustar su valor. En esta sección estudiaremos una forma de mejorar la eficiencia del cálculo del gradiente de forma independiente. Al final, tendremos una forma recurrente de calcular el gradiente, a través de un término de error similar al que calculamos en la sección 3.3. Esto nos permitirá reusar el término de error inmediato superior e independizar el cálculo de capas superiores.

Ilustración de la relación del término de error con las capas superiores.

27.1.1 Caso base

Iniciaremos con el análisis de la retropropagación en la capa superior. Esta comienza comienza calculando el error de la capa de salida, especificada con el sub-índice o. Observe la figura 3. De acuerdo con lo especificado en la sección 3.3, el término de error se determina como:

$$

_o = = (y-) f’(h) $$

El término \(\delta_o\) nos permite actualizar la capa de salida. Si embargo si deseamos actualizar la capa oculta, especificada con el sub-índice \(h\). Debemos calcular su contribución del peso esto es:

$$

= $$

Substituyendo la ecuación #eq:delta_o y resolviendo \(\frac{\partial h_o}{\partial a_h}\) reescribimos el gradiente como:

$$

= _o w_o $$

\(\frac{\partial f_h}{\partial h_h}\) indica la derivada parcial de la función de activación oculta, dado que la función puede cambiar en cada implementación, la dejaremos indicada como: \(f_h'(h_h)\) y reescribimos la ecuación como:

$$

= _o w_o f_h’(h_h) $$

Lo anterior nos permite definir un término de error en la capa oculta que depende de las capas superiores:

$$

{_h} = o w{h} f’(h_h)$$

Observemos que este nuevo término de error es proporcional al error en la capa de salida, \(\delta_o\), y a la conexión que se tiene con dicha capa, \(w_{h}\).

En la mayoría de los casos, las redes tienen más de una salida por lo cual, generalizaremos que el término de error en la capa oculta se calcula como:

$$

_h = o w{o} _o f’(h_h)$$

Una vez establecido el término de error en la capa oculta, reutilizaremos los conceptos de incremento y actualización. Donde el incremento de los pesos se calcula de la misma forma que en la ecuación (#eq:incremento_del_peso):

$$

w_{h,i} = h x{i}$$

27.1.2 Caso general

$$

{i,j} = {k} w_{i+1,k} {i+1,k} f’{i}(h_{i,j})$$

$$

W_{i,j} = {i,j} A{i-1}$$

Ejemplo

Partiendo de la siguiente red de una capa oculta, con funciones de activación \(f_1 =\) ELU y \(f_2 =\) Sigmoide:

image

donde la entrada es $$

X = \[\begin{bmatrix} -0.5 & 0.5 & -0.5 \end{bmatrix}\]

$$

los parámetros de la red son $$

W_1 = \[\begin{bmatrix} 0.5 & -0.1 \ 0.6 & 1.5 \ -0.2 & -0.2 \end{bmatrix}\] -0.2 & -0.2 \end{bmatrix}, W_2 = \[\begin{bmatrix} -0.5 \ -0.2 \end{bmatrix}\]

\end{bmatrix}$$

$$

B_1 = \[\begin{bmatrix} 1.6 & 0.8 \end{bmatrix}\] , B_2 = \[\begin{bmatrix} -1.9 \end{bmatrix}\]

$$

y la salida objetivo es $$

Y = [1]$$

determine:

  1. la salida de la red,

  2. los términos de error,

  3. el incremento de los pesos usando un \(\eta = 0.6\),

  4. los nuevos valores para los pesos.

Solución:

  1. Utilizando inferencia frontal obtenemos: $$

= f_2( f_1(X W_1 + B_1 ) W_2 + B_2 ) = [0.1]$$

  1. A continuación calculamos el vector del término de error $$

_2 = - f_2’(h) = (y - ) f_2(h)(1 - f_2(h)) = 6.81^{-02}$$

$$

_{1}[1] = W_2[1] _2 f_1(h[1])\[ \]

_{1}[2] = W_2[2] _2 f_1(h[2])$$

, note que se está utilizando el operador ‘\([ \quad ]\)’ como un selector de un elemento de la matriz. De esta forma tendríamos: $$

_{1} = \[\begin{bmatrix} -3.40 \times 10^{-2} & 1.36e \times 10^{-2} \end{bmatrix}\]

$$

  1. Recordando la fórmula $$
W_2 = _2 A_1 = \[\begin{bmatrix} 7.15 \times 10^{-2} \\ 6.95 \times 10^{-2} \end{bmatrix}\]

$$

para los primeros pesos $$

W_1 = \[\begin{bmatrix} \delta_1[1] X & \delta[2]X \end{bmatrix}\]

$$

es decir $$

W_1 =

\[\begin{bmatrix} 1.02 \times 10^{-2} & -4.09 \times 10^{-3} \ -1.02 \times 10^{-2} & 4.09 \times 10^{-3} \ 1.02 \times 10^{-2} & -4.09 \times 10^{-3} \end{bmatrix}\]

10^{-2} & 4.09 ^{-3}
1.02 ^{-2} & -4.09 ^{-3} \end{bmatrix}$$

  1. La actualización procede como $$
W_2^1 = W_2 + W_2 = \[\begin{bmatrix} -0.428 \ 0.269 \end{bmatrix}\]

\end{bmatrix}\[ \]

W_1^1 = W_1 + W_1 = \[\begin{bmatrix} 0.510 & -0.104 \ 0.590 & 1.50 \ -0.190 & -0.204 \end{bmatrix}\]


-0.190 & -0.204 \end{bmatrix}$$

Note que en las expresiones se usa el superíndice para indicar el número de época que se está usando.

27.2 Ejercicios

Ejercicio

Partiendo del ejercicio #ej:rn multicapa 211, suponga una métrica de pérdida como el MSE, \(y=0.5\), \(\eta = 10\). Determine lo siguiente:

  • Determine el error residual.

  • Determine los términos de error.

  • Determine las matrices de actualización.

  • Calcule los nuevos valores de todos los pesos.

Ejercicio

Dada la siguiente red neuronal multicapa: image donde: $$

X = [6, 7], W_1 = \[\begin{bmatrix} -0.4 & 0.2 \ 0.8 & 1.0 \end{bmatrix}\] \end{bmatrix}, W_2 = \[\begin{bmatrix} 0.1 & -0.8 \ 0.4 & 0.3 \end{bmatrix}\]

\end{bmatrix}, Y = [1.0, 0.5],$$

funciones de activación \(f_1 =\) ReLU y \(f_2\) = sigmoide, error cuadrático medio como pérdida, \(\eta = 3.0\), y sin sesgos.

  1. Calcule la salida vectorial de la red, \(\hat{Y}\).

  2. Determine el vector de error residual.

  3. Determine el término de error de salida, \(\delta_2\).

  4. Determine el término de error de la capa oculta, \(\delta_1\)

  5. Calcule las matrices de incremento, \(\Delta W_2\) y \(\Delta W_1\)

  6. Actualice el valor de los pesos.

27.3 Algoritmo de retropropagación

Para comprender la mecánica operativa de la retropropagación analizaremos una posible implementación sintetizada en el Algoritmo #al:retropropagacion.

El proceso comienza asignando valores iniciales a los tensores de pesos de todas las capas. Generalmente se utilizan distribuciones aleatorias pequeñas o métodos de normalización como Xavier o He para evitar la saturación temprana de las neuronas. El ciclo principal define cuántas épocas completas realizará el algoritmo sobre el conjunto de datos total \(\mathcal{D}\) para refinar los pesos. Al inicio de cada época, se reinician a cero los acumuladores de gradientes. Estos tensores almacenan la suma de las actualizaciones parciales calculadas para cada uno de los \(m\) ejemplos antes de aplicar el ajuste global.

Por cada par de entrada y objetivo \((X, Y)\) dentro del conjunto de datos \(\mathcal{D}\) Se ejecuta la propagación hacia adelante. La red calcula las activaciones de cada capa \(A_i\) mediante la relación \(A_i = f_i(A_{i-1}W_i)\) hasta obtener la predicción final en la capa de salida.

A continuación se determina el término de error en la capa de salida. Este valor resulta de multiplicar el residuo directo entre el valor real y el predicho por la derivada de la función de activación \(f'\) evaluada en la entrada neta \(h_j\).

En seguida se inicia la retropropagación propiamente dicha, recorriendo la red desde la penúltima capa hacia atrás hasta la primera capa oculta.

A continuación se calcula el término de error intermedio. La responsabilidad del error de la neurona \(j\) en la capa \(i\) es la suma ponderada de los errores de la capa siguiente, filtrada por la derivada de su propia activación.

Entonces, se acumula el gradiente para la capa \(i\). Esta operación representa el producto exterior entre el vector de error de la capa actual y las activaciones de la capa anterior, identificando qué conexiones fueron responsables del error observado. Note que el cálculo del incremento de pesos se hace mediante la expresión: \(\Delta W_{i} = \Delta W_{i} + \delta_{i}^T A_{i-1}\). Esta operación no es una multiplicación escalar ni un producto punto convencional, sino un producto exterior (o producto matricial de un vector columna por uno fila) que se justifica por la regla de la cadena aplicada a cada conexión individual \(w_{i,j,k}\).

Tras procesar los \(m\) ejemplos, se realiza la actualización matricial. Se escala el acumulador por la tasa de aprendizaje \(\eta\) y se promedia entre el número de ejemplos \(m\) para estabilizar el paso del gradiente. Una vez completadas las \(T\) épocas, el algoritmo devuelve la matriz de pesos optimizada.

# Algoritmo de retropropagación. Esta posible implementación por ciclos usa términos de error intermedios que permiten la reutilización del gradiente de la capa superior.
[htb]
    Entrada: Conjunto de datos ($\mathcal{D$), número de ejemplos ($m$), tasa de aprendizaje ($\eta$), número de épocas ($T$), número de capas ($\kappa$)}
    Salida: Pesos entrenados ($\mathbf{W$)}
    $\texttt{Inicializar}(\mathbf{W})$# Inicializar pesos
    \For{$t=1;T$}
            $\text{Ceros}(\Delta \mathbf{W})$ \;
        \ForEach{($X, Y) \in \mathcal{D}$}
            $\hat{Y} = \Phi_{\mathbf{W}}(X)$ # Nota: $A_i=f_i(A_{i-1W_i)$}
            $\delta_{\kappa,j} = (y_j-\hat{y}_j)f'(h_j)$ # Capa de salida
                \For{$i=\kappa-1;i>0;i=i-1$}
                    $\delta_{i,j} = \sum_k \delta_{i+1,k} \hspace{3pt} w_{i+1,j,k} \hspace{3pt} f'_{i}(h_{i,j})$ # Términos de error por capa
                \ForEach{$\Delta W_i \in \Delta \mathbf{W}$}
                %\ForEach{$\Delta w_{i,j} \in \Delta W_t$}
                $\Delta W_{i} = \Delta W_{i} + \delta_{i}^T A_{i-1}$
            # Incremento por capa
                %}
    \ForEach{$W_i \in \mathbf{W}$}
          $W_i = W_i + \frac{\eta}{m} \Delta W_i $ # Actualización matricial}
    return $\mathbf{W$}