目录
1 为什么提出 RNN
1.1 什么是 Slot Filling
1.2 为什么 FFN 做不好 Slot Filling
1.3 为什么 RNN 能做好 Slot Filling
2 RNN 的整体结构
3 更高级的 RNN 结构
3.1 Deep RNN
3.2 Elman Network & Jordan Network
3.3 Bidirectional RNN
原视频:李宏毅 2020:Recurrent Neural Network (Part I)
李宏毅老师用了一个槽填充(Slot Filling)问题进行了解释。
考虑以下场景:
这里有两个坑位(Slot),分别是目的地(Destination)和到达时间(Time of arrival)。槽填充(Slot Filling)要做的事情,就是从原始句子中提取有用信息,把这两个坑位(Slot)填上。
比如:Taipei 填目的地(Destination)这个坑位,November 2nd 填到达时间(Time of arrival)这个坑位。
考虑 FFN 处理到 Taipei 时:
其中,输出(output)是 Taipei 分属于目的地(Destination)和到达时间(Time of arrival)这两个坑位的概率。根据原始句子,当然是 Taipei 属于目的地(Destination)的概率更高。
然而,当存在两个都包含 Taipei 的句子,但是句意完全不同时:
上图右侧是我按照自己的理解画的,不一定对
在第一句话中,Taipei 属于目的地(Destination);在第二句话中,Taipei 属于出发地(Place of departure)。然而,FFN 在处理 Taipei 时只能看到 Taipei 一词,不能看到前面的 arrive 或者 leave 。又因为模型输入(input)都是一模一样的 Taipei,所以输出结果(output)也会是一样的,即要么永远是目的地(Destination)的概率最高,要么永远是出发地(Place of departure)的概率最高。换句话说,FFN 不能根据句子的不同,灵活地判定 Taipei 是目的地(Destination)还是出发地(Place of departure)。
根据上述分析可以看出,FFN 最大的问题就是看不见 Taipei 前面的单词。那我们让模型能够看见前文不就行了吗?这就引出了 RNN 模型以及 “记忆” 的概念。
“记忆” 就是指,让模型记住自己之前的处理结果,这样在处理当前输入时能够进行参考。比如,让模型记住它之前处理的是 arrive 或者 leave,那么在它处理 Taipei 时它就知道这是目的地(Destination)还是出发地(Place of departure)了。
那么 RNN 具体是怎么实现 “记忆” 的呢?如下图所示:
这是 RNN 的两个特点。第一是,隐层的输出会被存储到 memory 中;第二是,memory 中的内容将会和下一时刻的输入(input)一起被送入到模型中。
我们再来看看 RNN 具体是如何处理输入(input)的:
上图只画了处理第一个输入 [1, 1] 的过程,后面的处理过程请自行脑补。
从这个例子中我们可以看出,即使第一个输入和第二个输入均为 [1, 1],但是输出结果竟然不同(前者是 [4, 4],后者是 [12, 12])。这是因为 RNN 不仅存储了 “记忆”(memory),还让这个 “记忆”(memory)一起作为输入(input)。
换句话说,实际的输入并不单单是一个 [1, 1],还有 “记忆”(memory)中的内容。不同时刻 “记忆”(memory)中的内容不同,那输出当然就不同了。
也正是因为 RNN 存储了 “记忆”(memory),它就不会认为 arrive 后的 Taipei 和 leave 后的 Taipei 是同一个东西啦!
为了简化例子,李宏毅老师假设每个神经元的激活函数均为线性函数,并且权重均为 1,同时没有偏置项。
事实上,1.3 节的图已经说明了 RNN 的整体结构,我们这里只是把循环给展开了:
说明:在第一个时间步输入 arrive 和 memory 的内容(初始为 0),隐层的处理结果存入 memory 中;在第二个时间步输入 Taipei 和 memory 的内容,隐层的处理结果存入 memory 中;在第三个时间步输入 on 和 memory 的内容,隐层的处理结果存入 memory 中;以此类推。
每个时间步的输出(output)均为 xxx 词属于各个坑位的概率。
虽然在 1.3 节已经讲了,但我们还是再来看看 RNN 是如何辨析 Taipei 的:
话说 values 不应该用 are 吗?不过我八百年没学英语了。。。
第 2 节讲的是最基础的 RNN,实际上 RNN 还有很多变形。
这个名字是我随便取的,意思就是 RNN 的隐藏层可以叠加很多个:
Elman Network 是我们在第 2 节中讲的那种 RNN,Jordan Network 的区别在于,它的 memory 存储的是输出(output)而不是隐层的输出:
传说 Jordan Network 的表现更好。因为在训练模型的时候,针对输出(output)是有目标(target)的,我们知道它学到的是什么信息;而针对隐层的输出是没有目标(target)的,我们不知道它学到的是什么信息。所以人们认为输出(output)是可知的、可控的,让它作为 memory 的内容,我们就能知道 memory 的内容是什么了。
双向 RNN 如下图所示:
若是单向 RNN,则每个时刻的输入只能关注到前面的内容;若是双向 RNN,则正方向让每个时刻的输入关注它前面的内容,反方向让每个时刻的输入关注它后面的内容。
双向 RNN 帮助我们关注上下文的信息。比如,在做完形填空的时候,我们既要关注前文,又要关注后文。
介于篇幅长度以及 LSTM 模型的地位,将在下一篇博客介绍 LSTM 模型。