动手学深度学习 Vol5|循环神经网络RNN
承接上一会对Attention中seq2seq的模型的困惑,这里从RNN到介绍到更传统的Seq2Seq模型。同时结合最近接触的花书来利用更有利的工具解释RNN中的梯度。并给出序列学习中对于gradient或者hidden state转变的过程,在针对hidden state中的转变中引申出GRU、LSTM之类的变种,并结合D@L给出代码的实现。
0x01 序列学习与RNN
1.1 序列学习Seq2Seq
输入与输出均为序列数据的模型叫做Seq2Seq,注意这里不在按照传统的监督或者非监督的方式来限定模型的类型。常见序列模型的应用包括:语音识别Speech recognition、音乐生成Music generation、情感分析 Sentiment classification、DNA序列分析DNA sequence analysis、机器翻译Machine translation、视频行为识别Video activity recognition、命名实体识别Name entity recognition。
在Seq2Seq过程中,我们很难像MLP或者CNN得到一个明确的 feature,label;并且序列数据大多是按照一定的顺序来进行的,比如文本序列、视频信号、网站浏览行为等等,并不满足之前的独立同分布的假设。
为什么RNN类似的网络在Seq中会取得好的效果?主要是解决20世纪80年代机器学习和统计模型的思想的优点:在模型的不同部分共享参数。参数共享使得模型能够拓展到不同形式的样本并进行泛化。specially:假如在seq的每一个时间点都具有一个单独的参数,但是我们不能泛化我们没有见过的类型,也不能在时间上共享不同序列长度和不同位置的统计强度。同时我们也不能理解不同顺序seq的含义(比如In 2009,I went to Nepal和I went to Nepal in 2009之间的区别)
Shortly:RNN的优势主要是
- 跨时间权重共享
- 时间平移不对称
- 同一架构适应不同长度
1.2 RNN结构前向传播 Forward Propagation
这里先不管RNN内部的具体结构的原因,只要知道RNN包括时间步的input和output以及hidden state就可以,原因在后面会说明。计算图是形式化一组计算结构的方式,如果设计将输入和参数映射到输出和损失的计算。
先假设数据集为
通常的训练过程是将
𝐻𝑡=𝑓(𝐻𝑡−1,𝑥𝑡;𝜃)
如果采用神经网络,格式通常是
其中各项的分别为
在得到hidden state我们可以进行下一步状态转换,也可以输出当前的值
其中各项的形状为
得到模型的输入和输出之后就可以计算模型的损失
得到
image-20221019135246524
1.3 反向传播的梯度下降 Back Propagation
在之前中我们包括至少五个参数,
注意这里的第一项我们是知道的,第二项我们也是知道的,但是第三项它是会一直Recurrent计算下去的
这样梯度其实是会随着时间t不断拉长,这里通常称为长期依赖的问题这样我们可能出现梯度消失、或者梯度爆炸的情况。常见的操作有三种
- 完全计算直到收敛
- 采用N步马尔可夫模型,来截断时间步,到达时间步
- 采用随机截断的思想
还有针对梯度的一些操作,常见的有截断梯度和引导信息流的正则化,
- 针对梯度爆炸,截断梯度也就是在参数更新之前截断梯度的范数,在时间的过程中被证明是有用的。
- 针对梯度消失,引导信息流的正则化,一种是加入门控单元(如LSTM、GRU),也可以解决梯度爆炸的问题;一种是正则化项,后者被证明不有效
1.4 进一步。高级一点的RNN
在单向RNN的基础上,可以自然而然的联想到
- 双向RNN
- 深度RNN
- 递归神经网络,一个潜在的idea是研究推论
- 增加门控单元的不同变种GRU、LSTM
- 基于encoder- decoder的seq2seq框架
- 回声状态网络(echo state network),流体状态机(liquid state machines)
1.5 回过头解释RNN
首先我们可以回顾我们在时间序列预测中常用的一些方法:自回归模型、隐变量自回归模型、马尔可夫模型、因果关系模型等等,常用的是
因此我们也可以希望得到
也就是假如一个hidden state来作为对之前序列总结,将其送入状态转变中。
0x02 变种与思考GRU、LSTM
我们之前分析了长期依赖对于梯度消失或者梯度爆炸的影响,从实际效果来看它的影响是:
- 早期的预测值对预测所有未来预测值具有非常重要的意义
- 一些词元没有相关的观测值,比如对网页内容进行情感分析可能有一些辅助HTML代码与网页传达的情绪无关
- 序列之间的不同部分之间存在逻辑中断
在过去采取过很多方法来进行改进,目前主流的是使用门控的方式来确定什么时候更新hidden state、什么时候重置reset。
2.1 Gate
设计为(0,1)区间内的向量,这样我们可以进行凸组合:reset-gate允许我们控制可能还想记住的过去状态的数量,更新们能讲允许我们控制新状态中有多少是旧状态的副本
具体的计算过程如图:
注意在求和过程会触发 广播机制,使用sigmoid函数将其转换到0,1区间,在这个基础上更新 候选隐藏状态
使用tanh非线性激活函数来保证hidden state中的值是保持在区间-1,1之间的;Hadamar元素表示按照元素进行乘积我们结合更新门来对候选隐藏状态进行进一步的修正,得到最终hidden state的取值
由此得到门控循环单元具有两个显著的特征
- reset有助于捕获序列中的短期依赖关系
- updater有助于捕获序列中的长期依赖关系
2.2 GRU
image-20221019152134663
2.3 LSTM
image-20221019152055705
2.4 DRNN
image-20221019152209098
2.5 BRNN
image-20221019152224395
0x03 逻辑过程分析
3.1 序列数据读取(example:文本数据)-token-vocab
首先文本数据集从文本读取出来是这样子的
文本数据集time machine
我们总的idea是希望将上述不规则的文本,转换为可以用向量表示的数字,且为序列数据。Obviously,我们可以用一个词典vocab来将这些词语转换称为数字。那么这个词典的顺序怎么确定?通常是根据词的出现频率来实现的。同时对于出现频率过少的词可以用或者其他来表示。加入我们使用每个单词来表示,得到的vocab就是
vocab-word
除了单词我们也可以使用单个字符char来分割数据集
vocab-word
3.2 数据预处理-input: batchsize,num_steps–dataloader
在这个基础上我们就可以生成我们的dataloader,因为seq序列天然就有顺序性,而为了提高泛化性我们希望他们可以学习到顺序性,但是学习的又不太多,因此会有两种采样方式来做:
- 随机采样
- 顺序分区
批量的大小由batchsize来确定,同时单次训练的顺序包括num_steps个单词,因此经过这样我们采取送入网络训练的单个batch的形状为
总体的shape就是
这里有个操作是为了后面小批量矩阵运算,会做一个reshape,变成
3.3 模型主干-model-loss-optim
初始化参数
选择适合的loss
定义RNN model
3.4 训练与可视化- train- predict-ppl
train也就是设置learning rate和epoch训练就好了
0x04 代码实现1,2,3
这里完全参考李沐大大的代码,然后将其中的d2l的部分完全剔除得到如下的代码
4.1 数据集读取设置
1 |
|
4.2 模型搭建
1 |
|
4.3 预测与训练
1 |
|
下面选择一个模型就ok
- # 实际训练过程 # params setting from matplotlib.pyplot import isinteractive # model setting net=RNNmodel(rnn_layer,vocab_size=len(vocab)) net=net.to(device)
- # 第二种GRU num_inputs=len(vocab) gru_layer=nn.GRU(num_inputs,num_hiddens) net=RNNmodel(gru_layer,len(vocab)) net=net.to(device)
- # 第三种LSTM num_inputs=len(vocab) num_layers=2 lstm_layer=nn.LSTM(num_inputs,num_hiddens,num_layers) net=RNNmodel(lstm_layer,len(vocab)) net=net.to(device)
- # 第四种 Deep-LSTM num_inputs=len(vocab) num_layers=32 lstm_layer=nn.LSTM(num_inputs,num_hiddens,num_layers) net=RNNmodel(lstm_layer,len(vocab)) net=net.to(device)
1 |
|
4.5 结果
- 肯定都能训练出来
GRU结果
- 使用word的训练时间会大于char很多
word的训练过程
给他一个time traveller,可以得到这个:
time traveller stooping to light a spill at the fire then he turned lighting his pipe to look at the psychologist s face the psychologist to show that he was not unhinged helped himself to a cigar and tried to light it uncut what is more i have a big machine nearly
-—-
时间旅行者弯腰在火上点燃一个溢出物,然后他转动点亮他的烟斗,看着心理学家的脸,心理学家表明他不是不合时宜地帮助自己抽雪茄,并试图点燃它未切割,更重要的是我有一个大机器几乎
- 深层RNN不一定有效
32层LSTM的结果
0x05 Discussion(个人见识)
- MLP或者CNN有点像顺序结构,RNN有点像循环结构,Attention有点像判断结构
- 不同结构带来的是不同的感受野,MLP的感受野是个点,CNN的感受野可能是长方形,RNN的感受野可能是很长的序列,Attention则是选择感受野
- RNN很土