Stacked RNN(多层RNN)
1. 原理
多个全连接层可以堆叠,多个卷积层也可以堆叠。同理:RNN也可以堆叠形成多层RNN。
如下图所示:对于每一个时刻的输出
h
t
h_t
ht,它既会作为下一个时刻的输入,也会作为下一层RNN的输入。
第二层同理:
最终最后一层RNN的最后一个
h
t
h_t
ht 即为模型的输出:
2. 代码实现
加入多层LSTM,其中除最后一层的LSTM,把其他层的return_sequences置为True,因为需要它们作为下一层RNN的输入。
模型参数: 其中32为特征向量维度,这里不一定每一层的维度都为32,纯属巧合
模型效果: 与之前的普通LSTM变化不大,原因在于Embedding层的参数太多了,没有足够多的数据把Embedding训练好导致过拟合,加再多的LSTM层也无济于事
Bidirectional RNN
之前提到RNN和人的阅读习惯类似,从左往右读。人在阅读过程中在脑中记录信息,而RNN在状态向量
h
t
h_t
ht 中记录信息。而对RNN来说,从前往后阅读和从后往前阅读差别并不大。
因此:
- 可以想到可以从两个方向分别训练RNN,两者不共享参数,也不共享状态。
- 两条RNN各自输出自己的状态向量,然后把这两个向量作concatenation,
- 还可以堆叠双向RNN,原理和上面提到的类似,把concatenation后的向量作为下一层的输入即可
- 如果不进行堆叠,则舍弃
y
y
y 。只保留最后的两个
h
t
h_t
ht 即可,对它们作concatenation作为输出
双向RNN一般情况下都会比普通的RNN效果好,原因是: - 无论是Simple RNN还是LSTM都或多或少会遗忘前面的信息
- 从左往右的RNN最后会遗忘掉偏左边的信息,从右往左的RNN最后会遗忘掉偏右边的信息,这两者正好形成了互补
代码实现
导入Bidirectional即可实现双向RNN,这里是单层的实现
参数:
模型效果: 还是没有太大的改进,原理同上——Embedding层的参数太多了,没有足够多的数据把Embedding训练好导致过拟合,改进LSTM效果不佳
Pretrain
预训练在深度学习中非常常用,比如卷积神经网络。如果网络太大而训练数据不够大,那么可以在ImageNet等大数据上做预训练,好处在于:
- 有良好的初始化
- 避免过拟合
而我们训练RNN的时候是同理的,如下图所示,我们的Embedding层有32w个参数,而我们只有2w个样本。我们的模型太大而训练数据太少就容易导致过拟合
固我们可以得出解决办法:对Embedding层作预训练
具体方法
- 让模型在一个大的数据集上作预训练。最好是在情感分析上的数据集上进行预训练,两个任务越相似,预训练效果越好。训练的神经网络可以是任意的,即不是RNN都行
- 只保留这个网络的Embedding层和模型参数,然后用我们自己的RNN网络
- 训练我们自己的RNN,参数都是随机初始化的,而Embedding参数的已经训练好的,把它固定住,只训练其他层
Summary
想要RNN模型的效果好,关注以下几个点:
- Simple RNN和LSTM是两种不同的RNN,用LSTM肯定比用Simple RNN好
- 尽量用双向RNN
- 当堆叠的层足够大时,多层RNN的效果可能会比单层好
- 当数据小而模型大时,考虑预训练Embedding层