Aprendizaje Profundo - Principios Básicos de Redes Neuronales y Redes Neuronales Recurrentes

Propagación hacia adelante (hacia adelante)

¿Por qué hay una función de activación?

Aquí, se utilizan dos capas para representar una red neuronal multicapa como ejemplo: la salida de la primera capa es la entrada de la segunda capa, donde la matriz W*X multiplicación de MM, y ADD es la suma de vectores que es agregar sesgo Si cada capa tiene solo una transformación lineal, entonces no importa cuántas capas haya al final, se puede reducir a una capa (consulte la fórmula en el lado izquierdo de la figura anterior), por lo que la cantidad de capas no tiene sentido .

cadena de reglas 

Propagación hacia atrás (hacia atrás) 

  

Cuando x es la salida de la capa anterior, también se debe calcular, en este momento, es equivalente a la salida z de la capa anterior.

La derivada parcial de la pérdida L a z se pasa de la propagación hacia atrás, y la derivada parcial de z a x es el gradiente local calculado cuando se calcula la función f durante la propagación directa.

Aquí hay un ejemplo específico:

Por ejemplo, en la propagación directa, la función f=x*w, entonces la derivada parcial de z a x es w, y la derivada parcial de z a w es x. Cuando se pasan x=2 y w=3, se emite z=x*w=6.

Luego, en retropropagación, obtenemos la pérdida Loss, calculamos la derivada parcial de L a z como 5 y luego calculamos la derivada parcial de L a x como 5 * w, es decir, 5 * 3 = 15. De manera similar, la derivada parcial de L a w es 10, y luego continuamos pasando el resultado de la derivada parcial de L a x a la capa superior, de modo que cada capa pueda actualizar el peso w a través de la derivada parcial de w.

Lo anterior es el proceso general de avance y retroceso.Después de calcular la derivada parcial de la pérdida de w, el algoritmo de descenso de gradiente se puede usar para actualizar w.

Lo anterior es la derivación de la fórmula del algoritmo de descenso de gradiente.

Lo anterior es la fórmula del algoritmo de descenso de gradiente estocástico. 

demostración de código:

Redes neuronales recurrentes (RNN)

En general, las redes neuronales no pueden manejar datos con una relación de secuencia. Por ejemplo, use una red neuronal convolucional para una imagen y luego emita la categoría de la imagen. Esta salida solo está relacionada con la imagen de entrada y no tiene nada que ver con la imagen de entrada anterior. Estos son datos sin una relación de secuencia. Por ejemplo, al igual que el lenguaje natural , existe una relación contextual obvia entre palabras y oraciones, y es necesario utilizar una red neuronal recurrente para procesarla.

La celda RNN es una capa de transformación lineal. Las cuatro celdas RNN en el lado derecho de la figura de arriba se refieren a la misma celda RNN, donde h también se denomina oculta . Cada entrada se coloca en la celda RNN junto x_{yo}con la salida anterior , y luego se obtendrán los datos de la siguiente secuencia junto con ella. Esto sigue y sigue, de modo que cada entrada combina los resultados de la secuencia anterior , lo que refleja la relación de secuencia entre los datos.h_{i-1}Hola}x_{i+1}Hola}h_{yo+1}

Por ejemplo, hay tres capas en la figura anterior, la celda RNN de la primera capa recibe los datos originales x y la salida h de la secuencia anterior, la celda RNN de la segunda capa recibe la salida h de la secuencia de la capa anterior y la salida h de la secuencia anterior, la tercera capa es igual a la segunda capa, y así sucesivamente.

Ejemplo de práctica

Aquí se requiere aprender la ley de hello->ohlol, donde Seq es la abreviatura de secuencia.

Código de implementación concreto 

import torch

input_size = 4
hidden_size = 3
batch_size = 1

#构建输入输出字典
idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [2, 0, 1, 2, 1]
# y_data = [3, 1, 2, 2, 3]
one_hot_lookup = [[1, 0, 0, 0],
                  [0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 0, 0, 1]]
#构造独热向量,此时向量维度为(SeqLen*InputSize)
x_one_hot = [one_hot_lookup[x] for x in x_data]
#view(-1……)保留原始SeqLen,并添加batch_size,input_size两个维度
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
#将labels转换为(SeqLen*1)的维度
labels = torch.LongTensor(y_data).view(-1, 1)

class Model(torch.nn.Module):
    def __init__(self, input_size, hidden_size, batch_size):
        super(Model, self).__init__()
        self.batch_size = batch_size
        self.input_size = input_size
        self.hidden_size = hidden_size

        self.rnncell = torch.nn.RNNCell(input_size = self.input_size,
                                        hidden_size = self.hidden_size)

    def forward(self, input, hidden):
        # RNNCell input = (batchsize*inputsize)
        # RNNCell hidden = (batchsize*hiddensize)
        hidden = self.rnncell(input, hidden)
        return hidden

    #初始化零向量作为h0,只有此处用到batch_size
    def init_hidden(self):
        return torch.zeros(self.batch_size, self.hidden_size)

net = Model(input_size, hidden_size, batch_size)

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)

for epoch in range(15):
    #损失及梯度置0,创建前置条件h0
    loss = 0
    optimizer.zero_grad()
    hidden = net.init_hidden()

    print("Predicted string: ",end="")
    #inputs=(seqLen*batchsize*input_size) labels = (seqLen*1)
    #input是按序列取的inputs元素(batchsize*inputsize)
    #label是按序列去的labels元素(1)
    for input, label in zip(inputs, labels):
        hidden = net(input, hidden)
        #序列的每一项损失都需要累加
        loss += criterion(hidden, label)
        #多分类取最大
        _, idx = hidden.max(dim=1)
        print(idx2char_2[idx.item()], end='')

    loss.backward()
    optimizer.step()

    print(", Epoch [%d/15] loss = %.4f" % (epoch+1, loss.item()))

Supongo que te gusta

Origin blog.csdn.net/weixin_61725823/article/details/130568173
Recomendado
Clasificación