「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。
导语
本文为我之前在CSDN平台上的一篇博客记录。原链接为:NLP学习笔记(五)让RNNs更加高效
让RNNs更加高效(Making RNNs More Effective)
这节课我们学习三个技巧来提升RNN的效果,分别是:
- 多层RNN(Stacked RNN)
- 双向RNN(Bidirectional RNN)
- 预训练(Pre-train)
多层RNN(Stacked RNN)
我们知道,可以把许多全连接层/卷积层堆叠起来,构成一个很深的网络来提升效果。同样的道理,我们也可以把多层RNN堆叠起来,构成一个多层RNN网络以提升效果。
神经网络每一步都会更新状态h,新算出来的h有两个copys,一份送到下一个时刻,另一份作为输出。这一层输出的h,可以接到另外一层的输入。这里最底层RNN的输入是词向量x,这层RNN会输出每一步的状态h,这些输出的向量又成了第二层的输入。第二层RNN有自己的模型参数,也会计算和输出自己的状态。
这里,我们用了三层RNN,最后一层RNN的状态是输出。可以将最后一个输出视为从整个句子中提取的特征向量。
Keras实现略
双向RNN(Bidirectional RNN)
RNN跟人的阅读习惯一样,从左往右挨个单词阅读。人阅读的过程中在大脑中积累信息,RNN则是在状态向量h中积累信息。
我们人类总是习惯于从左往右,从前往后阅读。但对于RNN来说,从前往后和从后往前效果其实是差不多的。所以很自然的想法就是训练两条RNN,一条从左往右,另一条从右往左。两条RNN是完全独立的,不共享参数,也不共享状态。
两条RNN单独输出自己的状态向量,然后将这两个输出做concatenation,记作向量y。
如果有多层RNN,就把这个输出y当做输入继续传到下一层。如果只有这一层,那么可以直接丢掉这些y就可以了,只保留两条链最后的状态向量,分别是和。把这两个向量经过concatenation后得到的向量作为从句子中抽取的特征向量,根据它来判断电影评论是正面还是负面。
双向RNN总是比单向RNN效果好一些。原因可能是这样的:无论使用简单RNN还是LSTM,这些RNN都会或多或少遗忘掉早先的输入。如果RNN从左到右阅读,那么可能会遗忘掉靠左边的输入,反之,肯定能记住靠左边的输入。把这两个向量结合起来,这样RNN就不会遗忘最开始看到的词。
预训练(Pre-train)
预训练是深度学习中经常用到的一个技巧。比如,在图像领域,如果没有足够的训练数据,那么可以先让模型在ImageNet等大型数据集上训练后再进行微调。训练RNN的时候也是这个道理。
预训练具体是这么做的:
首先要找一个更大的数据集,可以是情感分析的数据,也可以是其他类型的数据,但是任务最好是接近原来情感分析的任务。最好是学出来的词向量带有正面/负面的情感。两个任务越相似,预训练后的transfer就会越好。有了大数据集之后要搭建一个神经网络。这个神经网络的结构是什么样的都可以,甚至不用是RNN。只要这个神经网络有embedding层就行。
然后就是在这个大数据集上训练这个网络,训练好之后,把上面的层全都丢掉。只保留embedding层和训练好的模型参数。然后再搭建我们自己的RNN网络。这个新的网络与之前预训练的可以有不同的网络结构,搭好之后,新的RNN层和全连接层都是随机初始化的,而下面embedding层的参数是预训练出来的。
要把embedding层的参数固定住,不要训练这个embedding层,只训练其他的层。
总结(Summary)
这两节课我们学习了两种RNN结构:简单RNN和LSTM。
- 简单RNN非常容易遗忘,而LSTM相对好一些。因而在实践中能用LSTM(GRU)就不要再用简单RNN了。
- 能用双向的LSTM就不要用单向的,双向的效果不会比单向的差
- 多层RNN可能会比单层效果要好(训练数据要多)
- 使用预训练的embedding层可以提升效果(训练数据集小时使用)