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 δyδE y δwδE. 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 x, para simplificar el desarrollo, y luego generalizaremos a un lote de N ejemplos.
Comenzamos con el caso de δxδE. Si bien este caso es en realidad simétrico con respecto a δwδE, 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 x∈R y w∈R, es decir, son escalares. entonces δyδE también es un escalar, y por regla de la cadena:
δxδE=δyδEδxδy=δyδEδxδwx=δyδEw
I entradas, 1 salida
Pasemos ahora al caso con I entradas y 1 salida. Entonces x es un vector de I valores, es decir, x∈RI y por ende w∈RI también es un vector con I valores. En tal caso, podemos pensar la salida como el producto punto o matricial entre w y x
y=x.w=i=1∑Ixiwi
Entonces, tenemos una derivada parcial por cada entrada: \frac{δE}{δx_j}. Recordando que δyδE sigue siendo un escalar (porque hay una sola salida), y utilizando la regla de la cadena, podemos calcular esta derivada:
δxjδE=δyδEδxjδy=δyδEδxjδ∑i=1Iwixi=δyδEi=1∑Iδxjδwixi=δyδEδxjδwjxj=δyδEwj
Entonces δxjδE=δyδEwj. Podemos generalizar esta definición entonces, y calcular el gradiente respecto a todo el vector x como:
δxδE=δyδEw
Notas
- Es genial que la misma definición de $\frac funcione en ambos casos, ya sea con 1 entrada o una cantidad I arbitraria de ellas.
- Es importante tener en cuenta que en este contexto podemos tratar a δyδE como una constante, ya que sus valores han sido previamente calculados.
- Podríamos hacer la derivación de δxδy aparte, sin tomar en cuenta el error de la red, y luego obtener δxδE aplicando la regla de la cadena δxδE=δyδEδxδy. No obstante, para ser más claros en el contexto del método
backward una red, lo estamos haciendo todo al mismo tiempo.
I entradas, O salida
Nuevamente, vamos por la derivada de una de las entradas, es decir, δxjδE.
δxjδE=δyδEδxjδy
En este caso, y es ahora un vector, con lo cual tenemos que sumar las contribuciones de cada elemento de y a la regla de la cadena. Por ende:
δxjδE=δyδEδxjδy=i=1∑OδyiδEδxjδyi
Ahora, sabemos que yi es el producto punto de la columna i de w con la entrada x, por la definición de la multiplicación de matrices. Entonces:
δxjδE=i=1∑OδyiδEδxjδyi=i=1∑OδyiδEδxjδ(w:,i⋅x)=i=1∑OδyiδEδxjδ(∑k=1Iwk,ixk)=i=1∑OδyiδE(k=1∑Iδxjδwk,ixk)=i=1∑OδyiδEwj,i
Ahora, ∑i=1OδyiδEwj,i es simplemente el producto punto entre la columna i de w (w:,i) y δyδE. Entonces podemos escribir:
δxjδE=δyδE⋅w:,i
Generalizando para todo el vector x, si δxjδE es el producto entre dos vectores, donde j indica la columna de w, entonces podemos escribir δxδE como un producto entre el vector δyδE y la matriz w entera:
δxδE=wδyδE
En este caso, el orden importa nuevamente. w tiene tamaño I×O y δyδE tiene tamaño O, con lo cual wδyδE tiene tamaño I (el mismo que x)
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 N ejemplos (y por ende, de N vectores de derivadas, tanto para la entrada como la salida)
En la implementación por lotes de δxδE, tenemos que x es una matriz de tamaño N×I, y por ende también lo es δxδE. Al mismo tiempo, como δyδE es en realidad δxδE de la capa siguiente, tenemos que δyδE es una matriz de tamaño N×O.
Entonces, no podemos multiplicar w∈RI×O por δyδE∈RN×O. En este caso, puedes comprobar que la fórmula correcta es δyδEwT, ya que al multiplicar una matriz de tamaño N×O por una de tamaño O×I (wT), obtenemos una matriz de tamaño N×I, o sea, del mismo tamaño de x:
δxδE=δyδEwT
En el caso del gradiente del error con respecto a w, también primero asumiremos que hay un solo ejemplo de entrada x, y vamos por casos de más simple a más complejo.
I entradas, 1 salida
Este es el caso más simple, y es simétrico al de x:
δwδE=δwδEδxδw=δwδEδwδwx=δyδEx
I entradas, 1 salida
Pasemos ahora al caso con I entradas y 1 salida.
y=x.w=i=1∑Ixiwi
Como w tiene I elementos, entonces hay una derivada parcial por cada valor de w: \frac{δE}{δw_j}. Recordando que δyδE sigue siendo un escalar (porque hay una sola salida), y utilizando la regla de la cadena, podemos calcular esta derivada:
δwjδE=δyδEδwjδy=δyδEδwjδ∑i=1Iwixi=δyδEi=1∑Iδxwjδwixi=δyδEδwjδwjxj=δyδExj
Entonces δwjδE=δyδExj. Podemos generalizar esta definición entonces, y calcular el gradiente respecto a todo el vector x como:
δwδE=δyδEx
De nuevo, este caso es entonces simétrico con x, ya que δxδE=δyδEw.
I entradas, O salidas
En este caso, al tener O salidas, ahora vamos a tener que buscar la derivada de los pesos de cada entrada i para cada salida j. En este caso, perdemos la simetría anterior (pero la recuperaremos en la versión por lotes).
Por ende, buscamos δwi,jδE. Por regla de la cadena:
δwi,jδE=δyδEδwi,jδy=δyδEδwi,jδxw
Como y es un vector, tenemos que sumar por todos sus valores para aplicar la regla de la cadena:
δwi,jδE=δyδEδwi,jδxw=k=1∑OδykδEδwi,jδ(xw)k
Como yk solo depende de wi,j si j=k, es decir, si estamos calculando la salida de la columna k, entonces:
δwi,jδE=δyδEδwi,jδxw=δyjδEδwi,jδ(xw)j
Por definición de la multiplicación de matrices, (xw)j=∑l=1Oxlwl,j, o sea, multiplicamos x por la columna j de w. Reemplazando:
δwi,jδE=δyjδEδwi,jδ(xw)j=δyjδEδwi,jδ(∑l=1Oxlwl,j)=δyjδEl=1∑Oδwi,jδ(xlwl,j)
Como wi,j es solo un peso en particular de w, entonces de toda esa sumatoria solo queda el término que la contiene, es decir wi,jδxiwi,j=xi. Reemplazando:
δwi,jδE=δyjδEl=1∑Oδwi,jδ(xlwl,j)=δyjδEδwi,jδ(xiwi,j)=δyjδExi
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 δwδE:
δwδE=⎝⎜⎜⎛δy1δEx1δy1δEx2...δy1δExIδy2δEx1δy2δEx2...δy2δExI............δyOδEx1δyOδEx2...δyOδExI⎠⎟⎟⎞=x⊗δyδE
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 a y b tienen tamaño p y q, entonces $ a ⊗ b$ tiene tamaño p×q, y $ b ⊗ a$ tiene tamaño q×p. Por eso, como δwδE debe tener tamaño I×O, entonces debemos computar x⊗δyδE en lugar de δyδE⊗x.
Caso por lotes
En el caso de tener un lote de n ejemplos, entonces recordamos que x tiene tamaño n×I, w tiene tamaño I×O, y δyδE tiene tamaño n×O.
Al igual que en el caso de b, para calcular δwδE tenemos que sumar el gradiente que contribuye cada ejemplo xi. Entonces:
δwδE=i=1∑nxi,:⊗δyi,:δE
Donde xi,: es la fila i de x, es decir, el ejemplo i (el equivalente en numpy sería x[i,:])
Por ejemplo, si n=2, podemos verificar que:
δwδE=x1,:⊗δy1,:δE+x1,:⊗δy2,:δE=⎝⎛δy1,1δEx1,1+δy2,1δEx2,1δy1,1δEx1,2+δy2,1δEx2,2...δy1,1δEx1,I+δy2,1δEx2,Iδy1,2δEx1,1+δy2,2δEx2,1δy1,2δEx1,2+δy2,2δEx2,2...δy1,2δEx1,I+δy2,2δEx2,I............δy1,OδEx1,1+δy2,OδEx2,1δy1,OδEx1,2+δy2,OδEx2,2...δy1,OδEx1,I+δy2,OδEx2,I⎠⎞=xtδyδE
Esto también vale para cualquier n!. Podemos confirmar esta identidad en base a los tamaños: si multiplicamos xt (tamaño I×n) con δyδE (tamaño n×O), obtenemos una matriz de tamaño I×O, igual que w y ¡justo el tamaño que debe tener δwδE!.
Entonces, ahora si podemos ver la simetría entre las dos derivadas:
δwδE=δwδyδyδE=xtδyδEδxδE=δxδyδyδE=δyδEw