假设我们当前要做一个人工智能客服系统,那该系统就需要对用户输入的话语进行辨认,例如用户输入:
I want to arrive Taipei on November 2nd
那么该系统就能够辨认出来Taipei是目的地,而后面是时间。那么我们可以用一个简单的前向网络来实现这个事情,输出为这个单词属于哪个含义的概率。但这会存在问题,例如输入以下:
I want to leave Taipei on November 2nd
同样输入都是Taipei,但是第一个句子是作为目的地,第二个句子是作为出发地,那么普通的前向网络是无法对同一个输出做出不同的输出的。因此就希望此时使用的网络能够具有一定的记忆性,即在看到Taipei之前因为已经读入了前一个词汇(arrive、leave),那么就根据这前面的词汇来进行辅助判断。
其主要的特点在于每个隐含层的输出都会存放在一个另外的位置中( a 1 , a 2 a_1,a_2 a1,a2),并且隐含层接受的输入包括原本的输入和当前存储记忆中的值,假设权重都是1,那么该隐含层的输入就是 a 1 + a 2 + x 1 + x 2 a_1+a_2+x_1+x_2 a1+a2+x1+x2。并且在第一次输入的时候由于记忆中没有值因此需要赋予初始值。
而这样存在记忆的结构就使得RNN对于输入的顺序是敏感的,不同的输入之间并不是独立的,它们顺序一旦变化就会引起输出的大不相同。那么如果用RNN来处理之前的任务:
注意这里并不是用到了三个网络结构,而是同一个网络在不同的时间点被使用了三次。那么这就可能使得输入同样的词汇结果输出是不一样的,因为前面的输入也会影响该结果。
而RNN同样也可以往deep发展:
下面介绍RNN网络的变体:
这两种网络都是RNN的推广,架构的主要区别在于:
这个结构的特点在于对于网络的架构是双向的,即正向是跟前面一样,反向呢是从尾部不断读到头部(因为顺序不同输出也就不相同),然后再把每个对应的输出结合起来给输出层作为输入,即将正向的 x t x^t xt的输出和反向的 x t x^t xt的输出一起作为输出层的输入得到真正输出 y t y^t yt:
那么这就导致在在对每个输入做判断的时候,相当于综合了前后的所有信息来做判断。
顾名思义,就是具有比较长期记忆能力的RNN网络,前面的RNN 网络都是只要有了新的输入进来,记忆结点中就会被重写,但LSTM不一样,其主要特点的结构如下,其具有三个Gate
上面各个Gata的打开和关闭都是网络自己学习到的。因此每一个记忆结点就有四个输入(输入数值和三个控制信号)和一个输出
下面来看其具体的运作行为:
为什么采用Sigmoid函数来作为Gate的激活函数呢?因为它的输出在0到1之间,可以认为是该闸门打开的程度。而这里可以看出ForgetGate打开的时候(输出为1)是对原来的值进行记忆的,只有关闭的时候才是对原来的值清零的。也可以看出输出的值跟所有闸门的打开关闭是息息相关的。这边所有Gate的输入都是学习得到的。
上面所说的只是单个结点,整体的网络就相当于将神经元换成这整个记忆单元,如下图:
因此认为神经元数目相同时,LSTM参数量是普通的四倍。而实际上LSTM并不会这么简单:
可以认为x是乘以了四个矩阵(权重矩阵)得到了四个向量,这四个向量的长度和该层LSTM记忆单元的数目一样,然后每一个作为LSTM的输入,因此刚好就四个输入,如上图。因此如果多个串起来就是:
就是将上一层的输出和记忆单元当前的值和这一层的输入拼在一起作为输入,再加上多层:
这就是LSTM的完全体了。
将输出的词性或者是标注作为目标向量,损失函数就是输出向量与目标向量的距离。
跟之前的网络一样,RNN对于网络参数的学习仍然是采用梯度下降的方式。而为了高效的计算梯度就有了BPTT这个算法(课程没有介绍这部分)。
但是RNN的训练并不容易:
这是因为它的损失函数非常地特殊:
这就导致损失函数计算梯度的时候经常跳动,总体损失也剧烈变化。而实际上做法可以将梯度设置一个阈值,超过则默认为阈值就可以了,不然可能会陡峭导致梯度无穷大。为什么会有上面这么陡峭的损失函数呢?来看下图的结构:
在很小的区间内,权重非常微小的变化就会导致输出剧烈的变化,因此很难通过学习率来应对。这主要是因为同一个参数在不同的时间点多次被使用所导致的。
而如果将RNN换成LSTM,它可以解决上述出现的梯度消失(Gradient vanishing)的问题,这可能会在面试中提及。
或者可以采用GRU,其只有两个gate,更简单但是表现也不差