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