Educode: implementación de una capa totalmente conectada y propagación hacia atrás de la función de activación

Nivel 1: implementar la retropropagación de la capa totalmente conectada

detalles de la misión

La tarea de este nivel: realizar la retropropagación de la capa totalmente conectada.

información relacionada

Para completar esta tarea, debe dominar:

  1. Propagación hacia atrás de redes neuronales;
  2. Propagación hacia atrás para capas totalmente conectadas.

Para conocer el contenido de esta capacitación, consulte el Capítulo 5 del libro "Introducción al aprendizaje profundo: teoría e implementación basada en Python".

Retropropagación de redes neuronales

En la capacitación anterior, aprendimos que la red neuronal calcula el gradiente de cada parámetro a través de la retropropagación, y la idea central de la retropropagación es la regla de derivación de la cadena, a saber:

∂x∂l​=∂f(x)∂l​⋅∂x∂f(x)​

Entonces, dada una red neuronal, ¿cómo funciona la retropropagación? Aquí tomamos una red neuronal de tres capas como ejemplo para explicar la retropropagación de la red neuronal. La siguiente figura muestra la estructura de esta red neuronal simple.


Figura 1 Red neuronal simple de tres capas

Primero, introducimos una notación f(x;W) para representar una capa de red con entrada x y parámetro W. Supongamos que las tres capas de esta red neuronal son f1​(x;W1​), f2​(x;W2​), f3​(x;W3​), y la función de activación después de cada capa es g1​(x), g2 ​(x), g3​(x). La función de pérdida utilizada en el entrenamiento de redes es L(x,t), donde x representa la salida de la red y t representa el objetivo. Entonces el proceso de cálculo de esta red se puede expresar como:

y1​z1​y2​z2​y3​z3​l​=f1​(x;W1​)=g1​(y1​)=f2​(z1​;W2​)=g2​(y2​)=f3​ (z2​;W3​)=g3​(y3​)=L(z3​,t)​

Al hacer retropropagación, primero retropropagamos la función de pérdida:

∂z3​∂l​=∂z3​∂L(z3​,t)​

Posteriormente, la tercera capa se propaga hacia atrás, y la capa de red anterior se puede deducir de la misma manera:

∂y3​∂l​∂W3​∂l​∂z2​∂l​​=∂z3​∂l​⋅∂y3​∂z3​​=∂z3​∂l​⋅∂y3​∂g3​(y3 ​)​=∂y3​∂l​⋅∂W3​∂y3​​=∂y3​∂l​⋅∂W3​∂f3​(z2​;W3​)​=∂y3​∂l​⋅∂z2 ​∂y3​​=∂y3​∂l​⋅∂z2​∂f3​(z2​;W3​)​​

De la derivación anterior se puede ver que para una capa de red específica, siempre que se conozca el gradiente de su salida, sus parámetros y el gradiente de entrada solo están relacionados con el cálculo de esta capa y no tienen nada que ver con la capa de red. antes y despues Por lo tanto, siempre que se defina el cálculo de la propagación directa y la propagación inversa para cada capa de red, la red neuronal puede calcular el gradiente de cada parámetro. En este proceso, el cálculo de la red neuronal forma un gráfico de cálculo , que no se ampliará en detalle aquí. Los estudiantes interesados ​​pueden consultar los capítulos 5.1−5.2 del libro de texto.

Propagación hacia atrás de capas completamente conectadas

A continuación, aprendamos la retropropagación de la capa totalmente conectada. Primero, revise el pase hacia adelante de la capa completamente conectada. Una capa completamente conectada con N neuronas de entrada y M neuronas de salida contiene dos conjuntos de parámetros: peso W∈RN×M y sesgo b∈RM, cuya entrada puede considerarse como un vector (columna) N-dimensional x ∈RN, en este tiempo, el cálculo de la propagación directa de la capa completamente conectada se puede expresar como:

y=xTW+b

Suponga primero que ∂l/∂y se conoce de acuerdo con la regla de la cadena. De acuerdo con la definición de la capa completamente conectada, debe ser un vector (columna) de M-dimensional. De acuerdo con la regla de derivación del cálculo matricial, podemos obtener:

∂b∂l​∂W∂l​∂x∂l​​=∂y∂l​⋅∂b∂y​=∂y∂l​=∂y∂l​⋅∂W∂y​=x×( ∂y∂l​)T=∂y∂l​⋅∂x∂y​=W×∂y∂l​​

Implementación de retropropagación de capa totalmente conectada

El entrenamiento amplía la clase definida en el entrenamiento anterior FullyConnected, el entrenamiento ya ha dado forward(x)la implementación, y se ha modificado para satisfacer las necesidades de backpropagation. Debe implementar la función de retropropagación de esta clase backward(dout), doutque es el gradiente de la función de pérdida en relación con la salida de la capa totalmente conectada, es decir, ∂y∂l​ en la fórmula anterior, que es una forma de (B, M) numpy.ndarray, y M es la capa completamente conectada el número de canales de salida. Durante la propagación hacia adelante, debido a que la forma de la entrada de la capa totalmente conectada se puede cambiar y registrar en self.original_x_shape, una vez que se complete el cálculo, restaure el gradiente de la entrada a la forma original. La entrada a la capa completamente conectada se documenta en self.x. Durante la retropropagación, almacene los gradientes de self.Wy en y devuelva los gradientes de , respectivamente .self.bself.dWself.dbx

requisitos de programación

De acuerdo con el indicador, agregue el código entre Begin y End del editor a la derecha para realizar la retropropagación de la capa completamente conectada.

instrucción de prueba

La plataforma probará el código que escriba. El método de prueba es: la plataforma generará aleatoriamente la entrada x, el peso W, el sesgo by el gradiente de salida dout, y luego creará una instancia de la clase de acuerdo con su código de implementación FullyConnected, y luego usará la instancia para realizar propagación hacia adelante primero Calcule y luego realice el cálculo de propagación hacia atrás. Sus respuestas se compararán con las respuestas estándar. Debido a que el cálculo de los números de punto flotante puede tener errores, siempre que el error entre su respuesta y la respuesta estándar no exceda 10−5.

Ejemplo de entrada:

 
 
  1. W:
  2. [[0.1, 0.2, 0.3],
  3. [0.4, 0.5, 0.6]]
  4. b:
  5. [0.1, 0.2, 0.3]
  6. x:
  7. [[1, 2],
  8. [3, 4]]
  9. dout:
  10. [[0.1, 0.2, 0.3],
  11. [0.4, 0.5, 0.6]]

Entonces el gradiente correspondiente es:

 
 
  1. dx:
  2. [[0.14 0.32]
  3. [0.32 0.77]]
  4. dW:
  5. [[1.3 1.7 2.1]
  6. [1.8 2.4 3. ]]
  7. db:
  8. [0.5 0.7 0.9]

Los resultados anteriores tienen errores de redondeo, que puede ignorar.


¡Comencemos tu misión, te deseo éxito!

Código de implementación: 

importar numpy como np

clase totalmente conectado:

    def __init__(self, W, b):

        r''''

        Inicialización de la capa completamente conectada.

        Parámetro:

        - W: numpy.array, (D_in, D_out)

        - b: numpy.array, (D_out)

        '''

        self.W = W

        self.b = b

        self.x = Ninguno

        self.original_x_shape = Ninguno

        self.dW = Ninguno

        self.db = Ninguno

    def adelante(auto, x):

        r''''

        El pase hacia adelante de la capa completamente conectada.

        Parámetro:

        - x: numpy.arreglo, (B, d1, d2, ..., dk)

        Devolver:

        - y: numpy.matriz, (B, M)

        '''

        self.original_x_shape = x.forma

        x = x.reforma(x.forma[0], -1)

        self.x = x

        out = np.dot(self.x, self.W) + self.b

        regresar

    def hacia atrás(self, dout):

        r''''

        Propagación hacia atrás de capas completamente conectadas

        Parámetro:

        - dout: numpy.array, (B, M)

        Devolver:

        - dx: numpy.array, (B, d1, d2, ..., dk) misma forma que self.original_x_shape

        Además, es necesario calcular los siguientes resultados:

        - self.dW: numpy.array, (N, M) misma forma que self.W

        - self.db: numpy.array, (M,)

        '''

        ########## Comenzar ##########

        dx = np.dot(dout, self.WT)

        self.dW = np.dot(self.xT, dout)

        self.db = np.sum(dout, eje=0)

        dx = dx.reshape(*self.original_x_shape)

        volver dx

        ########## Fin ##########

Captura de pantalla del código:

Nivel 2: implementar la retropropagación de funciones de activación comunes

detalles de la misión

La tarea de este nivel: realizar la retropropagación de las funciones de activación comunes.

información relacionada

Para completar la tarea de este nivel, debe dominar: retropropagación de funciones de activación comunes.

Para conocer el contenido de esta capacitación, consulte el Capítulo 5.5 del libro "Introducción al aprendizaje profundo: teoría e implementación basada en Python".

Propagación hacia atrás de funciones de activación comunes

En el último paso, aprendimos sobre la retropropagación para capas completamente conectadas. En este pase, vamos un paso más allá y aprendemos sobre la retropropagación para funciones de activación de uso común. Como en el entrenamiento anterior, nos enfocamos principalmente en las dos funciones de activación de sigmoid y ReLU.

1. función de activación sigmoide

En el entrenamiento anterior, aprendimos la propagación directa de la función de activación sigmoidea:

y=sigmoide(x)=1/(1+e−x)

Debido a que la función de activación se calcula elemento por elemento, la retropropagación de la función de activación solo necesita resolverse de acuerdo con la regla de derivación de funciones:

∂x∂y​=(1−y)y

Para la función de activación sigmoidea, puede obtener:

∂x∂l​=∂y∂l​⋅∂x∂y​=∂y∂l​⋅(1−y)y

2. Función de activación ReLU

En el entrenamiento anterior, aprendimos la propagación directa de la función de activación de ReLU:

y=ReLU(x)=max(0,x)

Se puede ver que hay un punto no diferenciable x=0 en la función de activación de ReLU, y no se puede derivar directamente. En este punto, usamos el subgradiente de ReLU en ese punto:

∂x∂y​(0)=0

En cuanto al concepto de subgradiente, no lo introduciré en profundidad aquí, los estudiantes interesados ​​pueden leer libros relacionados. Después de introducir el subgradiente, el gradiente de la función de activación de ReLU se puede expresar completamente como:

∂x∂y​={0,x≤01,x>0​

Combinado con la fórmula de retropropagación anterior, se puede obtener el método de cálculo de retropropagación de la función de activación ReLU.

Implementación de la función de activación común backpropagation

Para la función de activación sigmoidea, el entrenamiento expande la clase definida en el entrenamiento anterior Sigmoid, el entrenamiento ha dado forward(x)la implementación y se ha modificado para satisfacer las necesidades de backpropagation. Debe implementar la función de retropropagación de esta clase backward(dout), doutque es el gradiente de la función de pérdida en relación con la salida sigmoide, es decir, ∂y∂l​ en la fórmula anterior, que tiene la xmisma forma que la entrada numpy.ndarray. La salida del pase hacia adelante se registra en self.out, para que pueda realizar los cálculos de propagación hacia atrás convenientemente. backward(dout)La función necesita devolver xel gradiente de la entrada.

Para la función de activación de ReLU, el entrenamiento amplía la clase definida en el entrenamiento anterior ReLU, el entrenamiento ya ha dado forward(x)la implementación y se ha modificado para satisfacer las necesidades de propagación hacia atrás. Debe implementar la función de retropropagación de esta clase backward(dout), doutque es el gradiente de la función de pérdida en relación con la salida sigmoide, es decir, ∂y∂l​ en la fórmula anterior, que tiene la xmisma forma que la entrada numpy.ndarray. self.maskRegistra si cada entrada es menor o igual a 0 durante la propagación directa, para facilitar el cálculo de la dirección de propagación. backward(dout)La función necesita devolver xel gradiente de la entrada.

requisitos de programación

De acuerdo con el aviso, agregue el código entre Begin y End del editor a la derecha para realizar la retropropagación de la función de activación anterior.

instrucción de prueba

La plataforma probará el código que escriba. El método de prueba es: la plataforma generará aleatoriamente xgradientes de entrada y salida , y luego creará una instancia de / class doutde acuerdo con su implementación , y luego usará esta instancia para realizar cálculos de propagación hacia adelante, y luego Cálculos de diferencial inverso. Sus respuestas se compararán con las respuestas estándar. Debido a que el cálculo de los números de punto flotante puede tener errores, siempre que el error entre su respuesta y la respuesta estándar no exceda 10−5.SigmoidReLU

Ejemplo de entrada:

 
 
  1. # 对于sigmoid激活函数:
  2. x:
  3. [[-1, 0, 1]]
  4. dout:
  5. [[1, 2, 3]]
  6. #对于ReLU激活函数:
  7. x:
  8. [[-1, 0, 1]]
  9. dout:
  10. [[1, 2, 3]]

Entonces el gradiente correspondiente es:

 
 
  1. # 对于sigmoid激活函数:
  2. dx:
  3. [[0.20, 0.50, 0.59]]
  4. #对于ReLU激活函数:
  5. dx:
  6. [0, 2, 3]

Los resultados anteriores tienen errores de redondeo, que puede ignorar.


¡Comencemos tu misión, te deseo éxito!

Código de implementación:

importar numpy como np


 

clase sigmoide:

    def __init__(uno mismo):

        self.out = Ninguno

    def adelante(auto, x):

        r''''

        Propagación hacia adelante de la función de activación sigmoidea.

        Parámetro:

        - x: numpy.arreglo, (B, d1, d2, ..., dk)

        Devolver:

        - y: numpy.arreglo, (B, d1, d2, ..., dk)

        '''

        salida = 1. / (1. + np.exp(-x))

        self.fuera = fuera

        regresar

    def hacia atrás(self, dout):

        r''''

        Retropropagación del sigmoide

        Parámetro:

        - dout: numpy.array, (B, d1, d2, ..., dk)

        Devolver:

        - dx: numpy.array, (B, d1, d2, ..., dk)

        '''

        ########## Comenzar ##########

        dx = dout * (1.0 - self.out) * self.out

        volver dx

        ########## Fin ##########


 

clase Relu:

    def __init__(uno mismo):

        self.mask = Ninguno

    def adelante(auto, x):

        r''''

        Propagación directa de la función de activación de ReLU.

        Parámetro:

        - x: numpy.arreglo, (B, d1, d2, ..., dk)

        Devolver:

        - y: numpy.arreglo, (B, d1, d2, ..., dk)

        '''

        self.máscara = (x <= 0)

        fuera = x.copiar()

        fuera[self.mask] = 0

        regresar

    def hacia atrás(self, dout):

        r''''

        Retropropagación de relu

        Parámetro:

        - dout: numpy.array, (B, d1, d2, ..., dk)

        Devolver:

        - dx: numpy.array, (B, d1, d2, ..., dk)

        '''

        ########## Comenzar ##########

        dout[self.máscara] = 0

        dx = salida

        volver dx

        ########## Fin ##########

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_57409899/article/details/124616038
Recomendado
Clasificación