Método backward

En la implementación de la capa Bias las fórmulas de las derivadas eran relativamente sencillas, y la complejidad estaba más que todo en cómo utilizar el framework y comprender la diferencia entre la derivada de la entrada y la de los parámetros.

El método backward de la capa Linear requiere calcular δEδy\frac{δE}{δy} y δEδw\frac{δE}{δw}. En términos de uso del framework, la implementación es muy similar a la de Bias, pero las fórmulas de las derivadas son más complicadas.

Primero asumiremos que hay un solo ejemplo de entrada xx, para simplificar el desarrollo, y luego generalizaremos a un lote de NN ejemplos.

δEδx

Comenzamos con el caso de δEδx\frac{δE}{δx}. Si bien este caso es en realidad simétrico con respecto a δEδw\frac{δE}{δw}, es un poco más fácil de atacar conceptualmente.

Vamos a pensar en esta derivada por casos, desde el más simple al más complejo, incrementando las dimensiones de entrada y salida.

1 entrada, 1 salida

Comenzamos por en el caso más simple, donde tanto la entrada como la salida son 1D, entonces xRx \in R y wRw \in R, es decir, son escalares. entonces δEδy\frac{δE}{δy} también es un escalar, y por regla de la cadena:

δEδx=δEδyδyδx=δEδyδwxδx=δEδyw \frac{δE}{δx} = \frac{δE}{δy} \frac{δy}{δx} = \frac{δE}{δy} \frac{δ wx}{δx} = \frac{δE}{δy} w

II entradas, 1 salida

Pasemos ahora al caso con II entradas y 1 salida. Entonces xx es un vector de II valores, es decir, xRIx \in R^I y por ende wRIw \in R^I también es un vector con II valores. En tal caso, podemos pensar la salida como el producto punto o matricial entre ww y xx

y=x.w=i=1Ixiwiy = x . w= \sum_{i=1}^I x_i w_i

Entonces, tenemos una derivada parcial por cada entrada: \frac{δE}{δx_j}. Recordando que δEδy\frac{δE}{δy} sigue siendo un escalar (porque hay una sola salida), y utilizando la regla de la cadena, podemos calcular esta derivada:

δEδxj=δEδyδyδxj=δEδyδi=1Iwixiδxj=δEδyi=1Iδwixiδxj=δEδyδwjxjδxj=δEδywj \frac{δE}{δx_j} = \frac{δE}{δy} \frac{δy}{δx_j} = \frac{δE}{δy} \frac{δ \sum_{i=1}^I w_i x_i }{δx_j}\\ = \frac{δE}{δy} \sum_{i=1}^I \frac{δ w_i x_i }{δx_j}\\ = \frac{δE}{δy} \frac{δ w_j x_j }{δx_j}\\ = \frac{δE}{δy} w_j

Entonces δEδxj=δEδywj\frac{δE}{δx_j} = \frac{δE}{δy} w_j. Podemos generalizar esta definición entonces, y calcular el gradiente respecto a todo el vector xx como:

δEδx=δEδyw\frac{δE}{δx} = \frac{δE}{δy} w

Notas

  1. Es genial que la misma definición de $\frac funcione en ambos casos, ya sea con 11 entrada o una cantidad II arbitraria de ellas.
  2. Es importante tener en cuenta que en este contexto podemos tratar a δEδy\frac{δE}{δy} como una constante, ya que sus valores han sido previamente calculados.
  3. Podríamos hacer la derivación de δyδx\frac{δy}{δx} aparte, sin tomar en cuenta el error de la red, y luego obtener δEδx\frac{δE}{δx} aplicando la regla de la cadena δEδx=δEδyδyδx\frac{δE}{δx} =\frac{δE}{δy} \frac{δy}{δx}. No obstante, para ser más claros en el contexto del método backward una red, lo estamos haciendo todo al mismo tiempo.

II entradas, OO salida

Nuevamente, vamos por la derivada de una de las entradas, es decir, δEδxj\frac{δE}{δx_j}.

δEδxj=δEδyδyδxj \frac{δE}{δx_j} = \frac{δE}{δy} \frac{δy}{δx_j}

En este caso, yy es ahora un vector, con lo cual tenemos que sumar las contribuciones de cada elemento de yy a la regla de la cadena. Por ende:

δEδxj=δEδyδyδxj=i=1OδEδyiδyiδxj \frac{δE}{δx_j} = \frac{δE}{δy} \frac{δy}{δx_j} = \sum_{i=1}^O \frac{δE}{δy_i} \frac{δy_i}{δx_j}

Ahora, sabemos que yiy_i es el producto punto de la columna ii de ww con la entrada xx, por la definición de la multiplicación de matrices. Entonces:

δEδxj=i=1OδEδyiδyiδxj=i=1OδEδyiδ(w:,ix)δxj=i=1OδEδyiδ(k=1Iwk,ixk)δxj=i=1OδEδyi(k=1Iδwk,ixkδxj)=i=1OδEδyiwj,i \frac{δE}{δx_j} =\sum_{i=1}^O \frac{δE}{δy_i} \frac{δy_i}{δx_j} \\ = \sum_{i=1}^O \frac{δE}{δy_i} \frac{δ(w_{:,i} \cdot x)}{δx_j} \\ = \sum_{i=1}^O \frac{δE}{δy_i} \frac{δ(\sum_{k=1}^I w_{k,i} x_k)}{δx_j} \\ = \sum_{i=1}^O \frac{δE}{δy_i} (\sum_{k=1}^I \frac{δw_{k,i} x_k}{δx_j}) \\ = \sum_{i=1}^O \frac{δE}{δy_i} w_{j,i} \\

Ahora, i=1OδEδyiwj,i\sum_{i=1}^O \frac{δE}{δy_i} w_{j,i} es simplemente el producto punto entre la columna ii de ww (w:,iw_{:,i}) y δEδy\frac{δE}{δy}. Entonces podemos escribir:

δEδxj=δEδyw:,i \frac{δE}{δx_j} = \frac{δE}{δy} \cdot w_{:,i}

Generalizando para todo el vector xx, si δEδxj\frac{δE}{δx_j} es el producto entre dos vectores, donde jj indica la columna de ww, entonces podemos escribir δEδx\frac{δE}{δx} como un producto entre el vector δEδy\frac{δE}{δy} y la matriz ww entera:

δEδx=wδEδy \frac{δE}{δx} = w \frac{δE}{δy}

En este caso, el orden importa nuevamente. ww tiene tamaño I×OI×O y δEδy\frac{δE}{δy} tiene tamaño OO, con lo cual wδEδyw \frac{δE}{δy} tiene tamaño II (el mismo que xx)

Implementación por lotes

Para implementar la derivada para un lote de ejemplos podemos iterar sobre cada uno y calcular las derivadas como indicamos antes. Alternativamente, podemos reescribir la derivada para que funcione directamente para un lote de NN ejemplos (y por ende, de NN vectores de derivadas, tanto para la entrada como la salida)

En la implementación por lotes de δEδx\frac{δE}{δx}, tenemos que xx es una matriz de tamaño N×IN×I, y por ende también lo es δEδx\frac{δE}{δx}. Al mismo tiempo, como δEδy\frac{δE}{δy} es en realidad δEδx\frac{δE}{δx} de la capa siguiente, tenemos que δEδy\frac{δE}{δy} es una matriz de tamaño N×ON×O.

Entonces, no podemos multiplicar wRI×Ow \in R^{I×O} por δEδyRN×O\frac{δE}{δy} \in R{N×O}. En este caso, puedes comprobar que la fórmula correcta es δEδywT\frac{δE}{δy} w^T, ya que al multiplicar una matriz de tamaño N×ON×O por una de tamaño O×IO×I (wTw^T), obtenemos una matriz de tamaño N×IN×I, o sea, del mismo tamaño de xx:

δEδx=δEδywT \frac{δE}{δx} = \frac{δE}{δy} w^T

δEδw

En el caso del gradiente del error con respecto a ww, también primero asumiremos que hay un solo ejemplo de entrada xx, y vamos por casos de más simple a más complejo.

II entradas, 1 salida

Este es el caso más simple, y es simétrico al de xx:

δEδw=δEδwδwδx=δEδwδwxδw=δEδyx \frac{δE}{δw} = \frac{δE}{δw} \frac{δw}{δx} = \frac{δE}{δw} \frac{δ wx}{δw} = \frac{δE}{δy} x

II entradas, 1 salida

Pasemos ahora al caso con II entradas y 1 salida.

y=x.w=i=1Ixiwiy = x . w= \sum_{i=1}^I x_i w_i

Como ww tiene II elementos, entonces hay una derivada parcial por cada valor de ww: \frac{δE}{δw_j}. Recordando que δEδy\frac{δE}{δy} sigue siendo un escalar (porque hay una sola salida), y utilizando la regla de la cadena, podemos calcular esta derivada:

δEδwj=δEδyδyδwj=δEδyδi=1Iwixiδwj=δEδyi=1Iδwixiδxwj=δEδyδwjxjδwj=δEδyxj \frac{δE}{δw_j} = \frac{δE}{δy} \frac{δy}{δw_j} = \frac{δE}{δy} \frac{δ \sum_{i=1}^I w_i x_i }{δw_j}\\ = \frac{δE}{δy} \sum_{i=1}^I \frac{δ w_i x_i }{δxw_j}\\ = \frac{δE}{δy} \frac{δ w_j x_j }{δw_j}\\ = \frac{δE}{δy} x_j

Entonces δEδwj=δEδyxj\frac{δE}{δw_j} = \frac{δE}{δy} x_j. Podemos generalizar esta definición entonces, y calcular el gradiente respecto a todo el vector xx como:

δEδw=δEδyx\frac{δE}{δw} = \frac{δE}{δy} x

De nuevo, este caso es entonces simétrico con xx, ya que δEδx=δEδyw\frac{δE}{δx} = \frac{δE}{δy} w.

II entradas, OO salidas

En este caso, al tener OO salidas, ahora vamos a tener que buscar la derivada de los pesos de cada entrada ii para cada salida jj. En este caso, perdemos la simetría anterior (pero la recuperaremos en la versión por lotes).

Por ende, buscamos δEδwi,j\frac{δE}{δw_{i,j}}. Por regla de la cadena:

δEδwi,j=δEδyδyδwi,j=δEδyδxwδwi,j \frac{δE}{δw_{i,j}} = \frac{δE}{δy} \frac{δy}{δw_{i,j}} = \frac{δE}{δy} \frac{δxw}{δw_{i,j}}

Como yy es un vector, tenemos que sumar por todos sus valores para aplicar la regla de la cadena:

δEδwi,j=δEδyδxwδwi,j=k=1OδEδykδ(xw)kδwi,j \frac{δE}{δw_{i,j}} = \frac{δE}{δy} \frac{δxw}{δw_{i,j}} = \sum_{k=1}^O \frac{δE}{δy_k} \frac{δ(xw)_k}{δw_{i,j}}

Como yky_k solo depende de wi,jw_{i,j} si j=kj=k, es decir, si estamos calculando la salida de la columna kk, entonces:

δEδwi,j=δEδyδxwδwi,j=δEδyjδ(xw)jδwi,j \frac{δE}{δw_{i,j}} = \frac{δE}{δy} \frac{δxw}{δw_{i,j}} = \frac{δE}{δy_j} \frac{δ(xw)_j}{δw_{i,j}}

Por definición de la multiplicación de matrices, (xw)j=l=1Oxlwl,j(xw)_j = \sum_{l=1}^O x_l w_{l,j}, o sea, multiplicamos xx por la columna jj de ww. Reemplazando:

δEδwi,j=δEδyjδ(xw)jδwi,j=δEδyjδ(l=1Oxlwl,j)δwi,j=δEδyjl=1Oδ(xlwl,j)δwi,j \frac{δE}{δw_{i,j}} = \frac{δE}{δy_j} \frac{δ(xw)_j}{δw_{i,j}} = \frac{δE}{δy_j} \frac{δ(\sum_{l=1}^O x_l w_{l,j})}{δw_{i,j}} \\ = \frac{δE}{δy_j} \sum_{l=1}^O \frac{δ(x_l w_{l,j})}{δw_{i,j}}

Como wi,jw_{i,j} es solo un peso en particular de ww, entonces de toda esa sumatoria solo queda el término que la contiene, es decir δxiwi,jwi,j=xi\frac{δx_i w_{i,j}}{w_{i,j}} = x_i. Reemplazando:
δEδwi,j=δEδyjl=1Oδ(xlwl,j)δwi,j=δEδyjδ(xiwi,j)δwi,j=δEδyjxi \frac{δE}{δw_{i,j}} = \frac{δE}{δy_j} \sum_{l=1}^O \frac{δ(x_l w_{l,j})}{δw_{i,j}} \\ = \frac{δE}{δy_j} \frac{δ(x_i w_{i,j})}{δw_{i,j}} = \frac{δE}{δy_j} x_i

Expresión vectorial

La expresión anterior nos ayuda pero deberíamos utilizar un loop for con índices i y j sobre toda la matriz de w. En lugar de eso, podemos generalizar entonces, observando el patrón de la matrix δEδw\frac{δE}{δw}:
δEδw=(δEδy1x1δEδy2x1...δEδyOx1δEδy1x2δEδy2x2...δEδyOx2............δEδy1xIδEδy2xI...δEδyOxI)=xδEδy \frac{δE}{δw} = \left(\begin{matrix} \frac{δE}{δy_1} x_1 & \frac{δE}{δy_2} x_1 & ... & \frac{δE}{δy_O} x_1\\ \frac{δE}{δy_1} x_2 & \frac{δE}{δy_2} x_2 & ... & \frac{δE}{δy_O} x_2\\ ... & ... & ... & ...\\ \frac{δE}{δy_1} x_I & \frac{δE}{δy_2} x_I & ... & \frac{δE}{δy_O} x_I \\ \end{matrix}\right) = x ⊗\frac{δE}{δy}
Donde es el producto diádico o tensorial ( outer product en inglés) entre dos vectores. En numpy, la función outer permite hacer este tipo de operación sin loops.

Hay que tener en cuenta que el producto diádico no es conmutativo: si aa y bb tienen tamaño pp y qq, entonces $ a ⊗ b$ tiene tamaño p×qp×q, y $ b ⊗ a$ tiene tamaño q×pq×p. Por eso, como δEδw\frac{δE}{δw} debe tener tamaño I×OI×O, entonces debemos computar xδEδyx ⊗\frac{δE}{δy} en lugar de δEδyx\frac{δE}{δy} ⊗ x.

Caso por lotes

En el caso de tener un lote de nn ejemplos, entonces recordamos que xx tiene tamaño n×In × I, ww tiene tamaño I×OI×O, y δEδy\frac{δE}{δy} tiene tamaño n×On×O.

Al igual que en el caso de bb, para calcular δEδw\frac{δE}{δw} tenemos que sumar el gradiente que contribuye cada ejemplo xix_i. Entonces:

δEδw=i=1nxi,:δEδyi,:\frac{δE}{δw} = \sum_{i=1}^{n} x_{i,:} ⊗\frac{δE}{δy_{i,:}}

Donde xi,:x_{i,:} es la fila ii de x, es decir, el ejemplo ii (el equivalente en numpy sería x[i,:])

Por ejemplo, si n=2n=2, podemos verificar que:

δEδw=x1,:δEδy1,:+x1,:δEδy2,:=(δEδy1,1x1,1+δEδy2,1x2,1δEδy1,2x1,1+δEδy2,2x2,1...δEδy1,Ox1,1+δEδy2,Ox2,1δEδy1,1x1,2+δEδy2,1x2,2δEδy1,2x1,2+δEδy2,2x2,2...δEδy1,Ox1,2+δEδy2,Ox2,2............δEδy1,1x1,I+δEδy2,1x2,IδEδy1,2x1,I+δEδy2,2x2,I...δEδy1,Ox1,I+δEδy2,Ox2,I)=xtδEδy\frac{δE}{δw} = x_{1,:} ⊗\frac{δE}{δy_{1,:}} + x_{1,:} ⊗\frac{δE}{δy_{2,:}} \\ = \tiny \left(\begin{matrix} \frac{δE}{δy_{1,1}} x_{1,1} + \frac{δE}{δy_{2,1}} x_{2,1} & \frac{δE}{δy_{1,2}} x_{1,1} + \frac{δE}{δy_{2,2}} x_{2,1} & ... & \frac{δE}{δy_{1,O}} x_{1,1} + \frac{δE}{δy_{2,O}} x_{2,1}\\ \frac{δE}{δy_{1,1}} x_{1,2} + \frac{δE}{δy_{2,1}} x_{2,2} & \frac{δE}{δy_{1,2}} x_{1,2} + \frac{δE}{δy_{2,2}} x_{2,2} & ... & \frac{δE}{δy_{1,O}} x_{1,2} + \frac{δE}{δy_{2,O}} x_{2,2}\\ ... & ... & ... & ...\\ \frac{δE}{δy_{1,1}} x_{1,I} + \frac{δE}{δy_{2,1}} x_{2,I} & \frac{δE}{δy_{1,2}} x_{1,I} + \frac{δE}{δy_{2,2}} x_{2,I} & ... & \frac{δE}{δy_{1,O}} x_{1,I} + \frac{δE}{δy_{2,O}} x_{2,I}\\ \end{matrix}\right) \\ \normalsize = x^t \frac{δE}{δy}

Esto también vale para cualquier nn!. Podemos confirmar esta identidad en base a los tamaños: si multiplicamos xtx^t (tamaño I×nI×n) con δEδy\frac{δE}{δy} (tamaño n×On×O), obtenemos una matriz de tamaño I×OI×O, igual que ww y ¡justo el tamaño que debe tener δEδw\frac{δE}{δw}!.

Entonces, ahora si podemos ver la simetría entre las dos derivadas:

δEδw=δyδwδEδy=xtδEδyδEδx=δyδxδEδy=δEδyw \frac{δE}{δw} = \frac{δy}{δw} \frac{δE}{δy} = x^t \frac{δE}{δy} \\ \text{} \\ \frac{δE}{δx}= \frac{δy}{δx} \frac{δE}{δy} = \frac{δE}{δy} w