[Aprendizaje profundo] Directrices básicas de retropropagación

En realidad, esta es una pregunta que siempre quise registrar. Encontré una descripción fácil de entender en el libro "Red neuronal simple y profunda y aprendizaje profundo". Combinado con la rutina ejecutada recientemente, repasémosla intuitivamente.

En la introducción de muchos libros, la retropropagación en el aprendizaje profundo se considera una caja negra. Los usuarios solo necesitan saber que la retropropagación se puede utilizar para actualizar los pesos para entrenar la red. Pero la esencia del mecanismo básico de este tipo de entrenamiento en realidad constituye una interpretación de la red neuronal en sí , y esta interpretación es precisamente la clave para comprender la aplicabilidad y escalabilidad de la red neuronal, por lo que este artículo decide ampliarla.


Estructura de red y definición de parámetros.


Antes de derivar el mecanismo de retropropagación específico, primero se da la definición de la estructura de la red .

Tomemos como ejemplo una estructura de red simple de tres niveles. La primera capa es la capa de entrada , aquí se supone que hay tres neuronas de entrada; la segunda capa es la capa oculta (o capa intermedia), lo que significa que la red está realizando operaciones de extracción de características más complejas, las llamadas profundas. red, es decir, hay múltiples capas ocultas La red neuronal, la profundización de la red mejorará su capacidad de expresión no lineal; la tercera capa es la capa de salida , donde los dos valores de activación de salida compararán la función de costo de entrada con la valor esperado y generar el resultado del error.

inserte la descripción de la imagen aquí

En el modelo de perceptrón de la sección anterior , ya conocemos el peso de la conexión ww.w , sesgobbb y la función de activaciónσ \sigmaEl valor de activación aacorrespondiente a σLas ecuaciones básicas formadas por a . Para las redes neuronales compuestas por perceptrones multicapa, esta ecuación para un solo nodo sigue siendo la misma. Usando forma vectorial, expresaremos de manera más concisala generación de valores de activación de una determinada capa:

al = σ ( wlal − 1 + bl ) que define la entrada ponderada zl = wlal − 1 + bl a_{l} = \sigma(w^{l} a^{l-1} + b^{l}) \ \ \ \ Que define la entrada ponderada \ \ z^{l} =w^{l} a^{l-1} + b^{l}ayo=s ( wlal - 1+bl )donde se define la entrada ponderadaz      yo=wlal - 1+byo

Es decir: el producto escalar del peso de conexión entre capas y el valor de activación de la capa superior más el sesgo de esta capa obtendrá la entrada ponderada zlz^{l} de esta capazl , y la entrada ponderada pasa a través de la función de activación para obtener el valor de activación de la capa.


Complementar una operación matricial símbolo producto de Adamar o producto de Schur ⊙ \odot , lo que posteriormente simplifica la escritura de la ecuación.

asumiendo sss yttt son dos vectores con la misma dimensión, entoncess ⊙ ts \odot tst representa el producto por elementos, es decir( s ⊙ t ) j = sjtj (s \odot t)_{j} = s_j t_{j}( st )j=sjtj

Los ejemplos son los siguientes:

[ 1 2 ] ⊙ [ 3 4 ] = [ 1 ∗ 3 2 ∗ 4 ] = [ 3 8 ] \begin{bmatrix} 1 \\ 2 \end{bmatrix} \odot \begin{bmatrix} 3 \\ 4 \end {bmatrix} = \begin{bmatrix} 1*3 \\ 2*4 \end{bmatrix} = \begin{bmatrix} 3 \\ 8 \end{bmatrix}[12][34]=[1324]=[38]


derivación de la ecuación


De hecho, la retropropagación considera cómo cambiar el peso y el sesgo para controlar la función de costos . Su significado último es calcular la derivada parcial ∂ C / ∂ wjkl \partial C / \partial w_{jk}^{l}C / wjkyo∂ C / ∂ bjl \partial C / \partial b_{j}^{l}C / segundojyo. Una comprensión esclarecedora: ∂ C / ∂ zjl \partial C / \partial z_{j}^{l}∂C / ∂z _ _jyoes una medida del error neuronal (aquí elija zjl z_{j}^lzjyoLa expresión error es una simplificación de la forma de ecuación posterior), es decir, la definición de lll capajjError δ jl \delta _{j}^{l} en j neuronasdjyoDefinición:
δ jl ≡ ∂ C ∂ zjl \delta_{j}^{l} \equiv \frac{\partial C}{\partial z_{j}^{l}}djyozjyo∂C _

Por convención, utilice δ l \delta^{l}dl significa lo mismo que lallEl vector de error asociado con la capa l . Cada capa de δ l \delta^{l}se puede calcular mediante retropropagacióndl y luego compare estos errores con la cantidad real requerida∂ C / ∂ wjkl \partial C / \partial w_{jk}^{l}C / wjkyo∂ C / ∂ bjl \partial C / \partial b_{j}^{l}C / segundojyoconectar.

Antes de comenzar el proceso de prueba, primero proporcione cuatro fórmulas sobre la ecuación de retropropagación , de la siguiente manera:


Resumen: ecuación de retropropagación

δ L = ∇ a C ⊙ σ ′ ( z L ) error de capa de salida ( 1 ) \delta^{L} = \nabla_{a} C \odot \sigma^{\prime}(z^{L}) \qquad \qquad error de capa de salida \qquad (1)dl=unCpag (zl )error de capa de salida( 1 )

δ l = ( ( wl + 1 ) T δ l + 1 ) ⊙ σ ′ ( zl ) Error de transmisión de la capa frontal ( 2 ) \delta^{l} = ((w^{l+1})^{T} \ delta ^{l+1}) \odot \sigma ^{\prime}(z^{l}) \qquad \qquad Error de transferencia de capa frontal\qquad (2)dyo=(( wl + 1 )T δl + 1 )pag (zl )error de pase frontal( 2 )

∂ C ∂ bjl = tasa de cambio del sesgo δ jl ( 3 ) \frac{\partial C}{\partial b_{j}^{l}} = \delta_{j}^{l} \qquad \qquad sesgo El tasa de cambio\qquad (3)segundojyo∂C _=djyoTasa de cambio de sesgo( 3 )

∂ C ∂ wjkl = akl − 1 δ jl tasa de cambio de peso ( 4 ) \frac{\partial C}{ \partial w_{jk}^{l}} = a_{k}^{l-1}\delta_{ j }^{l} \qquad tasa de cambio de pesos\qquad (4)wjkyo∂C _=akl - 1djyotasa de cambio de peso( 4 )


Comencemos a demostrarlo uno por uno. Recuerde la regla central de la cadena de cálculo multivariante .


(1) Error de la capa de salida

Para el error de la capa de salida, se define como:
δ j L = ∂ C ∂ zj L \delta_{j}^{L} = \frac{\partial C}{\partial z_{j}^{L}}djL=zjL∂C _
Entre ellos, L es el número de capas de la red, lo que significa que este es el error en la j-ésima neurona de la capa de salida . De hecho, podemos reescribir la derivada parcial anterior en términos de la derivada parcial del valor de activación de salida, es decir,
δ j L = ∑ k ∂ C ∂ ak L ∂ ak L ∂ zj L \delta_{j}^{L } =\sum_ {k} \frac{\partial C}{\partial a_{k}^{L}} \frac{\partial a_{k}^{L}}{\partial z_{j}^{L }}djL=kunkL∂C _zjLunkL
donde la suma se realiza en todas las neuronas de la capa de salida. Por supuesto, el kkEl valor de activación de salida de k neuronasak L a_{k}^{L}akLsolo depende de k = jk =jk=El peso de entrada zj de la j-ésima neurona en el momento j L z_{j}^{L}zjL, entonces cuando k ≠ jk \ne jk=j∂ ak L / ∂ zj L \partial a_{k}^{L}/ \partial z_{j}^{L}unkL/ ∂z _jLNo existe (es decir, ningún impacto es 0). Por lo tanto, la ecuación se puede reducir a
δ j L = ∂ C ∂ aj L ∂ aj L ∂ zj L \delta_{j}^{L} =\frac{\partial C}{\partial a_{j}^{L } } \frac{\partial a_{j}^{L}}{\partial z_{j}^{L}}djL=unjL∂C _zjLunjL
Esto muestra que el error de la neurona solo está relacionado con la derivada parcial de la función de pérdida con el valor de activación de la neurona y la derivada parcial del valor de activación con la entrada ponderada de la neurona (es decir, el valor de la derivada de la función de activación en este punto). Basado en aj L = σ ( zj L ) a_{j}^{L} = \sigma (z_{j}^{L})ajL=s ( zjL) , el segundo elemento de la derecha se puede escribir como
σ j L = ∂ C ∂ aj L σ ′ ( zj L ) \sigma_{j}^{L}= \frac{ \partial{C} }{\partial a_ {j} ^{L}} \sigma^{\prime}(z_{j}^{L})pagjL=unjL∂C _pag (zjL)
Extienda la fórmula anterior a cada neurona en la capa de salida y use el producto de Hadamard para expresar, puede obtener la forma de la fórmula (1), es decir,
δ L = ∇ a C ⊙ σ ′ ( z L ) \delta ^{L} = \nabla_{a} C \odot \sigma^{\prime}(z^{L})dl=unCpag (zl )


(2) Error de transferencia de la capa frontal

Esta debería ser la fórmula que mejor explique el significado de la palabra "inverso" en el algoritmo de retropropagación, es decir, el error se pasa de atrás hacia adelante. Específicamente, la consideración es utilizar la siguiente capa de error δ l + 1 \delta^{l+1}dl + 1 para representar el errorδ l \delta^{l}dyo . De manera similar, usamosδ kl + 1 = ∂ C / ∂ zkl + 1 \delta^{l+1}_{k} = \partial{C} / \partial z_{k}^{l+1}dkl + 1=∂C / ∂z _ _kl + 1重写δ jl = ∂ C / ∂ zjl \delta^{l}_{j} = \partial{C} / \partial z_{j}^{l}djyo=∂C / ∂z _ _jyoSea
δ jl = ∂ C ∂ zjl = ∑ k ∂ C ∂ zkl + 1 ∂ zkl + 1 ∂ zjl = ∑ k ∂ zkl + 1 ∂ z jl δ kl + 1 \begin{aligned } \delta_j^l &=\frac {\partial C}{\partial z_j^l} \\ &=\sum_k \frac{\partial C}{\partial z_k^{l+1}} \frac{\partial z_k^{l+1}}{ \partial z_j^l} \\ &=\sum_k \frac{\partial z_k^{l+1}}{\partial z_j^l} \delta_k^{l+1}\ end{aligned}djyo=zjyo∂C _=kzkl + 1∂C _zjyozkl + 1=kzjyozkl + 1dkl + 1
La última línea intercambia los dos términos de la derecha y sustituye δ kl + 1 \delta_{k}^{l+1}dkl + 1La definición de realiza correspondientemente la sustitución del error de la capa inferior. Para evaluar la última fila, expanda
zkl + 1 = ∑ jwkjl + 1 ajl + bkl + 1 = ∑ jwkjl + 1 σ ( zjl ) + bkl + 1 z_k^{l+1}=\sum_j w_{kj}^{ l +1} a_j^l+b_k^{l+1}=\sum_j w_{kj}^{l+1} \sigma\left(z_j^l\right)+b_k^{l+1}zkl + 1=jwkjl + 1ajyo+bkl + 1=jwkjl + 1pag( zjyo)+bkl + 1
Diferenciarlo para obtener
∂ zkl + 1 ∂ zjl = wkjl + 1 σ ′ ( zjl ) \frac{\partial z_k^{l+1}}{\partial z_j^l}=w_{kj}^{l+ 1} \ sigma^{\prime}\left(z_j^l\right)zjyozkl + 1=wkjl + 1pag( zjyo)
volviendo a la fórmula original, habrá
δ jl = ∑ kwkjl + 1 δ kl + 1 σ ′ ( zjl ) \delta_j^l=\sum_k w_{kj}^{l+1} \delta_k^ {l+1 } \sigma^{\prime}\left(z_j^l\right)djyo=kwkjl + 1dkl + 1pag( zjyo)
Esta es también la forma componente de (2). Después de introducir el operador del producto Hadamard, se puede escribir la forma vectorial de transferir el error de la capa posterior a la capa frontal, es decir, δ l = ((wl + 1) T δ l +
1 ) ⊙ σ ′ ( zl ) \delta^{l} = ((w^{l+1})^{T} \delta ^{l+1}) \odot \sigma ^{\prime }(z^{ l})dyo=(( wl + 1 )T δl + 1 )pag (zl )


(3) Tasa de cambio de sesgo

De manera similar a las demostraciones de los dos pasos anteriores, podemos imaginar que la demostración en este momento todavía se desarrolla aplicando la regla de la cadena. Considerando
δ jl = ∂ C ∂ zjl = ∂ C ∂ bjl ∂ bjl ∂ zjl \delta_j^l = \frac{\partial C}{\partial z_j^l} = \frac{\partial C}{\partial b_j^ l } \frac{\b_j^l parcial}{\z_j^l parcial}djyo=zjyo∂C _=segundojyo∂C _zjyosegundojyo
Entre ellos, zjl z_{j}^{l} puede serzjyo展开
zjl = ∑ kwjklakl − 1 + bjl z_j^{l}=\sum_k w_{jk}^{l} a_k^{l-1}+b_j^{l}zjyo=kwjkyoakl - 1+bjyo
Ambos lados miran a bjl b_{j}^{l} al mismo tiempobjyoEncuentra la derivada parcial, porque wjkl w_{jk}^{l}wjkyocon bjl b_{j}^{l}bjyoirrelevante, porque cada una es una variable que puede cambiar libremente. Entonces
∂ zjl ∂ bjl = 1 \frac{\partial z_{j}^{l}}{\partial b_{j}^{l}} = 1segundojyozjyo=1
Luego, está la prueba de (3).
∂ C ∂ bjl = δ jl \frac{\partial C}{\partial b_j^l} = \delta_j^lsegundojyo∂C _=djyo


(4) Tasa de cambio de peso

De manera similar a la prueba en (3), tenemos
δ jl = ∂ C ∂ zjl = ∂ C ∂ wjkl ∂ wjkl ∂ zjl \delta_j^l = \frac{\partial C}{\partial z_j^l} = \frac{ \ parcial C}{\partial w_{jk}^{l}} \frac{\partial w_{jk}^{l}}{\partial z_j^l}djyo=zjyo∂C _=wjkyo∂C _zjyowjkyo
Igual que arriba, General zkl z_{k}^{l}zkyo展开
zjl = ∑ kwjklakl − 1 + bjl z_j^{l}=\sum_k w_{jk}^{l} a_k^{l-1}+b_j^{l}zjyo=kwjkyoakl - 1+bjyo
Ambos lados al mismo tiempo para wjkl w_{jk}^{l}wjkyoEncuentre la derivada parcial, wjkl w_{jk}^{l}wjkyoNo sólo con bjl b_{j}^{l}bjyono tiene nada que ver con otros pesos, sino solo consigo mismo, por lo que tenemos:
∂ zjl ∂ wjkl = akl − 1 \frac{\partial z_{j}^{l}}{\partial w_{jk}^ {l} } = a_ {k} ^ {l-1}wjkyozjyo=akl - 1
Después de la transformación, hay una prueba de (4)
∂ C ∂ wjkl = akl − 1 δ jl \frac{\partial C}{ \partial w_{jk}^{l}} = a_{k}^{l- 1 }\delta_{j}^{l}wjkyo∂C _=akl - 1djyo

resumen

A través del proceso de prueba anterior, podemos ver fácilmente cómo devolvemos el error capa por capa a través del algoritmo de retropropagación y actualizamos los principios matemáticos de ponderaciones y sesgos.

Ahora volvemos a mirar la ecuación (1), y en su forma componente, miramos el término σ ′ ( zj L ) \sigma^{\prime}(z_{j}^{L})pag (zjL) . Mirando hacia atrás a la gráfica de la función sigmoidea, cuandoσ ( zj L ) \sigma (z_{j}^{L})s ( zjL) es aproximadamente 0 o 1, la función sigmoidea se vuelve muy suave, entoncesσ ′ ( zjl ) ≈ 0 \sigma^{\prime}(z_{j}^{l}) \approx 0pag (zjyo)0 . Por lo tanto, si la neurona de salida tiene un valor de activación pequeño (aproximadamente 0) o un valor de activación grande (aproximadamente 1), el aprendizaje de peso de la capa final será muy lento. En este momento, se puede decir que la neurona de salida está saturado, y el aprendizaje de pesotambién terminará (o aprenderá muy lentamente), y la neurona de salida estará sesgada de manera similar. Debido a que analizamos las ecuaciones (3) y (4), podemos encontrar que la actualización de ponderaciones y sesgos en realidad depende del error σ( zjl ) \sigma (z_{j}^{l})s ( zjyo) , y para la capa de salida, el error depende de la derivada de la función de activaciónσ ′ ( zj L ) \sigma^{\prime}(z_{j}^{L})pag (zjL) , por lo que en un estado saturado, el aprendizaje se vuelve difícil.

inserte la descripción de la imagen aquí

Miremos (2) finalmente, observemos el término σ ′ ( zjl ) \sigma^{\prime}(z_{j}^{l}) en (2)pag (zjyo) , lo que significa que el error se multiplicará por el valor derivado de una función de activación cuando se devuelva a la capa frontal. Para la función sigmoidea, podemos saber que el valor de la derivada está entre 0 y 1. Si el número de capas de la red es grande, cuando se propaga desde la capa de salida a la capa poco profunda, podemos saber que el error se reducirá. Muchas veces, el error eventualmente caerá a un nivel insignificante (cerca de 0), por lo que el aprendizaje superficial se volverá muy difícil, que es ella desaparición del gradiente.

Además, de acuerdo con el análisis en el escenario de saturación de neuronas de la capa de salida, la saturación de interneuronas también conducirá a δ jl \delta _{j}^{l}djyose vuelve pequeño porque σ ′ ( zjl ) \sigma^{\prime}(z_{j}^{l})pag (zjyo) es muy pequeño. Es decir:aprender lentamente ante cualquier entrada de peso a una neurona saturada.


La ecuación de retropropagación es válida para cualquier función de activación. La discusión sobre la función de costo se ignora aquí porque ese es otro contenido, pero se puede demostrar que la inferencia anterior en sí misma no tiene nada que ver con ninguna función de costo específica . Al mismo tiempo, es posible que tengamos nuevas ideas y que la función sigmoidea no sea adecuada como función de activación ideal en algunas aplicaciones. De hecho, diseñar una función de activación con propiedades de aprendizaje específicas es en realidad una parte importante de la red neuronal .


intenta observar

A continuación se muestra un ejemplo simple para ilustrar cómo observar específicamente la actualización iterativa de pesos en una red neuronal: este es un ejemplo del uso de una red neuronal para un ajuste no lineal.

Primero generamos una señal sinusoidal ruidosa (señal no lineal), de la siguiente manera:

x = torch.unsqueeze(torch.linspace(-np.pi, np.pi, 100), dim = 1) # 构建等差数列
y = torch.sin(x) + 0.5*torch.rand(x.size())  # 条件随机数

Luego definimos una estructura de red:

class Net(nn.Module):  # 定义类,存储网络结构
    def __init__(self):
        super(Net, self).__init__()
        self.predict = nn.Sequential(
            nn.Linear(1,10),  # 全连接层,1个输入,10个输出
            nn.ReLU(),  #ReLU激活函数
            nn.Linear(10,1)  # 全连接层,10个输入,1个输出
        )

La función de activación utilizada aquí es la función ReLU. En comparación con la función sigmoidea, ReLU no tiene el problema de la desaparición del gradiente en el intervalo positivo y la derivación de la función es relativamente simple . Es una función de activación comúnmente utilizada en las redes CNN.
inserte la descripción de la imagen aquí
Durante el entrenamiento, podemos obtener los pesos correspondientes a la capa completamente conectada llamando al módulo y atravesando las capas, el código correspondiente es el siguiente:

        # 输出权重变化,net.modules返回的是generator类型
        for layer in net.modules():
            if isinstance(layer, nn.Linear):
                print(layer.weight)

El código de todo el proceso es el siguiente:

# 这是一个用神经网络进行函数拟合的函数
import  numpy as np
import torch
import torch.nn as nn
import matplotlib.pyplot as plt

x = torch.unsqueeze(torch.linspace(-np.pi, np.pi, 100), dim = 1) # 构建等差数列
y = torch.sin(x) + 0.5*torch.rand(x.size())  # 条件随机数

class Net(nn.Module):  # 定义类,存储网络结构
    def __init__(self):
        super(Net, self).__init__()
        self.predict = nn.Sequential(
            nn.Linear(1,10),  # 全连接层,1个输入,10个输出
            nn.ReLU(),  #ReLU激活函数
            nn.Linear(10,1)  # 全连接层,10个输入,1个输出
        )

    def forward(self,x):  # 定义前向传播过程
        prediction = self.predict(x)  # 将x传入网络
        return prediction


net = Net()
optimizer = torch.optim.SGD(net.parameters(), lr = 0.05)  # 设置优化器
loss_func = nn.MSELoss()  # 设置损失函数
plt.ion()   # 打开交互模式

for epoch in range(1000):
    out = net(x)   # 实际输出
    loss = loss_func(out, y)  # 实际输出和期望输出传入损失函数
    optimizer.zero_grad()  # 清除梯度
    loss.backward()  # 误差反向传播

    optimizer.step()  # 优化器开始优化
    if epoch % 25 == 0:  # 每25epoch显示
        plt.cla()   # 清除上一次绘图
        plt.scatter(x,y)  # 绘制散点图

        # 输出权重变化,net.modules返回的是generator类型
        for layer in net.modules():
            if isinstance(layer, nn.Linear):
                print(layer.weight)

        plt.plot(x, out.data.numpy(), 'r', lw = 5 )  # 绘制曲线图
        plt.text(0, 0 , f'loss={
      
      loss}',fontdict={
    
    'size':20,'color':'red'})  #  添加文字来显示loss值

        plt.pause(0.1) # 显示时间0.1s

    plt.show()

plt.ioff()  # 关闭交互模式
plt.show()  # 定格显示最后结果

Puede ver el efecto de ajuste mostrado en tiempo real en la interfaz gráfica. A medida que el valor de pérdida disminuye, la red se ajustará gradualmente a la forma de la curva sinusoidal.Por favor agregue una descripción de la imagen.

También podemos ver los pesos de la red de salida en la consola. Aquí se toma como ejemplo el peso obtenido durante el último entrenamiento, se puede ver una matriz de pesos de 10×1 (1→10) y una matriz de pesos de 1×10 (10→1), que son diferentes a las anteriores. definición La estructura de red de las dos capas completamente conectadas es exactamente correspondiente.
inserte la descripción de la imagen aquí


Referencia:
"Red neuronal Python y aprendizaje profundo" Autor: [Australia] Michael Nielsen Traductor: Zhu Xiaohu Capítulo 2
"Introducción a la red neuronal Python y combate práctico" Autor: Wang Kai Capítulo 7

Supongo que te gusta

Origin blog.csdn.net/weixin_47305073/article/details/127680476
Recomendado
Clasificación