李宏毅深度学习笔记 3 - 循环神经网络

为什么需要 RNN?

RNN 处理的对象是时序的数据,这些时序的数据前后之间是存在有某种联系的(例如我们可以根据前后文推断挖掉的某个词)。每一个单词可以使用一个向量来表示,传统的神经网络将这些词一个个的输入网络,是不能得到这种 “前后文” 关系的,所以我们需要一种有记忆的神经网络 - Recurrent Neural network (RNN)

RNN

Elman network

我们只需要对原先的神经网络做一点小小的改动就可以让他拥有 “记忆”。具体来说,我们用一个 memory 区域来保存网络中间层的结果,然后每一次输入数据的时候,网络不仅需要考虑前面的层传过来的参数,还有同时的考虑 memory 区域中的值。比如,我们可以设置每一次中间层的神经元都要将计算得到的结果加上 memory 中的值,这样这一层的神经元就拥有了历史数据的信息。当然,简单的相加是会有很多问题的,这里只是举一个例子。

BQtQUg.png

Jordan network

注意前面说的 Elman network 其实是没有 target 的,我们很难知道把什么东西放到 memory 里面才是比较好的。而 Jordan network 就是把当前的输出存到 memory 里面,然后再下一个节点的时候在读出来,这样我们很就很清楚自己需要放到 memory 里面的是什么东西,从而去优化他。

image-20201027161917508

Bidirectional RNN

前面说的两个网络的 memory,是存储了当前词之前的词的信息,我们很自然的会想到,除了 “前文”,“后文” 的内容也可以充分的利用起来,这就是 Bidirectional RNN

img

LSTM

LSTM 是什么?

前面的三个 RNN 的网络,存储于 memory 中的值都是设计好的,再一次输入数据的时候都会进行更新。但是在实际操作中我们会有更多的需求,因此我们对需要设立几个 “门” 来控制 memory 中的值以及他什么时候去输出。具体来说,有一个 input gate 控制是否需要将数据输入近 memory,有一个 forget gate 用于控制是否擦除 memory 中的内容,有一个 output gate 用于控制是否输出 memory 中的内容。这里我们可以把控制” 门” 的信号也看做是输入,加上输入的数据 x,LSTM 实际上就是一个输入 4 个 input 产生 1 个 output 的块。

拓展知识 1:Long Short-term Memory 中 - 的正确位置

这个 “-” 应该在 short-term 中间,是长时间的短期记忆。想想我们之前看的 Recurrent Neural Network,它的 memory 在每一个时间点都会被洗掉,只要有新的 input 进来,每一个时间点都会把 memory 洗掉,所以的 short-term 是非常 short 的,但如果是 Long Short-term Memory,它记得会比较久一点 (只要 forget Gate 不要决定要忘记,它的值就会被存起来)。

LSTM 是如何运作的?

假设输入的数据是 z,三个 gate 分别由信号 z~i~,z~f~,z~o~ 控制,首先输入数据会先经过一层激活函数得到 g (z),input gate 的信号在经过一层变换后会得到 f (z~i~),两者相乘就得到了我们想要存入 memory 的数据 $g (z)f (z_i)$(可以认为 f (z~i~) 等于 0 或 1,代表是否存入 memory)。而 forget gate 就决定了是否需要记住 memory 中上一次的数据 c,所以最终存入 memory 的值为 $c’=g (z) f (z_i)+cf (z_f)$,同样的 outout gate 决定了我们是否需要输出 memory 中的值,所以整个 LSTM 最后的输出就可以表示为 $a=h (c’)f(z_o)$。

LSTM meet RNN

这个其实很简单啦,上面整个过程唯一还没有说明的就是,控制三个门的信号是怎么来的?实际上,这三个信号都是由输入经过现象变换得到的

事实上,除了 memory 中的值会让我们获得当前此之前的内容信息之外,LSTM 还会额外的把上一个节点中 LSTM 的一些中间输出取出来,和当前节点的输入 x 拼在一起,然后在用这个拼接的值得到当前节点 LSTM 的四个输入。所以,LSTM 网路的完整结构图应该是介个样子的:

传统 RNN 存在的问题

传统 RNN 的训练其实并没有那么的容易,因为他的 error surface 通常是下面这样的

可以看到,RNN 的 error surface 是非常的崎岖的(一些地方很平坦,突然变的很陡峭)。所以,如果当前位置是在右边的缓坡上,这样因为梯度很小,我们会把学习率设置成一个较大的值,而随着我们在坡面上不断的下行,很有可能我们会一脚踩在这个悬崖上,这样悬崖处的梯度是很大的,这时候的学习率也很大,我们下一次的落脚的位置,就会非在十万八千里外了。这一点也很好解决,我们可以设置一个阈值,超过了这个阈值梯度都设置为同意的值,这样即使踩在了悬崖上,也不会飞的很远,这就是 Clipping 技术。

拓展阅读 2:如何得到梯度的大小?

可以用 “对于输入变化,输出变化的剧烈程度” 来表示梯度的大小

RNN VS LSTM

RNN 的 error surface 为什么会这么崎岖呢?在 RNN 当中,每一个数据都可以影响 memory 中的值。所以在每一个节点数据输入的时候,memory 中的值会被完全的覆盖掉。但是在 LSTM 中,对于一个新的 input,我们会把原来的 memory 乘上一个值再加上 input。这样做首先保证了如果一个节点对 memory 产生了影响,这种影响会一直存在于 memory 中;此外,memory 和 input 是相加的,不像 RNN 在输入新的 input 后会强制刷新 memory。

GRU

相比于 lstm,Gates Recurrent Unit (GRU) 只有两个 Gate。其实这两个 Gate 也并不是那么神秘,只不过他对 input gate 和 forget gate 做了一个联动,即当 input gate 打开的时候,forget gate 会自动的关闭;当 forget gate 没有要刷新 memory 中的值,input gate 就会关起来。也就是说要把 memory 里面的值清楚掉,才放新的值进来

后面的内容都是关于 RNN 的实际应用的,还蛮好玩的,感兴趣的可以看视频做进一步的了解 https://www.bilibili.com/video/BV1JE411g7XF?p=21

丨fengche丨 wechat
来找我聊天吧~
-------------本文结束感谢您的阅读-------------