Algoritmo de retropropagación


19

Tengo una ligera confusión sobre el algoritmo de retropropagación utilizado en el perceptrón multicapa (MLP).

El error se ajusta mediante la función de costo. En la retropropagación, estamos tratando de ajustar el peso de las capas ocultas. El error de salida que puedo entender, es decir, e = d - y[Sin los subíndices].

Las preguntas son:

  1. ¿Cómo se obtiene el error de la capa oculta? ¿Cómo se calcula?
  2. Si lo propago hacia atrás, ¿debería usarlo como una función de costo de un filtro adaptativo o debería usar un puntero (en C / C ++) sentido de programación, para actualizar el peso?

NN es más bien una tecnología obsoleta, por lo que me temo que no obtendrá una respuesta porque aquí nadie los está utilizando ...

@mbq: No dudo de tus palabras, pero ¿cómo llegas a la conclusión de que NN son "tecnología obsoleta"?
steffen

1
@steffen Por observación; Quiero decir que es obvio que nadie importante de la comunidad de NN saldrá y dirá "¡Hola chicos, dejemos nuestro trabajo de la vida y juguemos con algo mejor!", Pero tenemos herramientas que logran la misma o mejor precisión sin toda esta ambivalencia y nunca final de entrenamiento. Y la gente deja caer NN a favor de ellos.

55
Esto tenía algo de verdad cuando lo dijiste, @mbq, pero ya no.
jerad

1
@jerad Bastante fácil: simplemente todavía no he visto una comparación justa con otros métodos (Kaggle no es una comparación justa debido a la falta de intervalos de confianza para las precisiones, especialmente cuando los resultados de todos los equipos de alta puntuación están tan cerca como en el concurso de Merck), ni ningún análisis de robustez de la optimización de parámetros, que es mucho peor.

Respuestas:


27

Pensé que respondería una publicación independiente aquí para cualquiera que esté interesado. Esto usará la notación descrita aquí .

Introducción

La idea detrás de la propagación hacia atrás es tener un conjunto de "ejemplos de capacitación" que usamos para capacitar a nuestra red. Cada uno de estos tiene una respuesta conocida, por lo que podemos conectarlos a la red neuronal y descubrir cuánto estuvo mal.

Por ejemplo, con el reconocimiento de escritura a mano, tendría muchos caracteres escritos a mano junto a lo que realmente eran. Luego, la red neuronal se puede entrenar a través de la propagación hacia atrás para "aprender" cómo reconocer cada símbolo, de modo que cuando se presente más tarde con un carácter escrito a mano desconocido pueda identificar qué es correctamente.

Específicamente, ingresamos alguna muestra de entrenamiento en la red neuronal, vemos qué tan bien funcionó, luego "goteamos hacia atrás" para encontrar cuánto podemos cambiar los pesos y el sesgo de cada nodo para obtener un mejor resultado, y luego ajustarlos en consecuencia. A medida que continuamos haciendo esto, la red "aprende".

También hay otros pasos que pueden incluirse en el proceso de capacitación (por ejemplo, abandono), pero me enfocaré principalmente en la propagación hacia atrás ya que de eso se trataba esta pregunta.

Derivadas parciales

Una derivada parcial es una derivada defcon respecto a alguna variablex.fxfx

Por ejemplo, si , ff(x,y)=x2+y2, porquey2es simplemente una constante con respecto ax. Del mismo modo,ffx=2xy2x, porquex2es simplemente una constante con respecto ay.fy=2yx2y

Un gradiente de una función, designada , es una función que contiene la derivada parcial para cada variable en f. Específicamente:f

,

f(v1,v2,...,vn)=fv1e1++fvnorteenorte

donde es un vector unitario que apunta en la dirección de la variable v 1 .miyov1

Ahora, una vez que hemos calculado la para alguna función f , si estamos en la posición ( v 1 , v 2 , . . . , V n ) , podemos "slide abajo" f yendo en la dirección - f ( v 1 , v 2 , . . . , v n ) .FF(v1,v2,...,vnorte)F-F(v1,v2,...,vnorte)

Con nuestro ejemplo de , los vectores unitarios son e 1 = ( 1 , 0 ) y e 2 = ( 0 , 1 ) , porque v 1 = x y v 2 = y , y esos vectores apuntan en la dirección de los ejes x e y . Por lo tanto, f ( x , yF(X,y)=X2+y2mi1=(1,0 0)mi2=(0 0,1)v1=Xv2=yXy .f(x,y)=2x(1,0)+2y(0,1)

Ahora, para "deslizar hacia abajo" nuestra función , digamos que estamos en un punto ( - 2 , 4 ) . Entonces tendríamos que movernos en dirección - f ( - 2 , - 4 ) = - ( 2 - 2 ( 1 , 0 ) + 2 4 ( 0 , 1 ) ) = - ( ( - 4 , 0 ) +f(2,4) .f(2,4)=(2-2(1,0 0)+24 4(0 0,1))=-((-4 4,0 0)+(0 0,8))=(4,8)

La magnitud de este vector nos dará cuán empinada es la colina (valores más altos significan que la colina es más empinada). En este caso, tenemos .42+(8)28.944

Descenso de gradiente

Producto Hadamard

El producto Hadamard de dos matrices , es como la suma de matrices, excepto que en lugar de sumar las matrices en cuanto a elementos, las multiplicamos en función de elementos.A,BRn×m

Formalmente, mientras que la suma de matrices es , donde C R n × m tal queA+B=CCRn×m

,

Cji=Ajyo+sijyo

El producto Hadamard , donde C R n × m tal queUNsi=CCRnorte×metro

Cjyo=UNjyosijyo

Calcular los gradientes

(La mayor parte de esta sección es del libro de Neilsen ).

(S,mi)SrmirWsirijk

C(W,B,Sr,Er)

Normalmente, lo que se usa es el costo cuadrático, que se define por

C(W,B,Sr,Er)=0.5j(ajLEjr)2

aLSr

CwjiCbji

CSrErWBWB

δji=Czjiji

aLSr

δL

δjL=CajLσ(zjL)

Que también se puede escribir como

δL=aCσ(zL)

δiδi+1

δi=((Wi+1)Tδi+1)σ(zi)

Ahora que tenemos el error de cada nodo en nuestra red neuronal, es fácil calcular el gradiente con respecto a nuestros pesos y sesgos:

Cwjki=δjiaki1=δi(ai1)T

Cbji=δji

Tenga en cuenta que la ecuación para el error de la capa de salida es la única ecuación que depende de la función de costo, por lo que, independientemente de la función de costo, las últimas tres ecuaciones son las mismas.

Como ejemplo, con costo cuadrático, obtenemos

δL=(aLEr)σ(zL)

L1th layer:

δL1=((WL)TδL)σ(zL1)
=((WL)T((aLEr)σ(zL)))σ(zL1)

which we can repeat this process to find the error of any layer with respect to C, which then allows us to compute the gradient of any node's weights and bias with respect to C.

I could write up an explanation and proof of these equations if desired, though one can also find proofs of them here. I'd encourage anyone that is reading this to prove these themselves though, beginning with the definition δji=Czji and applying the chain rule liberally.

For some more examples, I made a list of some cost functions alongside their gradients here.

Gradient Descent

Now that we have these gradients, we need to use them learn. In the previous section, we found how to move to "slide down" the curve with respect to some point. In this case, because it's a gradient of some node with respect to weights and a bias of that node, our "coordinate" is the current weights and bias of that node. Since we've already found the gradients with respect to those coordinates, those values are already how much we need to change.

We don't want to slide down the slope at a very fast speed, otherwise we risk sliding past the minimum. To prevent this, we want some "step size" η.

Then, find the how much we should modify each weight and bias by, because we have already computed the gradient with respect to the current we have

Δwjki=ηCwjki

Δbji=ηCbji

Thus, our new weights and biases are

wjki=wjki+Δwjki
bji=bji+Δbji

Using this process on a neural network with only an input layer and an output layer is called the Delta Rule.

Stochastic Gradient Descent

Now that we know how to perform backpropagation for a single sample, we need some way of using this process to "learn" our entire training set.

One option is simply performing backpropagation for each sample in our training data, one at a time. This is pretty inefficient though.

A better approach is Stochastic Gradient Descent. Instead of performing backpropagation for each sample, we pick a small random sample (called a batch) of our training set, then perform backpropagation for each sample in that batch. The hope is that by doing this, we capture the "intent" of the data set, without having to compute the gradient of every sample.

For example, if we had 1000 samples, we could pick a batch of size 50, then run backpropagation for each sample in this batch. The hope is that we were given a large enough training set that it represents the distribution of the actual data we are trying to learn well enough that picking a small random sample is sufficient to capture this information.

However, doing backpropagation for each training example in our mini-batch isn't ideal, because we can end up "wiggling around" where training samples modify weights and biases in such a way that they cancel each other out and prevent them from getting to the minimum we are trying to get to.

To prevent this, we want to go to the "average minimum," because the hope is that, on average, the samples' gradients are pointing down the slope. So, after choosing our batch randomly, we create a mini-batch which is a small random sample of our batch. Then, given a mini-batch with n training samples, and only update the weights and biases after averaging the gradients of each sample in the mini-batch.

Formally, we do

Δwjki=1nrΔwjkri

and

Δbji=1nrΔbjri

where Δwjkri is the computed change in weight for sample r, and Δbjri is the computed change in bias for sample r.

Then, like before, we can update the weights and biases via:

wjki=wjki+Δwjki
bji=bji+Δbji

This gives us some flexibility in how we want to perform gradient descent. If we have a function we are trying to learn with lots of local minima, this "wiggling around" behavior is actually desirable, because it means that we're much less likely to get "stuck" in one local minima, and more likely to "jump out" of one local minima and hopefully fall in another that is closer to the global minima. Thus we want small mini-batches.

On the other hand, if we know that there are very few local minima, and generally gradient descent goes towards the global minima, we want larger mini-batches, because this "wiggling around" behavior will prevent us from going down the slope as fast as we would like. See here.

One option is to pick the largest mini-batch possible, considering the entire batch as one mini-batch. This is called Batch Gradient Descent, since we are simply averaging the gradients of the batch. This is almost never used in practice, however, because it is very inefficient.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.