您现在的位置是:首页 >技术交流 >RNNs GRUs & LSTMs网站首页技术交流

RNNs GRUs & LSTMs

时间很奇妙! 2025-06-18 12:01:05
简介RNNs GRUs & LSTMs

为什么需要序列模型

很多应用需要处理序列数据,下面举了很多例子,可能输入输出都是序列数据,也可能能只有输出或输入是序列数据,输入和输出可能是相同的长度,也可能不同。需要序列模型对序列数据进行处理。

Notation 符号

有一个词典之后,你可以给句子中每个单词用一个one-hot向量表示。

Recurrent neural network RNN模型

标准神经网络的局限性

上述经过编码的句子无法使用标准的深度神经网络进行处理,原因如下:

1. 在不同的训练数据中,输入输出的长度会不一致

2. 无法在文本的不同位置共享学习到的特征(这句话其实有点拗口,难于理解的,下面也贴一张DeepSeek的解释,可以学习完RNN之后再回头看看这句话是否更容易理解)

模型结构

如下图,左面是展开形式,右边是合并形式,展开形势更容易理解。

逐次将序列特征传入更新模型,可以看到一个缺点是顺序放入导致后面一个特征只能利用前序特征的信息,但是无法利用后续特征的信息,有BRNN会解决这个问题,不过这里先不展开。

前向传播

使用a^{<t-1>}x^{<t>}计算a^{<t>},再使用a^{<t>}计算y^{<t>}

其中计算a^{<t>}时使用的激活函数在RNN里面通常是tanh,有时也用ReLU;计算y^{<t>}则根据你需要的输出类型决定激活函数即可,比如需要判断是否则用sigmod,如果多分类则用softmax。

计算公式简化

可以简化上述公式,计算a^{<t>}时将两个参数矩阵横向拼接,a^{<t-1>}x^{<t>}竖向拼接,最终只需要进行一次矩阵运算。

反向传播 Back propagation through time(BPTT)

有了损失函数之后进行反向计算,并且逐步传播回前一时间步。这里没有展开讲了,可以ChatGPT看下

不同类型的RNN模型

可以看到前面的标准RNN模型的输入与输出的长度是一致的,但是在文章最开头的例子有输入输出长度不一致的情况,这种情况有RNN家族的其他变种来解决。比如多对一,一对多,多对多。

基于RNN的语言模型

语言模型是什么

评估一个特定单词序列出现的概率。

构建过程
Tokenize 标记化

创建词库后,将数据集中每个单词在词库的位置将数据标记化。

词库中可以包含结束符EOS,不认识的字符UNK等。

训练模型

第一个输入0向量,之后逐个单词输入,每一轮输出是个softmax,即下一个单词是词库中每个词的概率,然后按照损失函数训练。

Sampling Novel Sequence 新序列采样

不再使用训练集的数据,而是让模型自动输出,每轮输出下个单词的预测概率后,带权重的随机抽样下一个单词,并作为下一轮的输入,这样模型按顺序会输出一个语句,直到抽样到一个EOS或者达到指定轮数后结束输出。

使用不同的训练集训练出的模型,新序列采样的结果也差异很大,比如下图,使用新闻和使用莎士比亚文章训练出的模型产出的新序列也延续着各自的风格。

字母级别与单词级别语言模型对比

字母级别模型,一个句子的序列会长很多,rnn模型更难学习到序列前面元素对后面元素的影响;另外在计算层面训练成本也会高很多。因此现在语言模型绝大多数还是单词级别的,很少使用字母级别。

梯度消失

标准的RNN模型很难捕捉到长序列前后的关系,每层主要收到前面几层的影响,但是英语中,很可能在一个句子中间增加一段语句,类似下面图片,这个子句前后是有强关联的。

在标准RNN模型中很大的一个问题是经常碰到梯度消失的问题。梯度爆炸可以通过梯度裁剪(gradient clipping)解决,当出现很大的梯度的时候将整个参数矩阵缩放到合理范围

GRU(Gated Recurrent Unit) 

只带更新门的GRU

当更新门Gamma _u接近1时,c^{<t>}主要由新信息决定,减少对c^{<t-1>}依赖;

当更新门Gamma _u接近0时,c^{<t>}主要继承自c^{<t-1>},使梯度更容易回传。

更新门平滑了梯度传递,衰减较慢,缓解了梯度消失。

完整GRU(更新门、重置门)

增加了重置门,重置门作用于上一轮的隐藏输出。

当重置门Gamma _r接近0时,widetilde{c}^{<t>}主要由当前输入x^{<t>}决定,过去信息c^{<t-1>}被大幅遗忘;

当重置门Gamma _r接近1时,则可以保留较多的过去信息c^{<t-1>}

LSTM(Long Short Term Memory)

LSTM里面有三个门:更新门、遗忘门、输出门。相比GRU,c^{<t>}的计算有独立的更新门和遗忘门,而不是用1-更新门作为遗忘门;此外多了一个输出门来通过c^{<t>}计算a^{<t>}

将时间步上的迭代展开为图片如下图下部,可以看到,通过适当的设置更新门和遗忘门,红线所在的记忆细胞在整个迭代中很有可能某个C值从左一直往右传递,GRU也是这样,这就是为什么LSTM和GRU很擅长记忆某些值,捕获更远距离的依赖关系。

GRU与LSTM

虽然先讲了GRU,后讲的LSTM,但是实际上历史上是LSTM先出现的,GRU是作为简化版本出现的。两者对比GRU的复杂度和计算量更低,LSTM会更强大一些。

BRNN

标准RNN模型在时间步的迭代过程中只考虑序列中前面的输入,而无法感知后续的输入。BRNN模型解决了这个问题,类似顺序和倒序将序列中的输入分别输入,计算得到正向underset{a^{<t>}}{
ightarrow}和反向underset{a^{<t>}}{leftarrow},之后再合并计算widehat{y}^{t}

这个计算方式即可以应用到标准RNN模型,也可以应用到GRU和LSTM上,实际上在Transformer出现之前,BiLSTM是应用比较广泛的。

BRNN的坏处是需要有完整的序列之后才能开始计算,对于比如实时演讲这种不合适。

DEEP RNN

相比单层RNN,可以往上堆叠,计算a^{[l]<t>}的公式同时考虑前序参数a^{[l]<t-1>}和下层参数a^{[l-1]<t>}.

深度RNN的计算成本非常昂贵,通常不会有很深的层数。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。