RNN&LSTM

RNN&LSTM

  • RNN
  • LSTM
  • 双向LSTM
  • BiLSTM 的 pytorch 实现

RNN

RNN是循环神经网络的缩写。它是一种用于处理序列数据的神经网络。在标准的前馈神经网络中,输入数据从输入到输出逐层处理。相比之下,循环神经网络具有其架构中的循环,使其能够跨多个时间步长保持信息。

RNN的主要优点是能够处理顺序数据,例如时间序列、语音和自然语言文本。它们可以从输入数据中学习时间模式,并利用这些知识进行预测。RNN还可以用于生成序列,例如生成新的音乐或文本。

训练RNN的一个挑战是梯度消失问题,即用于更新权重的梯度信号随着时间反向传播变得非常小。这可能使网络难以学习输入数据中的长期依赖关系。为了解决这个问题,已经开发了几种RNN的变体,包括LSTM和GRU,它们使用门控机制选择性地更新隐藏状态,并根据需要保留或遗忘信息。

LSTM

LSTM(长短时记忆网络)是一种循环神经网络的变体,它在RNN的基础上做了一些结构上的改进。

传统的RNN在处理长序列数据时,由于梯度消失的问题,很难捕捉到长期的依赖关系。而LSTM通过引入一个称为“门”的机制来解决这个问题。这些门的作用是选择性地更新和遗忘之前的状态,并将新的信息合并到当前状态中。

LSTM包含三个门:输入门、输出门和遗忘门。输入门控制着新的信息是否应该被添加到当前状态中,输出门控制着当前状态中哪些信息应该传递给下一个时间步,遗忘门控制着以前的状态中哪些信息应该被遗忘。此外,LSTM还包含一个记忆单元,用于存储长期的状态信息,并通过门控制进行更新。

因此,LSTM相比于传统的RNN具有更强的记忆和长期依赖能力,能够更好地处理序列数据,并且在自然语言处理、语音识别、机器翻译等任务中表现出色。

双向LSTM

双向LSTM(Bidirectional LSTM)是在LSTM的基础上进行改进,它通过同时考虑序列的正向和反向信息来提高序列建模的能力。

传统的LSTM只考虑了当前时间步之前的信息,而双向LSTM则在当前时间步之前和之后都考虑了信息。具体来说,双向LSTM由两个独立的LSTM组成,一个LSTM沿着正向序列处理输入,另一个LSTM沿着反向序列处理输入。两个LSTM的输出在每个时间步上被连接起来,作为模型的最终输出。

在双向LSTM中,正向LSTM和反向LSTM的计算方式是一样的,只不过它们的输入序列是正序和反序的。假设输入序列为x(1), x(2), …, x(T),正向LSTM的输出序列为h(1), h(2), …, h(T),反向LSTM的输出序列为g(1), g(2), …, g(T)。则双向LSTM的输出序列y(1), y(2), …, y(T)为:

y(t) = W_h * [h(t); g(t)] + b

其中,[h(t); g(t)]表示h(t)和g(t)在维度上的连接,W_h和b是可训练的参数。这样,每个时间步上的输出y(t)就包含了当前时间步之前和之后的信息,能够更好地捕捉序列中的上下文关系。

双向LSTM在自然语言处理、语音识别、视频分析等领域都有广泛的应用。

BiLSTM 的 pytorch 实现

import torch
import torch.nn as nn

class BiLSTM(nn.Module):
    def __init__(self, input_dim, hidden_dim, num_layers, output_dim):
        super(BiLSTM, self).__init__()
        
        self.hidden_dim = hidden_dim
        self.num_layers = num_layers
        
        self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True, bidirectional=True)
        self.fc = nn.Linear(hidden_dim * 2, output_dim)
        
    def forward(self, x):
        h0 = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_dim).to(device=x.device) # 初始化正向LSTM的隐藏状态
        c0 = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_dim).to(device=x.device) # 初始化正向LSTM的细胞状态
        
        out, _ = self.lstm(x, (h0, c0)) # 正向LSTM的输出
        
        h0_back = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_dim).to(device=x.device) # 初始化反向LSTM的隐藏状态
        c0_back = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_dim).to(device=x.device) # 初始化反向LSTM的细胞状态
        
        out_back, _ = self.lstm(torch.flip(x, dims=[1]), (h0_back, c0_back)) # 反向LSTM的输出
        out_back = torch.flip(out_back, dims=[1]) # 将反向LSTM的输出翻转回来
        
        out = torch.cat((out, out_back), dim=2) # 将正向LSTM和反向LSTM的输出拼接起来
        out = self.fc(out) # 线性变换
        
        return out

在这个示例中,我们使用了PyTorch自带的LSTM层,并设置bidirectional=True以实现双向LSTM。在forward方法中,我们首先用正向LSTM处理输入序列,然后用反向LSTM处理反转后的输入序列,最后将两个LSTM的输出拼接起来,并通过一个线性层将其映射到指定的输出维度。

需要注意的是,这里我们将正向LSTM和反向LSTM的隐藏状态和细胞状态分别初始化为全0张量。这种初始化方式在实践中表现不错,但也可以使用其他初始化方法。另外,我们还需要将输入张量在序列维度上翻转,以便将其输入到反向LSTM中。

你可能感兴趣的:(rnn,lstm,深度学习)