卷积神经网络CNN已经足够强大,为什么还需要RNN?
RNN的独特价值
卷积神经网络 – CNN 和普通的算法大部分都是输入和输出的一一对应,也就是一个输入得到一个输出。不同的输入之间是没有联系的。
比如下图中的X1和X2互换一下位置,对结果是没有任何影响的。
可是还存在这样场景,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。如白雪和雪白就是两种不同的意思。
基于序列的模型可以用在很多领域中。
在音乐中,一首曲子的下一个音符肯定取决于前面的音符,而在视频领域,电影中的下一帧肯定与先前的帧有关。
此外,在某些情况下,视频的当前帧、单词、字符或音符不仅仅取决于过去的信号,而且还取决于未来的信号。
例如,如果你想写一个文档,单词的顺序很重要,当前的单词肯定取决于以前的单词。如果把注意力放在文字写作上…一个单词中的下一个字符取决于之前的字符(例如,The quick brown f…,下一个字母是 o 的概率很高),如下图所示。关键思想是在给定上下文的情况下产生下一个字符的分布,然后从分布中取样产生下一个候选字符:
- 关于“The quick brown fox”句子的预测示例
一个简单的变体是存储多个预测值,并创建一个预测扩展树,如下图所示:
这种需要处理 序列数据 (一串相互依赖的数据流) 的场景就需要使用 RNN 来解决了。
RNN的原理
回顾一下传统神经网络的结构,如下图,比较简单地分为:输入层 – 隐藏层 – 输出层。
RNN 跟传统神经网络最大的区别在于每次都会将前一次的输出结果,带到下一次的隐藏层中,一起训练。如下图所示:
把上图按照时间线展开就得到( X t X_t Xt代表t时刻的X值,U是输入层到隐藏层的权重矩阵,o也是一个向量,它表示输出层的值;V是隐藏层到输出层的权重矩阵。):
也许第一次看到会有点难以理解,网络在t时刻接收到输入 X t X_t Xt 之后,隐藏层的值是 S t S_t St ,输出值是 O t O_t Ot 。关键的是, S t S_t St 的值不仅仅取决于 X t X_t Xt ,还取决于 S t − 1 S_{t-1} St−1 。
请对照上面的展开图,我们可以用下面的公式来表示循环神经网络的计算方法(f,g是激活函数,且公式中并没有包含偏置项):
Q t = g ( V ⋅ S t ) (a) Q_t=g(V\cdot S_t) \tag a Qt=g(V⋅St)(a)
S t = f ( U ⋅ X t + W ⋅ S t − 1 ) (b) S_t=f(U \cdot X_t +W \cdot S_{t-1}) \tag b St=f(U⋅Xt+W⋅St−1)(b)
注意各状态的W、V、U的值是相同的,循环神经元的特点是权重共享
RNN在实际实现的时候把隐藏层的输出叫作state,将前一刻的state和当前时刻的输入作为共同输入,输出给下一隐藏层。
上述两个公式完成了RNN的前向传播。总结一下:
(1) t时刻的输入 + t-1时刻的状态 S t − 1 S_{t-1} St−1(第一个输入的state可以看作0),应用循环递推公式,得到下一时刻的状态 S t S_t St
(2) 对t+1时刻的输入和 S t S_t St应用循环递推公式,得到 S t + 1 S_{t+1} St+1。
以此类推,直至完成所有时间步,得到最后的状态输出
(n) 对最后的状态应用公式a,得到最后的输出。
再加上以下两步即构成完整的循环神经元的计算步骤:
(a)输出与真实标签进行比较并得到误差。
(b)误差通过反向传播对权重进行更新,进而网络训练完成。
RNN的优化算法
RNN基于这样的机制,信息的结果依赖于前面的状态或前N个时间步。普通的RNN可能在学习长距离依赖性方面存在困难。例如,如果我们有这样一句话,“The man who ate my pizza has purple hair”。在这种情况下,purple hair描述的是The man,而不是pizza。所以这是一个长距离的依赖关系。
RNN 到 LSTM – 长短期记忆网络
RNN 是一种死板的逻辑,越晚的输入影响越大,越早的输入影响越小,且无法改变这个逻辑。
LSTM 做的最大的改变就是打破了这个死板的逻辑,而改用了一套灵活了逻辑——只保留重要的信息。
简单说就是:抓重点!
长短时记忆网络(LSTM)
长短时记忆网络可以控制何时让输入进入神经元,何时记住之前时序中学到的东西,以及何时让输出传递到下一个时间戳。所有这些决策仅仅基于输入就能自我调整。
LSTM 被明确设计用来避免长期依赖性问题。长时间记住信息实际上是 LSTM 的默认行为,而不是需要努力学习的东西!
所有递归神经网络都具有神经网络的链式重复模块。在标准的 RNN 中,这个重复模块具有非常简单的结构,例如只有单个 tanh 层。
乍一看,LSTM 看起来很难理解,但事实并非如此。我们用下图来解释它是如何工作的:
LSTM 的关键是细胞状态,即图中上方的水平线。
细胞状态有点像传送带。它贯穿整个链条,只有一些次要的线性交互作用。信息很容易以不变的方式流过。
LSTM 可以通过所谓“门”的精细结构向细胞状态添加或移除信息。
门可以选择性地以让信息通过。它们由 S 形神经网络层和逐点乘法运算组成。
S 形网络的输出值介于 0 和 1 之间,表示有多大比例的信息通过。0 值表示“没有信息通过”,1 值表示“所有信息通过”。
一个 LSTM 有三种这样的门用来保持和控制细胞状态。
详细一点解释的话:
首先,需要一个逻辑函数 σ 计算出介于 0 和 1 之间的值,并且控制哪个信息片段流经 LSTM 门。请记住,logisitic 函数是可微的,所以它允许反向传播。
然后需要一个运算符 ⊗ 对两个相同维数的矩阵进行点乘产生一个新矩阵,其中新矩阵的第 ij 个元素是两个原始矩阵第 ij 个元素的乘积。同样,需要一个运算符 ⊕ 将两个相同维数的矩阵相加,其中新矩阵的第 ij 个元素是两个原始矩阵第 ij 个元素的和。在这些基本模块中,将 i 时刻的输入 xi 与前一步的输出 yi 放在一起。
方程 fi=σ(Wf·[yi-1,xi]+bf) 是逻辑回归函数,通过控制激活门 ⊗ 决定前一个单元状态 Ci-1 中有多少信息应该传输给下一个单元状态 Ci(Wf 是权重矩阵,bf 是偏置)。逻辑输出 1 意味着完全保留先前单元状态 Ct-1,输出 0 代表完全忘记 Ci-1 ,输出(0,1)中的数值则代表要传递的信息量。
接着,方程根据当前输入产生新信息,方程 si=σ(Wc·[Yi-1,Xi]+bc) 则能控制有多少新信息通过运算符 ⊕ 被加入到单元状态 Ci 中。利用运算符 ⊗ 和 ⊕,给出公式对单元状态进行更新。
最后,需要确定当前单元状态的哪些信息输出到 Yi。很简单,再次采用逻辑回归方程,通过 ⊗ 运算符控制候选值的哪一部分应该输出。在这里有一点需要注意,单元状态是通过 tanh 函数压缩到 [-1,1]。这部分对应的方程是 Yi=ti*tanh(Ci)。
这看起来像很多数学理论,但有两个好消息。首先,如果你明白想要达到的目标,那么数学部分就不是那么难;其次,你可以使用 LSTM 单元作为标准 RNN 元的黑盒替换,并立即解决梯度消失问题。
处理向量序列
真正使 RNN 强大的是它能够处理向量序列,其中 RNN 的输入和输出可以是序列,下图很好地说明了这一点,最左边的例子是一个传统(非递归)网络,后面跟着一个序列输出的 RNN,接着跟着一个序列输入的 RNN,其次跟着序列输入和序列输出不同步的 RNN,最后是序列输入和序列输出同步的 RNN。
机器翻译是输入序列和输出序列中不同步的一个例子:网络将输入文本作为一个序列读取,读完全文后输出目标语言。
视频分类是输入序列和输出序列同步的一个例子:视频输入是一系列帧,对于每一帧,在输出中提供分类标签。
参考:
https://easyai.tech/ai-definition/rnn/
http://c.biancheng.net/view/1946.html
一些有趣的应用:
http://karpathy.github.io/2015/05/21/rnn-effectiveness/