我之前一直主要研究CNN,对RNN一直望而生畏,但一直有一股明知山有虎偏向虎山行的莽劲,决心弄明白RNN背后的原理。这是我第一次为了弄懂一个基础网络结构专门去阅读源码。我主要使用pytorch框架,因此这里主要讨论pytorch框架下RNN的实现问题。这里我仅以自己的角度去描述这个问题,有可能有各位读者需要的内容,也有可能没有。
国内百度一下"RNN",大多的博客都是用如下的图示表示:
笔者看过很多类似的博客,这些图都只是告诉了我RNN的理论结构,并不能让我知道RNN中内部到底发生了什么,尤其像我这种强迫症患者,一定要知道内部整个数据流动才能让我放心地去使用。相比CNN,整个过程相当透明,因此十分容易上手,但RNN一直是我“不敢接近之地”。后来我试着去找一些国内外从代码的角度来解释RNN的博客。在介绍这些博客之前,我想先定一个调子。请记住RNN内部就是MLP,MLP,MLP。这个结论可能有的读者早已领悟,笔者比较愚钝,直到使用了CNN一年半之后才明白这个道理(不敢甩锅给国内一些博客,确实是自己笨)。文章最后会附上笔者觉得比较好的博客给大家参考。
现在,我们来看看RNN的公式 :
上面公式中,和表示的是第t时刻的跟上一个时刻的隐藏状态 的权重系数,这个公式直接来源于pytorch的源码文件中
从这里其实可以看出RNN就是一个mlp的结构(本人愚钝)。接下来我们看下RNN的接口参数的使用
torch.nn.rnn(input_size,hidden_size,num_layers,nolinearity,bias,batch_first,dropout,bidrectional
- input_size: 表示输入的特征大小,即mlp的输入层的神经元个数。
- hidden_size:表示隐层状态的大小,可以认为是mlp输出层的神经元个数
- num_layers: 表示的是要堆叠多少个RNN的cell。
- nolinearity: 表示使用的激活函数选择
- bias: 是否使用偏差
- batch_first: 告诉网络输入数据的结构里,第一维是batch大小还是输入的大小。
- dropout: 在mlp里是否使用dropout
- bidirectional: 这个应该是否使用双向RNN,这个笔者目前还不会用.默认不使用
以上是构建了RNN的实例过程,在以上过程中,笔者对num_layers的理解有过错误。最初笔者理解的num_layers表示的mlp的层数。一度与实验室同学讨论激烈,但后来看了源码才感觉是自己错了。仅此记录
构建完RNN实例后,我们来看看这个实例的输入有哪些限制 - input: 输入数据的shape形状模式是(seq_len,batch,input_size)
- h_0:h_0表示的给每层RNN的初始状态,shape的大小应该是(num
_layers,batch,hidden_size)
而对于输出的数据: - output:输出数据的大小是(seq_len,batch,hidden_size)
- h_n:h_n表示最后的输出状态,大小是(num
_layers,batch,hidden_size)
以上,读者应该对RNN的整体结构有了一个了解。对于数据的流动过程,有一位博主的实验做得很好,这里先贴出链接来分享给大家,后来我会加上一些实验,验证自己的想法. https://blog.csdn.net/out_of_memory_error/article/details/81456501 这个博客是对方博主自己写了一个关于RNN的代码,还是很简单易懂的。//www.greatytc.com/p/298116084ec7
未完待续