一、循环神经网络(Recurrent Neural Network)
有记忆的神经网络就是循环神经网络(RNN)
1.1 槽填充(Slot Filling)
- 如下图,一个关键元素就是一个槽位(Slot),从用户交互中抽取出的这个槽位对应的取值,就是填充(Filling)
- 下图的槽位(Slot)有两个,分别是目的地(destination)和到达时间(arrival time)
- 我们是可以用之前学过的前馈网络(Feedforward network)来解决槽填充的问题的
- 首先输入是一个单词,每个单词都代表一个向量
- 输出代表输入单词属于这些槽位(Slot)的概率分布
1.2 1-of-N Encoding
- vector中元素数量就等于所有word的数量,对1个单词来说只需要vector中对应元素为1,其余元素都是0即可
- 但这种vector一点都不信息丰富(informative),任意两个vector都是不一样的,无法建立起同类word之间的联系(比如cat和dog都是动物)。
1.3 RNN工作原理
- RNN中的隐藏层的输出被存储在存储器(store)中,存储器可以被认为是另一种输入,存储器在输入之前需要给定初始值。
- 因此改变输入的序列顺序(sequence order)将会改变输出,因此就很好的解决了同一个输入在不同场景下如何使输出变得不同的问题。
- 下图中的示例是单个隐层的网络,当然也可以叠很多层,做成深度神经网络
1.4 Elman Network & Jordan Network
- Elman Network
- 就是上面介绍的网络结构,即将隐层输出存起来,等到下一个时间点再读出来。
- Jordan Network
- 它存的是整个网络最终的输出值,等到下一个时间点再读出来。
- 由于Elman Network的隐层输出是没有目标(target)的,因此难以控制说它会学到什么样的隐层信息。一般情况下Jordan Network的表现要好很多。
- Bidirectional RNN
- 由于之前的RNN网络只能记住上文,而无法记住下文,为了解决这个问题。如下图,我们会将网络设计成双向的,从而达到根据上下文来推断语义的功能。
二、长短期记忆网络 (Long Short-term Memory)
- 长短期记忆网络(LSTM)有4个输入,1个输出。其中3个输入分别为:输入门(input gate)的控制信号 z i z_i zi,遗忘门(forget gate)的控制信号 z f z_f zf,输出门(output gate)的控制信号 z 0 z_0 z0。
- 其工作原理如下图
- 激活函数 f 通常是一个sigmoid函数,其输出介于0和1之间
- 输入 𝑐 ′ = 𝑔 ( z ) 𝑓 ( 𝑧 𝑖 ) + 𝑐 𝑓 ( 𝑧 𝑓 ) 𝑐′=𝑔(z)𝑓(𝑧_𝑖)+𝑐𝑓(𝑧_𝑓) c′=g(z)f(zi)+cf(zf) ,c为存储单元的初始值,当输入门和遗忘门同时打开为1时,c’才能存储成功
- 输出 a = h ( c ′ ) 𝑓 ( 𝑧 0 ) a=h(c')𝑓(𝑧_0) a=h(c′)f(z0),当输出门打开为1时,才能输出a
- 第3,4两张图模拟了LSTM的工作过程,其中 x 1 代表输入, x 2 代表遗忘门, x 3 代表输出门 x_1代表输入,x_2代表遗忘门,x_3代表输出门 x1代表输入,x2代表遗忘门,x3代表输出门
- 后面的图完整介绍了LSTM的工作流程,网络看起来相当复杂,由于他需要4个输入,因此他的参数量是普通网络的4倍
- 我们常说的RNN网络有3种,分别是LSTM,GRU(相比LSTM少了一个门,因此参数量也少了三分之一,相当于LSTM的简化版),SimpleRNN(就是我们开头介绍的Bidirectional RNN,存储单元没有门控制)
三、RNN怎么学习?
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-30.png)
假设我们现在做的事情是slot filling,那你会有train data,那这个train data是说:我给你一些sentence,你要给sentence一些label,告诉machine说第一个word它是属于other slot,“Taipei是”Destination slot,"on"属于other
slot,“November”和“2nd”属于time slot。
那这边注意的事情就是,(在丢“Taipei”之前先把“arrive’'丢进去),不然你就不知道存到memory里面的值是多少。**所以在做training的时候,你也不能够把这些word打散来看,word sentence仍然要当做一个整体来看。**把“on”丢进去,reference vector对应的other的dimension是1,其它是0.
RNN的损失函数output和reference vector的entropy的和就是要最小化的对象。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-31.png)
- 在讲feedforward neural network的时候,我们说GD用在feedforward neural network里面你要用一个有效率的算法叫做Backpropagation。(反向传播)
- 在Recurrent Neural Network里面,**为了要计算方便,所以也有开发一套算法是Backpropagation的进阶版,叫做BPTT。**它跟Backpropagation其实是很类似的,只是Recurrent Neural Network它是在high sequence上运作,所以BPTT它要考虑时间上的information。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-32.png)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-33.png)
用工程的思想来解决,这一招蛮关键的,在很长的一段时间,只有他的code可以把RNN的model给train出来。
这一招就是clipping(当gradient大于某一个threshold的时候,不要让它超过那个threshold),当gradient大于15时,让gradient等于15结束。因为gradient不会太大,所以你要做clipping的时候,就算是踩着这个悬崖上,也不飞出来,会飞到一个比较近的地方,这样你还可以继续做你得RNN的training。
问题:为什么RNN会有这种奇特的特性。有人会说,是不是来自sigmoid function,我们之前讲过Relu activation function的时候,讲过一个问题gradient vanish(梯度消失),这个问题是从sigmoid function来的,RNN会有很平滑的error surface是因为来自于gradient vanish,这问题我是不认同的。等一下来看这个问题是来自sigmoid function,你换成Relu去解决这个问题就不是这个问题了。跟大家讲个秘密,**一般在train neural network时,一般很少用Relu来当做activation function。为什么呢?其实你把sigmoid function换成Relu,其实在RNN performance通常是比较差的。**所以activation function并不是这里的关键点。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-34.png)
你把某一个参数做小小的变化,看它对network output的变化有多大,你就可以测出这个参数的gradient的大小。
所以RNN不好训练的原因不是来自activation function,而是来自于它有high sequence同样的weight在不同的时间点被反复的使用。
3.1 如何解决RNN梯度消失或者爆炸
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-35.png)
如果你要做LSTM时,大部分地方变化的很剧烈,所以当你做LSTM的时候,你可以放心的把你的learning rate设置的小一点,保证在learning rate很小的情况下进行训练。
那为什么LSTM 可以解决梯度消失的问题呢,为什么可以避免gradient特别小呢?
我听说某人在面试某国际大厂的时候被问到这个问题,那这个问题怎么答比较好呢(问题:为什么我们把RNN换成LSTM)。如果你的答案是LSTM比较潮,LSTM比较复杂,这个就太弱了。正在的理由就是LSTM可以handle gradient vanishing的问题。接下里面试官说:为什么LSTM会handle gradient vanishing的问题呢?用这边的式子回答看看,若考试在碰到这样的问题时,你就可以回答了。
RNN跟LSTM在面对memory的时候,它处理的操作其实是不一样的。你想想看,在RNN里面,在每一个时间点,memory里面的值都是会被洗掉,但是在LSTM里面不一样,它是把原来memory里面的值乘上一个值再把input的值加起来放到cell里面。所以今天它和RNN不同的是,如果今天你的weight可以影响到memory里面的值的话,一旦发生影响会永远都存在。不像RNN在每个时间点的值都会被format掉,所以只要这个影响被format掉它就消失了。但是在LSTM里面,一旦对memory造成影响,那影响一直会被留着(除非forget gate要把memory的值洗掉),不然memory一旦有改变,只会把新的东西加进来,不会把原来的值洗掉,所以它不会有gradient vanishing的问题
那你想说们现在有forget gate可能会把memory的值洗掉。**其实LSTM的第一个版本其实就是为了解决gradient vanishing的问题,所以它是没有forget gate,forget gate是后来才加上去的。**甚至,现在有个传言是:你在训练LSTM的时候,你要给forget gate特别大的bias,你要确保forget gate在多数的情况下都是开启的,只要少数的情况是关闭的
那现在有另外一个版本用gate操控memory cell,叫做Gates Recurrent Unit(GRU),LSTM有三个Gate,而GRU有两个gate,所以GRU需要的参数是比较少的。因为它需要的参数量比较少,所以它在training的时候是比较鲁棒的。如果你今天在train LSTM,你觉得overfitting的情况很严重,你可以试下GRU。GRU的精神就是:旧的不去,新的不来。它会把input gate跟forget gate联动起来,也就是说当input gate打开的时候,forget gate会自动的关闭(format存在memory里面的值),当forget gate没有要format里面的值,input gate就会被关起来。也就是说你要把memory里面的值清掉,才能把新的值放进来。
其他方式
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-36.png)
有一个蛮有趣的paper是这样的:一般的RNN用identity matrix(单位矩阵)来initialized transformation weight+ReLU activaton function它可以得到很好的performance。刚才不是说用ReLU的performance会比较呀,如果你说一般train的方法initiaed weight是random,那ReLU跟sigmoid function来比的话,sigmoid performance 会比较好。但是你今天用了identity matrix的话,这时候用ReLU performance会比较好。
3.2 RNN其他应用
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-37.png)
多对一序列
情感分析
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-38.png)
某家公司想要知道,他们的产品在网上的评价是positive 还是negative。他们可能会写一个爬虫,把跟他们产品有关的文章都爬下来。那这一篇一篇的看太累了,所以你可以用一个machine learning 的方法learn一个classifier去说哪些document是正向的,哪些document是负向的。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-39.png)
多对多序列
语音识别
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-40.png)
CTC语音识别
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-41.png)
以下是在文献CTC上得到的结果。在做英文辨识的时候,你的RNN output target 就是character(英文的字母+空白)。直接output字母,然后如果字和字之间有boundary,就自动有空白。
假设有一个例子,第一个frame是output h,第二个frame是output null,第三个frame是output null,第四个frame是output I等等。如果你看到output是这样子话,那最后把“null”的地方拿掉,那这句话的辨识结果就是“HIS FRIEND’S”。你不需要告诉machine说:"HIS"是一个词汇,“FRIEND’s”是一个词汇,machine通过training data会自己学到这件事情。那传说,Google的语音辨识系统已经全面换成CTC来做语音辨识。如果你用CTC来做语音辨识的话,就算是有某一个词汇(比如是:英文中人名,地名)在training data中从来没有出现过,machine也是有机会把它辨识出来。
序列对序列学习
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-44.png)
比如说,我们现在做machine translation,input英文word sequence把它翻译成中文的character sequence。那我们并不知道说,英文跟中文谁比较长谁比较短(有可能是output比较长,output比较短)。所以改怎么办呢?
现在假如说input machine learning ,然后用RNN读过去,然后在最后一个时间点,这个memory里面就存了所有input sequence的information。
这就让我想到推文接龙,有一个人推超,下一个人推人,然后推正,然后后面一直推推,等你推好几个月,都不会停下来。你要怎么让它停下来呢?推出一个“断”,就停下来了。
这篇的paper是这样做的,sequence to sequence learning我们原来是input 某种语言的文字翻译成另外一种语言的文字(假设做翻译的话)。那我们有没有可能直接input某种语言的声音讯号,output另外一种语言的文字呢?我们完全不做语音辨识。比如说你要把英文翻译成中文,你就收集一大堆英文的句子,看看它对应的中文翻译。你完全不要做语音辨识,直接把英文的声音讯号丢到这个model里面去,看它能不能output正确的中文。这一招居然是行得通的。假设你今天要把台语转成英文,但是台语的语音辨识系统不好做,因为台语根本就没有standard文字系统,所以这项技术可以成功的话,未来你在训练台语转英文语音辨识系统的时候,你只需要收集台语的声音讯号跟它的英文翻译就可以刻了。你就不需要台语语音辨识的结果,你也不需要知道台语的文字,也可以做这件事。
Beyond Sequence
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-49.png)
你可能想说machine它今天output的sequence不符合文法结构呢(记得加左括号,忘记加右括号),神奇的地方就是LSTM不会忘记右括号。
Document转成Vector
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-50.png)
那我们可以用sequence to sequence Auto-encoder这种做法来考虑word sequence order的情况下,把一个document变成一个vector。
序列对序列自编码器 - 文本
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-51.png)
Sequence-to-sequence 还有另外一个版本叫skip thought,如果用Sequence-to-sequence的,输入输出都是同一个句子,如果用skip thought的话,输出的目标就会是下一个句子,用sequence-to-sequence得到的结果通常容易表达,如果要得到语义的意思的,那么skip thought会得到比较好的结果。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-52.png)
这个结构甚至可以是hierarchical(分层的),你可以每一个句子都先得到一个vector(Mary was hungry得到一个vector,she didn’t find any food得到一个vector),然后把这些vector加起来,然后变成一个整个 document high label vector,在让这整个vector去产生一串sentence vector,在根据每一个sentence vector再去解回word sequence。这是一个四层的LSTM(从word 变成sentence sequence ,变成document lable,再解回sentence sequence,再解回word sequence)
序列对序列自编码器 - 语音
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-53.png)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-54.png)
怎么实现呢?你就先把一个audio data base,把这个data base做segmentation切成一段一段的。然后每一个段用刚才讲的audio segment to vector这个技术,把他们通通变成vector。然后现再输入一个spoken query,可以通过audio segment to vector技术也变成vector,接下来计算他们的相似程度。然后就得到搜寻的结果
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-55.png)
**但是只要RNN Encoder我没有办法去train,同时你还要train一个RNN Decoder,Decoder的作用就是,它把Encoder得到的值存到memory里面的值,拿进来当做input,然后产生一个acoustic features sequence。**然后希望这个y_1y1跟x_1x1越接近越好。然后再根据y_1y1产生y_2y2,以此类推。今天训练的targety_1,y_2,y_3,y_4y1,y2,y3,y4跟x_1,x_2,x_3,x_4x1,x2,x3,x4越接近越好。那在训练的时候,RNN Encoder跟RNN Decoder是一起train的
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-56.png)
Demo:聊天机器人
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-57.png)
现在除了RNN以外,还有另外一种有用到memory的network,叫做Attention-based Model,这个可以想成是RNN的进阶的版本。
那我们知道说,人的大脑有非常强的记忆力,所以你可以记得非常非常多的东西。比如说,你现在同时记得早餐吃了什么,同时记得10年前夏天发生的事,同时记得在这几门课中学到的东西。那当然有人问你说什么是deep learning的时候,那你的脑中会去提取重要的information,然后再把这些information组织起来,产生答案。但是你的脑中会自动忽略那些无关的事情,比如说,10年前夏天发生的事情等等。
Attension-based Model
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-60.png)
当你输入一个input的时候,这个input会被丢进一个中央处理器,这个中央处理器可能是一个DNN/RNN,那这个中央处理器会操控一个Reading Head
Controller,这个Reading Head Controller会去决定这个reading head放的位置。machine再从这个reading head 的位置去读取information,然后产生最后的output
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-61.png)
阅读理解(Reading Comprehension)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-62.png)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-63.png)
上图是在**baby corpus(婴儿语料库)**上的结果,baby corpus是一个Q&A的一个简单的测试。我们需要做的事就是读过这五个句子,然后说:what color is Grey?,得到正确的答案,yes。那你可以从machine attention的位置(也就是reading head 的位置)看出machine的思路。图中蓝色代表了machine reading head 的位置,Hop1,Hop2,Hop3代表的是时间,在第一个时间点,machine先把它的reading head放在“greg is a frog”,把这个information提取出来。接下来提取“brian is a frog” information ,再提取“brian is yellow”information。最后它得到结论说:greg 的颜色是yellow。这些事情是machine自动learn出来的。也就是machine attention在哪个位置,这些通过neural network学到该怎么做,并不是去写程序,你要先看这个句子,在看这个句子。这是machine自动去决定的。
视觉问答(Visual Question Answering)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-64.png)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-65.png)
语音问答(Speech Question Answering)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-66.png)
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-67.png)
另外还可以用memory network可以得到39.2 %正确率,如果用我们刚才讲的那个model的话,可以做到48.8%正确率。
RNN 和Structured learning关系
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-70.png)
最后总结来看,RNN/LSTM在deep这件事的表现其实会比较好,同时这件事也很重要,如果只是线性的模型,function space就这么大,可以直接最小化一个错误的上界,但是这样没什么,因为所有的结果都是坏的,所以相比之下,deep learning占到很大的优势。
Integerated Together
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-71.png)
先用Bi-directional LSTM做feature,然后把这些feature拿来在做CRF或者Structured SVM,然后学习一个权重w,这个\phi(x,y)ϕ(x,y)的feature,要直接从Bidirectional LSTM的输出可以得到比较好的结果。
Structure learning practical?
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-74.png)
有人说structured learning是否现实?
structured learning需要解三个问题,其中input的问题往往很困难,因为要穷举所有的y让其最大,解一个optimization的问题,其实大部分状况都没有好的解决办法,只有少数有,其他都是不好的状况。所有有人说structured learning应用并不广泛,但是未来未必是这样的。
**其实GAN就是一种structured learning,可以把discriminator看做是evaluation function(也就是problem 1)最后要解一个inference的问题,我们要穷举我们未知的东西,看看哪个可以让我们的evaluation function最大。**这步往往比较困难,因为x的可能性太多了。但其实这个可以就是generator,我们可以想成generator就是用所给的noise,输出一个update,它输出的这个高斯模型,就是让discriminator分辨不出的高斯模型,如果discriminator就是evaluation function的话,那output的值就是让evaluation function的值很大的那个对应值,所以这个generator就是在解这个问题,其实generator的输出就是argmax的输出,可以把generator当做在解inference这个问题,然后就直接求problem 3。structured learning过程和GAN模型generator不断产生让discriminator最大的那个值,然后再去训练discriminator不断识别真实值,然后更新值的过程是异曲同工的。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-75.png)
GAN也可以是conditional的GAN,现在的任务是给定x,找出最有可能的y,想象成语音辨识,x是声音讯号,y是辨识出来的文字,如果是用conditional的概念,generator输入一个x,就会output一个y,discriminator是去检查y的pair是不是对的,如果给他一个真正的x,y的pair,会得到一个比较高的分数,给一个generator输出的一个y配上输入的x,所产生的一个假的pair,就会给他一个比较低的分数。训练的过程就和原来的GAN就是一样的,这个已经成功运用在文字产生图片这个task上面。这个task的input就是一句话,output就是一张图,generator做的事就是输入一句话,然后产生一张图片,而discriminator要做的事就是给他一张图片,要他判断这个x,y的pair是不是真的,如果把 discriminator换成evaluation function,把generator换成解inference的problem,其实conditional GAN和structured learning就是可以类比,或者说GAN就是训练structured learning的一种方法。
![img](https://oss.linklearner.com/leeml/chapter37/res/chapter37-76.png)