长短期记忆网络 LSTM
为什么需要 LSTM (Long short-term memory)
普通 RNN 的信息不能长久传播(存在于理论上)—原因是针对结尾较远的信息被稀释的比较厉害
引入选择性机制(门机制)
选择性输入
选择性遗忘
选择性输出
选择性机制实现的原理 ——> 门:Sigmoid 函数: [0,1]
LSTM(长短时记忆) 是一种循环神经网络, 具有门控结构, 用于处理序列数据。其运算过程可以概括为以下几个步骤:
- 输入门(Input Gate) : 计算当前输入和前一时刻的输出是否应该被记忆。
- 遗忘门(Forget Gate) : 决定前一时刻输出, 结合当前的输入, 哪些记忆是否被保留。
- 记忆单元(Memory Cell) : 根据输入门和遗忘门的结果更新记忆状态。
- 输出门(Output Gate) : 基于当前输入和记忆状态计算当前时刻的输出。
https://blog.csdn.net/weixin_44162104/article/details/88660003
LSTM 图示
以下图来进行理解:
- 遗忘门:用于使用sigmoid,取值在(0,1),删去Ct-1中的取值为0的元素,相当于选择性遗忘了部分记忆
- 输入门:第一部份进行选择,然后使用tanh,取值在(-1,1),不是遗忘而是进行梳理归纳,并写入C中
- Ct=f1 * Ct-1 + f2:先相乘再相加,更新了Ct。用于传递以及更新St等到Yt
- 可以理解为在短期记忆的RNN上(St这条竖线),加上了一个长期记忆的节点(Ct这条竖线线)中间的交互即为,遗忘门和输入门。负责删去和写入内容。并对Yt进行影响

对应的图示:

LSTM 公式


- 从上面公式可以看出, 参数量是 rnn 的 4 倍
- Ht-1 和 xt 拼接是直接加起来的
- LSTM的计算过程,权重参数数目,weight_ih_l0,weight_hh_l0
- 源码 lstm 是继承 rnn 实现的
- RNN 没有细胞状态; LSTM 通过细胞状态记忆信息。RNN 激活函数只有 tanh; LSTM 通过输入门、 遗忘门、 输出门引入 sigmoid 函数并结合 tanh 函数, 添加求和操作, 减少梯度消失和梯度爆炸的可能性。RNN 只能够处理短期依赖问题; LSTM 既能够处理短期依赖问题, 又能够处理长期依赖问题。
文本分类
- 代码和RNN相同,只是在nn.RNN改为nn.LSTM。embedding_dim和hidden_dim和RNN一样。
- 参数量是 RNN 的 4 倍:对应的四个W[ht-1,xt] (4x16x64)(4x64x64) 和 四个b
让我们来解析这些参数的数量和计算方式:
embedding.weight:
vocab_size 是词汇表大小。
embedding_dim 是嵌入维度。
参数量为 vocab_size * embedding_dim
lstm.weight_ih_l0 和 lstm.weight_hh_l0:
- embedding_dim 是输入维度。
- hidden_dim 是 LSTM 隐藏层的维度。
- 对于单向 LSTM:
- weight_ih 是输入到隐藏层的权重, 大小为 (4 * hidden_dim, embedding_dim)。
- weight_hh 是隐藏层到隐藏层的权重, 大小为 (4 * hidden_dim, hidden_dim)。
- 对于双向 LSTM:
- weight_ih 是输入到隐藏层的权重, 大小为 (4 * hidden_dim, embedding_dim)。
- weight_hh 是隐藏层到隐藏层的权重, 大小为 (4 * hidden_dim, hidden_dim)。
- 参数量计算为 (4 * hidden_dim * (embedding_dim + hidden_dim))。
lstm.bias_ih_l0 和 lstm.bias_hh_l0:
- LSTM 层的偏置参数。
- 对于单向 LSTM, 每个都有 4 * hidden_dim 个参数。
- 对于双向 LSTM, 每个都有 8 * hidden_dim 个参数。
- 参数量计算为 4 * hidden_dim 或 8 * hidden_dim。
layer.weight:
- 将隐藏状态维度从 hidden_dim * (2 if bidirectional else 1) 转换为 hidden_dim。
- 参数量计算为 hidden_dim * hidden_dim。
layer.bias:
- 线性层的偏置参数。
- 参数量计算为 hidden_dim。
fc.weight:
- 输入维度是 hidden_dim, 输出维度是 1。
- 参数量计算为 hidden_dim * 1 = hidden_dim。
fc.bias:
- 输出层的偏置参数。
- 参数量计算为 1
根据提供的参数数量和上述计算方式:
- embedding.weight: vocab_size * embedding_dim = 10000 * 16 = 160000。
- lstm.weight_ih_l0 和 lstm.weight_hh_l0 : 4 * hidden_dim * (embedding_dim + hidden_dim), 即 4 * 64 * 16 = 4096 和 4 * 64 * 64 = 16384。
- lstm.bias_ih_l0 和 lstm.bias_hh_l0: 4 * hidden_dim = 256。
- layer.weight: hidden_dim * hidden_dim = 64 * 64 = 4096。
- layer.bias: hidden_dim = 64。
- fc.weight: hidden_dim = 64。
- fc.bias: 1。
代码
准备数据
1 | from tensorflow import keras |
构造 word2idx 和 idx2word
1 | word2idx = {word: idx + 3 for word, idx in word_index.items()} |
Tokenizer
1 | class Tokenizer: |
数据集与 DataLoader
1 | from torch.utils.data import Dataset, DataLoader |
定义模型
1 | class LSTM(nn.Module): |

训练
1 | from sklearn.metrics import accuracy_score |