24 votos

Algoritmo de retropropagación y error en la capa oculta

Tengo una pequeña confusión en el retropropagación algoritmo utilizado en perceptrón multicapa (MLP).

El error se ajusta mediante la función de costes. En la retropropagación, se trata de ajustar el peso de las capas ocultas. El error de salida 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 retropropago, ¿debo utilizarlo como una función de coste de un filtro adaptativo o debo utilizar un puntero (en C/C++) sentido de la programación, para actualizar el peso?

33voto

William Ryan Puntos 1

Me imaginé que iba a responder a un post independiente aquí para cualquiera que esté interesado. Esto será utilizando la notación descrita ici .

Introducción

La idea detrás de la retropropagación es tener un conjunto de "ejemplos de entrenamiento" que utilizamos para entrenar nuestra red. Cada uno de ellos tiene una respuesta conocida, por lo que podemos introducirlos en la red neuronal y averiguar en qué medida se equivocó.

Por ejemplo, con el reconocimiento de escritura a mano, tendrías un montón de caracteres manuscritos junto a lo que son en realidad. La red neuronal puede entrenarse mediante retropropagación para "aprender" a reconocer cada símbolo, de modo que cuando se le presente un carácter manuscrito desconocido pueda identificarlo correctamente.

Específicamente, introducimos una muestra de entrenamiento en la red neuronal, vemos lo bien que lo ha hecho y, a continuación, "retrocedemos" para averiguar cuánto podemos cambiar los pesos y el sesgo de cada nodo para obtener un resultado mejor, y luego los ajustamos en consecuencia. De este modo, la red "aprende".

También hay otros pasos que pueden incluirse en el proceso de entrenamiento (por ejemplo, el abandono), pero me centraré sobre todo en la retropropagación, ya que es de lo que trataba esta pregunta.

Derivadas parciales

Una derivada parcial $\frac{\partial f}{\partial x}$ es una derivada de $f$ con respecto a alguna variable $x$ .

Por ejemplo, si $f(x, y)=x^2 + y^2$ , $\frac{\partial f}{\partial x}=2x$ porque $y^2$ es simplemente una constante con respecto a $x$ . Igualmente, $\frac{\partial f}{\partial y}= 2y$ porque $x^2$ es simplemente una constante con respecto a $y$ .

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

$$\nabla f(v_1, v_2, ..., v_n) = \frac{\partial f}{\partial v_1 }\mathbf{e}_1 + \cdots + \frac{\partial f}{\partial v_n }\mathbf{e}_n$$ ,

donde $e_i$ es un vector unitario que apunta en la dirección de la variable $v_1$ .

Ahora, una vez que hemos calculado el $\nabla f$ para alguna función $f$ , si estamos en posición $(v_1, v_2, ..., v_n)$ podemos "deslizarnos hacia abajo" $f$ yendo en dirección $-\nabla f(v_1, v_2, ..., v_n)$ .

Con nuestro ejemplo de $f(x, y)=x^2 + y^2$ 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 del $x$ y $y$ ejes. Así, $\nabla f(x, y) = 2x (1, 0) + 2y(0, 1)$ .

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

La magnitud de este vector nos dará la pendiente de la colina (los valores más altos significan que la colina es más empinada). En este caso, tenemos $\sqrt{4^2+(-8)^2}\approx 8.944$ .

Gradient Descent

Producto Hadamard

Producto Hadamard de dos matrices $A, B \in R^{n\times m}$ es igual que la suma de matrices, excepto que en lugar de sumar las matrices elemento a elemento, las multiplicamos elemento a elemento.

Formalmente, mientras que la suma de matrices es $A + B = C$ donde $C \in R^{n \times m}$ tal que

$$C^i_j = A^i_j + B^i_j$$ ,

El producto Hadamard $A \odot B = C$ donde $C \in R^{n \times m}$ tal que

$$C^i_j = A^i_j \cdot B^i_j$$

Cálculo de los gradientes

(la mayor parte de esta sección procede de El libro de Neilsen ).

Disponemos de un conjunto de muestras de entrenamiento, $(S, E)$ donde $S_r$ es una única muestra de entrenamiento de entrada, y $E_r$ es el valor de salida esperado de esa muestra de entrenamiento. También tenemos nuestra red neuronal, compuesta por pesos $W$ y sesgos $B$ . $r$ se utiliza para evitar la confusión del $i$ , $j$ et $k$ utilizado en la definición de una red feedforward.

A continuación, definimos una función de costes, $C(W, B, S^r, E^r)$ que toma nuestra red neuronal y un único ejemplo de entrenamiento, y nos dice cómo de bien lo ha hecho.

Normalmente lo que se utiliza es el coste cuadrático, que se define por

$$C(W, B, S^r, E^r) = 0.5\sum\limits_j (a^L_j - E^r_j)^2$$

donde $a^L$ es la salida de nuestra red neuronal, dada la muestra de entrada $S^r$

Entonces queremos encontrar $\frac{\partial C}{\partial w^i_j}$ y $\frac{\partial C}{\partial b^i_j}$ para cada nodo de nuestra red neuronal feedforward.

Podemos llamar a esto el gradiente de $C$ en cada neurona porque consideramos $S^r$ y $E^r$ como constantes, ya que no podemos cambiarlas cuando intentamos aprender. Y esto tiene sentido: queremos movernos en una dirección relativa a $W$ y $B$ que minimice el coste, y moviéndose en la dirección negativa del gradiente con respecto a $W$ y $B$ hará esto.

Para ello, definimos $\delta^i_j=\frac{\partial C}{\partial z^i_j}$ como el error de la neurona $j$ en capa $i$ .

Empezamos por calcular $a^L$ enchufando $S^r$ en nuestra red neuronal.

A continuación, calculamos el error de nuestra capa de salida, $\delta^L$ a través de

$$\delta^L_j = \frac{\partial C}{\partial a^L_j} \sigma^{ \prime}(z^L_j)$$ .

Que también puede escribirse como

$$\delta^L = \nabla_a C \odot \sigma^{ \prime}(z^L)$$ .

A continuación, hallamos el error $\delta^i$ en función del error en la capa siguiente $\delta^{i+1}$ a través de

$$\delta^i=((W^{i+1})^T \delta^{i+1}) \odot \sigma^{\prime}(z^i)$$

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

$$\frac{\partial C}{\partial w^i_{jk}}=\delta^i_j a^{i-1}_k=\delta^i(a^{i-1})^T$$

$$\frac{\partial C}{\partial b^i_j} = \delta^i_j$$

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 coste, por lo que, independientemente de la función de coste, las tres últimas ecuaciones son las mismas.

Como ejemplo, con coste cuadrático, obtenemos

$$\delta ^L = (a^L - E^r) \odot \sigma ^ {\prime}(z^L)$$

para el error de la capa de salida. y luego esta ecuación se puede enchufar en la segunda ecuación para obtener el error de la capa de $L-1^{\text{th}}$ capa:

$$\delta^{L-1}=((W^{L})^T \delta^{L}) \odot \sigma^{\prime}(z^{L-1})$$ $$=((W^{L})^T ((a^L - E^r) \odot \sigma ^ {\prime}(z^L))) \odot \sigma^{\prime}(z^{L-1})$$

que podemos repetir este proceso para encontrar el error de cualquier capa con respecto a $C$ lo que nos permite calcular el gradiente de los pesos y el sesgo de cualquier nodo con respecto a $C$ .

Podría escribir una explicación y prueba de estas ecuaciones si se desea, aunque también se pueden encontrar pruebas de las mismas ici . Sin embargo, animo a todos los que lean esto a que lo comprueben por sí mismos, empezando por la definición $\delta^i_j=\frac{\partial C}{\partial z^i_j}$ y aplicando generosamente la regla de la cadena.

Para algunos ejemplos más, he hecho una lista de algunas funciones de coste junto con sus gradientes ici .

Descenso gradual

Ahora que tenemos estos gradientes, tenemos que usarlos aprender. En la sección anterior, vimos cómo mover para "deslizar hacia abajo" la curva con respecto a algún punto. En este caso, debido a que es un gradiente de algún nodo con respecto a los pesos y un sesgo de ese nodo, nuestra "coordenada" son los pesos actuales y el sesgo de ese nodo. Dado que ya hemos encontrado los gradientes con respecto a esas coordenadas, esos valores ya son cuánto tenemos que cambiar.

No queremos deslizarnos por la pendiente a una velocidad muy rápida, de lo contrario corremos el riesgo de deslizarnos más allá del mínimo. Para evitarlo, queremos cierto "tamaño de paso" $\eta$ .

A continuación, encontrar el cuánto debemos modificar cada peso y sesgo por, porque ya hemos calculado el gradiente con respecto a la corriente que tenemos

$$\Delta w^i_{jk}= -\eta \frac{\partial C}{\partial w^i_{jk}}$$

$$\Delta b^i_j = -\eta \frac{\partial C}{\partial b^i_j}$$

Así, nuestras nuevas ponderaciones y sesgos son

$$w^i_{jk} = w^i_{jk} + \Delta w^i_{jk}$$ $$b^i_j = b^i_j + \Delta b^i_j$$

El uso de este proceso en una red neuronal con sólo una capa de entrada y una capa de salida se denomina Regla Delta .

Descenso Gradiente Estocástico

Ahora que sabemos cómo realizar la retropropagación para una sola muestra, necesitamos alguna forma de utilizar este proceso para "aprender" todo nuestro conjunto de entrenamiento.

Una opción es simplemente realizar la retropropagación para cada muestra de nuestros datos de entrenamiento, de una en una. Sin embargo, esto es bastante ineficiente.

Un enfoque mejor es Descenso Gradiente Estocástico . En lugar de realizar la retropropagación para cada muestra, elegimos una pequeña muestra aleatoria (llamada a lote ) de nuestro conjunto de entrenamiento y, a continuación, realizar la retropropagación para cada muestra de ese lote. La esperanza es que al hacer esto, capturamos la "intención" del conjunto de datos, sin tener que calcular el gradiente de cada muestra.

Por ejemplo, si tuviéramos 1000 muestras, podríamos elegir un lote de tamaño 50 y, a continuación, ejecutar la retropropagación para cada muestra de este lote. La esperanza es que nos dieron un conjunto de entrenamiento lo suficientemente grande que representa la distribución de los datos reales que estamos tratando de aprender lo suficientemente bien como para elegir una pequeña muestra aleatoria es suficiente para capturar esta información.

Sin embargo, hacer retropropagación para cada ejemplo de entrenamiento de nuestro mini lote no es lo ideal, porque podemos acabar "dando bandazos" en los que las muestras de entrenamiento modifican los pesos y los sesgos de tal forma que se anulan entre sí e impiden llegar al mínimo al que estamos intentando llegar.

Para evitarlo, queremos ir al "mínimo medio", porque la esperanza es que, de media, los gradientes de las muestras apunten hacia abajo en la pendiente. Así que, después de elegir nuestro lote al azar, creamos un minilotes que es una pequeña muestra aleatoria de nuestro lote. Entonces, dado un minilote con $n$ muestras de entrenamiento, y sólo actualizar los pesos y sesgos después de promediar los gradientes de cada muestra en el mini lote.

Formalmente, hacemos

$$\Delta w^{i}_{jk} = \frac{1}{n}\sum\limits_r \Delta w^{ri}_{jk}$$

y

$$\Delta b^{i}_{j} = \frac{1}{n}\sum\limits_r \Delta b^{ri}_{j}$$

donde $\Delta w^{ri}_{jk}$ es el cambio de peso calculado para la muestra $r$ et $\Delta b^{ri}_{j}$ es el cambio de sesgo calculado para la muestra $r$ .

Entonces, como antes, podemos actualizar los pesos y los sesgos mediante:

$$w^i_{jk} = w^i_{jk} + \Delta w^{i}_{jk}$$ $$b^i_j = b^i_j + \Delta b^{i}_{j}$$

Esto nos da cierta flexibilidad en cómo queremos realizar el descenso de gradiente. Si tenemos una función que estamos intentando aprender con muchos mínimos locales, este comportamiento de "meneo" es realmente deseable, porque significa que es mucho menos probable que nos quedemos "atascados" en un mínimo local, y más probable que "saltemos" de un mínimo local y, con suerte, caigamos en otro que esté más cerca del mínimo global. Por eso queremos minilotes pequeños.

Por otro lado, si sabemos que hay muy pocos mínimos locales, y en general el descenso por gradiente va hacia los mínimos globales, queremos minilotes más grandes, porque este comportamiento de "meneo" nos impedirá bajar la pendiente tan rápido como nos gustaría. Véase ici .

Una opción es elegir el minilote más grande posible, considerando todo el lote como un único minilote. Esto se denomina Descenso gradual por lotes ya que simplemente estamos promediando los gradientes del lote. Sin embargo, esto casi nunca se utiliza en la práctica, porque es muy ineficiente.

6voto

Xenph Yan Puntos 20883

Hace algunos años que no me ocupo de las redes neuronales, pero creo que aquí encontrará todo lo que necesita:

Redes neuronales - Una introducción sistemática, Capítulo 7: El algoritmo de retropropagación

Pido disculpas por no escribir aquí la respuesta directa, pero como tengo que buscar los detalles para acordarme (como tú) y dado que la respuesta sin algún respaldo puede ser incluso inútil, espero que esto esté bien. No obstante, si queda alguna duda, deja un comentario y veré lo que puedo hacer.

6voto

Aksakal Puntos 11351

Abordaré primero la confusión principal: no hay error de capa oculta. Sólo hay error de la salida. La retropropagación = "back" (regla de diferenciación en cadena) + "propagación" (la información viaja entre las capas). Voy a explicar.

El término retropropagación proviene de la siguiente intuición: las entradas se propagan a través de las capas hasta las salidas. Una vez obtenidas las salidas, se comparan con las observaciones reales y se calcula errores y sus coste . A continuación, se propagan estos errores hacia atrás hasta las entradas, mientras se atribuye el cambio en la función de pérdida a cada peso y sesgo en las capas. La dirección hacia atrás proviene de la regla de la cadena del cálculo.

Así funciona la regla de la cadena Supongamos que las entradas son $x$ y tienes una red de dos capas que en última instancia produce $\hat y$ . La salida de una capa oculta con un parámetro $\theta$ es $g(x|\theta)$ y la salida de la NN de la última capa es entonces $\hat y=f(g(x|\theta)|\phi)$ donde $\phi$ un único parámetro de la capa de salida. Se compara la salida $\hat y$ con observación $y$ a continuación, calcule la pérdida $L(y,\hat y)$ .

Por lo tanto, usted quiere disminuir la pérdida $L(y,\hat y(x|\theta,\phi))$ y para ello hay que intentar cambiar los parámetros por $\Delta\theta,\Delta\phi$ de alguna manera. Una forma de hacerlo es ver cómo de sensible es la salida a los cambios de parámetro, y se mide por el gradiente. Así que vas y lo calculas: $$\frac{\partial L}{\partial \phi}=\frac{\partial f}{\partial\phi}\frac{\partial}{\partial f}L$$ $$\frac{\partial L}{\partial \theta}=\frac{\partial g}{\partial\theta}\frac{\partial f}{\partial g}\frac{\partial}{\partial f}L$$

Puede ver cómo, en cierto modo, retrocedemos al calcular las sensibilidades (pendientes) de los parámetros de la capa oculta (pesos) $\frac{\partial L}{\partial \theta}$ . Si tiene más capas, la expresión para el gradiente se alarga con cada capa, añadiendo derivadas desde la izquierda. Por eso se llama volver propagación. No me gusta el término, pero es lo que usa la gente de ML.

Una vez obtenido el gradiente, puede utilizarlo para determinar en qué dirección y cuánto debe modificar los parámetros en la siguiente iteración. Como se puede ver NO hay pérdida o error de una capa oculta. Todo lo que obtenemos es la sensibilidad de la pérdida (error) $L(y,\hat y)$ a los pesos de las capas ocultas.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X