RNN基本原理
当初学RNN的时候,被各种公式原理讲解弄得云里雾里。
其实很简单
RNN中,有几个变量,一个h和一个x。x是当前的输入。比如我们输入一个句子序列“我真牛逼”,这里的每一个字对应一个x。四个字代表四个时间步的输入。
而隐藏层h是由上一个时间步的h和当前时间步的x计算得到的。
这个计算也很简单,就是把当前时间步的x和上一步的h分别经过全连接层运算后相加。
也就是y=wx和h=wh的结果加起来,作为当前时间步的h。然后下一个时间步的h也是重复这个过程。
初始化h_0=0
比如 我真牛逼这个输入。
初始化h_0=0,
h1=W1 * “我”+W2 * h_0+b
h2=W3 * “真” +W4 * h_1
…
pytorch RNN使用
RNN接收序列输入。对于一个句子,要转换成向量形式输入。
如果把一个字转换为一个n维向量,那么一个由K个字组成的一句话
输入到RNN时,就是[k,n]的形状
比如我最牛逼,每个字用5维向量做Embedding,输入就是[4,5]的shape。
在torch中,可以利用字典表和torch自带的nn.Embedding层做转换。
字典表的形式是{字:序号}的形式。
对于一个句子,先根据字典表转换成离散数值形式。假设我最牛逼四个字在字典表中对应的序号是0,1,2,3。
那么将[0,1,2,3]这个tensor输入到Embedding中即可。
Embedding有两个参数,第一个是num_Embedding,即字典表有多少个字。
第二个参数是Embedding_dim,就是要将一个字转换为多少维。
若Embdding_dim=5
那么,[0,1,2,3]经过Embedding后,就会变成一个(4,5)shape的tensor
形如
[[. . . . .],
[. . . . .],
[. . . . .],
[. . . . .]]
每一行代表一个字的信息。将这个tensor输入到RNN中,可以得到想要的结果。
附带Pooling层小细节
Pooling在文本中,使用的方向应该是沿着句子的方向。也就是对于上面这个[4,5]的tensor,使用时候应该是竖着相加,得到一个[1,5]的tensor。因为如果是横着做pooling,相当于对单个字做pooling,没什么意义。
另外如果Embedding后直接加pooling层,会丢失字的顺序信息。如果做的下游任务与顺序相关,很可能无法完成。比如判断一个字母在句子中的位置,如果Embedding后直接对结果做pooling,就无法通过神经网络训练处出有效的网络,因为顺序信息已经丢失。