Модели рекуррентной нейронной сети (RNN), долговременной кратковременной памяти (LSTM) и (GRU)

глубокое обучение

Рекуррентная нейронная сеть (RNN)

image.pngРекуррентная нейронная сеть отличается от других нейронных сетей тем, что循环Два слова, цикл здесь относится к隐含的输出(v)Повторно введите неявные веса для участия в обучении модели,不同时刻的输入(X)Также поместите в скрытый слой веса. Неявный вес циклически повторяется в разные периоды времени, и его параметры различны, но неявный вес共用, обратите внимание, что на рисункеunfoldМатрица нижнего неявного веса просто一个矩阵(Объясняется позже здесь: как неявный вывод (v) и соответствующий ввод (x) совместно используют матрицу), причина, по которой их несколько, состоит в том, чтобы соответствовать разным моментам.

Прежде чем продолжить описание, необходимо решить проблему оптимизации, то есть разделить матрицу, здесь можно объяснить на простом примере: Для удобства понимания неявная переменная двумерная, а входная — одномерная, и цель — получить новый неявный вход, то есть двумерный.image.pngМы можем обнаружить, что весовые коэффициенты комбинируются рядом друг с другом, чтобы получить тот же результат. Это увеличивает возможности параллельной обработки.

Реализация исходного кода RNN

import torch.nn as nn

class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNN, self).__init__()

        self.hidden_size = hidden_size

        self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
        self.i2o = nn.Linear(input_size + hidden_size, output_size)
        self.softmax = nn.LogSoftmax(dim=1)

    def forward(self, input, hidden):
        combined = torch.cat((input, hidden), 1)
        hidden = self.i2h(combined)
        output = self.i2o(combined)
        output = self.softmax(output)
        return output, hidden

    def initHidden(self):
        return torch.zeros(1, self.hidden_size)

Характеристика рекуррентной нейронной сети заключается в том, что на каждом входе присутствует информация скрытого слоя предыдущего момента, а также仅仅是上一刻, Если вход нейронной сети связан не только с информацией последнего момента, другими словами, модель, которую необходимо обучить в текущий момент времени, также связана с информацией давно прошедшей давности, как позволить участвовать? Это требует введения сети с долговременной кратковременной памятью (LSTM), но прежде чем говорить о модели, статья, которая была опубликована и улучшена на этой основе, — это модель GRU, которую легче понять, чем модель LSTM.

модель ГРУ

Модель ГРУ должна обратить внимание на门控Роль , более определенно в формуле как权重проявление илиmaskЭффект. Нечего сказать, понимание этих четырех формул позволит понять модель ГРУ, так что ее будет легче понять, глядя на картинку.

Rt=о(XtWxr+Ht1Whr+br)Zt=о(XtWxz+Ht1Whz+bz)R_t = \sigma(X_tW_{xr}+H_{t-1}W_{hr}+b_r)\\ Z_t = \sigma(X_tW_{xz}+H_{t-1}W_{hz}+b_z)

вRtR_tНазываемый воротами сброса, он помогает захватить短期的依赖关系,ZtZ_tНазываемые воротами обновления, они помогают собирать данные временных рядов в长期的依赖关系. Его функция будет воплощена в следующей формуле.

Ht~=tanh(XtWxh+RtHt1Whh+bn)\tilde{H_{t}}=tanh(X_t W_{xh} + R_t \odot H_{t-1} W_{hh} + b_n)

Ht~\tilde{H_{t}}мы называем候选隐含状态, который в основном сохраняет кратковременную память. Зачем重置门может помочь зафиксировать краткосрочные зависимости в данных временных рядов, потому что он действует на上一个隐含状态Умножить на попарно. Мы можем решить, какую часть неявного состояния мы хотим сохранить в последний момент.RtR_tЧем больше значение, соответствующее измерению, тем больше информации сохраняет последнее скрытое состояние в этом измерении.

Ht=ZtHt1+(1Zt)Ht~H_t = Z_t \odot H_{t-1} + (1-Z_t)\odot \tilde{H_{t}}

В формулеZtZ_tВ качестве ворот обновления мы могли бы также взять крайний пример, на данный моментZtZ_tЕсли он равен 1, то независимо от того, сохраняется ли информация в последний момент, соответствующее состояние кандидата в кратковременную память равно нулю. Аналогично продолжаем往前递推, в предыдущий момент,ZtZ_tЕсли он равен 1, то сохраняется ли информация в предыдущий момент времени, и соответствующее состояние кандидата в кратковременную память также равно нулю. Таким образом, мы можем сохранить информацию, полученную давным-давно, поэтому шлюзы обновлений помогают фиксировать долгосрочные зависимости в данных временных рядов.

Тогда картинка ниже упрощает понимание.

image.png

реализация исходного кода

class GRUCell(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(GRUCell, self).__init__()
        self.hidden_size = hidden_size
        self.gate = nn.Linear(input_size + hidden_size, hidden_size)
        self.output = nn.Linear(hidden_size, output_size)
        self.sigmoid = nn.Sigmoid()
        self.tanh = nn.Tanh()
        self.softmax = nn.LogSoftmax(dim=1)

    def forward(self, input, hidden):
        combined = torch.cat((input, hidden), 1)        
        z_gate = self.sigmoid(self.gate(combined))
        r_gate = self.sigmoid(self.gate(combined))
        combined01 = torch.cat((input, torch.mul(hidden,r_gate)), 1)  
        h1_state = self.tanh(self.gate(combined01))
        
        h_state = torch.add(torch.mul((1-z_gate), hidden), torch.mul(h1_state, z_gate))
        output = self.output(h_state)
        output = self.softmax(output)
        return output, h_state

    def initHidden(self):
        return torch.zeros(1, self.hidden_size)  

Наконец, давайте посмотрим, что такого сложного для понимания в lstm.

Сеть с долговременной кратковременной памятью (lstm)

Понимая модель ГРУ, мы можем понять lstm непосредственно через формулу.

It=о(XtWxi+Ht1Whi+bi)Ft=о(XtWxf+Ht1Whf+bf)Ot=о(XtWxo+Ht1Who+bo)I_t = \sigma(X_tW_{xi}+H_{t-1}W_{hi}+b_i)\\ F_t = \sigma(X_tW_{xf}+H_{t-1}W_{hf}+b_f)\\ O_t = \sigma(X_tW_{xo}+H_{t-1}W_{ho}+b_o)\\

вItI_t,FtF_t,OtO_tЭто входные ворота, ворота забывания и выходные ворота.

Ct~=tanh(XtWxc+Ht1Whc+bc)\tilde{C_{t}}=tanh(X_t W_{xc} + H_{t-1} W_{hc} + b_c)

Ct~\tilde{C_{t}}в виде候选记忆细胞,主要用来保存短期记忆.

Ct=FtCt1+ItCt~C_{t}=F_t\odot C_{t-1} + I_t\odot \tilde{C_{t}}

CtC_{t}Для текущей ячейки памяти используйтеItI_t,FtF_tразмер, чтобы пойти衡量长期记忆和短期记忆孰多孰少. Способ понимания тот же, что и в ГРУ, ноZtZ_tи(1Zt)(1-Z_t)Заменено двумя вариативными формами.

Ht=Ottanh(Ct)H_t = O_t \odot tanh(C_t)

HtH_tтекущее скрытое состояние, гдеOtO_tВыбирать当前记忆细胞一部分到隐含状态, который отличается от GRU, не все идет на скрытый слой, поэтому более эффективно или гибко выводить на основе скрытого слоя или передавать его на следующий скрытый слой.

Давайте еще раз посмотрим на картинку

image.png

Реализация исходного кода:

import torch.nn as nn
import torch

class LSTMCell(nn.Module):
    def __init__(self, input_size, hidden_size, cell_size, output_size):
        super(LSTMCell, self).__init__()
        self.hidden_size = hidden_size
        self.cell_size = cell_size
        self.gate = nn.Linear(input_size + hidden_size, cell_size)
        self.output = nn.Linear(hidden_size, output_size)
        self.sigmoid = nn.Sigmoid()
        self.tanh = nn.Tanh()
        self.softmax = nn.LogSoftmax(dim=1)

    def forward(self, input, hidden, cell):
        combined = torch.cat((input, hidden), 1)
        f_gate = self.sigmoid(self.gate(combined))
        i_gate = self.sigmoid(self.gate(combined))
        o_gate = self.sigmoid(self.gate(combined))
        z_state = self.tanh(self.gate(combined))
        cell = torch.add(torch.mul(cell, f_gate), torch.mul(z_state, i_gate))
        hidden = torch.mul(self.tanh(cell), o_gate)
        output = self.output(hidden)
        output = self.softmax(output)
        return output, hidden, cell

    def initHidden(self):
        return torch.zeros(1, self.hidden_size)

    def initCell(self):
        return torch.zeros(1, self.cell_size)

использованная литература:
Глубокое обучение Python на основе pytorch
Практическое глубокое обучение

Если статья оказалась полезной, ставьте лайк~