encoder-decoder模型
先给⾃⼰写个标题,等我理解深刻了,再来填充内容。
Encoder-Decoder(编码-解码)是深度学习中⾮常常见的⼀个模型框架,⽐如⽆监督算法的auto-encoding就是⽤编码-解码的结构设计并训练的;⽐如这两年⽐较热的image caption的应⽤,就是CNN-RNN的编码-解码框架;再⽐如神经⽹络机器翻译NMT模型,往往就是LSTM-LSTM的编码-解码框架。因此,准确的说,Encoder-Decoder并不是⼀个具体的模型,⽽是⼀类框架。Encoder和Decoder部分可以是任意的⽂字,语⾳,图像,视频数据,模型可以采⽤CNN,RNN,BiRNN、LSTM、GRU等等。所以基于Encoder-Decoder,我们可以设计出各种各样的应⽤算法。
Encoder-Decoder框架有⼀个最显著的特征就是它是⼀个End-to-End学习的算法;本⽂将以⽂本-⽂本的例⼦作为介绍,这样的模型往往⽤在机器翻译中,⽐如将法语翻译成英语。这样的模型也被叫做 Sequence to Sequence learning[1]。所谓编码,就是将输⼊序列转化成⼀个固定长度的向量;解码,就是将之前⽣成的固定向量再转化成输出序列。
参考⽂章:本段出⾃Bin的专栏blog.csdn/xbinworld。
这⾥复习下Sequence2Sequence任务到底是什么,所谓的Sequence2Sequence任务主要是泛指⼀些Se
quence到Sequence的映射问题,Sequence在这⾥可以理解为⼀个字符串序列,当我们在给定⼀个字符串序列后,希望得到与之对应的另⼀个字符串序列(如 翻译后的、如语义上对应的)时,这个任务就可以称为Sequence2Sequence了。
在现在的深度学习领域当中,通常的做法是将输⼊的源Sequence编码到⼀个中间的context当中,这个context是⼀个特定长度的编码(可以理解为⼀个向量),然后再通过这个context还原成⼀个输出的⽬标Sequence。
如果⽤⼈的思维来看,就是我们先看到源Sequence,将其读⼀遍,然后在我们⼤脑当中就记住了这个源Sequence,并且存在⼤脑的某⼀个位置上,形成我们⾃⼰的记忆(对应Context),然后我们再经过思考,将这个⼤脑⾥的东西转变成输出,然后写下来。
那么我们⼤脑读⼊的过程叫做Encoder,即将输⼊的东西变成我们⾃⼰的记忆,放在⼤脑当中,⽽这个记忆可以叫做Context,然后我们再根据这个Context,转化成答案写下来,这个写的过程叫做Decoder。其实就是编码-存储-解码的过程。
⽽对应的,⼤脑怎么读⼊(Encoder怎么⼯作)有⼀个特定的⽅式,怎么记忆(Context)有⼀种特定的形式,怎么转变成答案(Decoder 怎么⼯作)⼜有⼀种特定的⼯作⽅式。
decoder
好了,现在我们⼤体了解了⼀个⼯作的流程Encoder-Decoder后,我们来介绍⼀个深度学习当中,最经典的Encoder-Decoder实现⽅式,即⽤RNN来实现。
在RNN Encoder-Decoder的⼯作当中,我们⽤⼀个RNN去模拟⼤脑的读⼊动作,⽤⼀个特定长度的特征向量去模拟我们的记忆,然后再⽤另外⼀个RNN去模拟⼤脑思考得到答案的动作,将三者组织起来利⽤就成了⼀个可以实现Sequence2Sequence⼯作的“模拟⼤
脑”了。
⽽我们剩下的⼯作也就是如何正确的利⽤RNN去实现,以及如何正确且合理的组织这三个部分了。
Encoder-Decoder模型
Encoder-Decoder框架可以看作是⼀种⽂本处理领域的研究模式,应⽤场景异常⼴泛。下图是⽂本处理领域⾥常⽤的Encoder-Decoder框架最抽象的⼀种表⽰:
Encoder-Decoder框架可以这么直观地去理解:可以把它看作适合处理由⼀个句⼦(或篇章)⽣成另外⼀个句⼦(或篇章)的通⽤处理模型。对于句⼦对<X,Y>,我们的⽬标是给定输⼊句⼦X,期待通过Encoder-Decoder框架来⽣成⽬标句⼦Y。X和Y可以是同⼀种语⾔,也可以是两种不同的语⾔。⽽X和Y分别由各⾃的单词序列构成:
Encoder顾名思义就是对输⼊句⼦X进⾏编码,将输⼊句⼦通过⾮线性变换转化为中间语义表⽰C:
对于解码器Decoder来说,其任务是根据句⼦X的中间语义表⽰C和之前已经⽣成的历史信息y1,y2….yi-1来⽣成i时刻要⽣成的单词yi
每个yi都依次这么产⽣,那么看起来就是整个系统根据输⼊句⼦X⽣成了⽬标句⼦Y。
Encoder-Decoder不是⼀种模型,⽽是⼀种框架,⼀种处理问题的思路,最早应⽤于机器翻译领域,输⼊⼀个序列,输出另外⼀个序列。机器翻译问题就是将⼀种语⾔序列转换成另外⼀种语⾔序列,将该技术扩展到其他领域,⽐如输⼊序列可以是⽂字,语⾳,图像,视频,输出序列可以是⽂字,图像,可以解决很多别的类型的问题。这⼀⼤类问题就是上图中的sequence-to-sequence问题。这⾥以输⼊为⽂本,输出也为⽂本作为例⼦进⾏介绍:
encoder部分是将输⼊序列表⽰成⼀个带有语义的向量,使⽤最⼴泛的表⽰技术是Recurrent Neural Network,RNN是⼀个基本模型,在训练的时候会遇到gradient explode或者gradient vanishing的问题,导致⽆法训练,所以在实际中经常使⽤的是经过改良的LSTM RNN 或者GRU RNN对输⼊序列进⾏表⽰,更加复杂⼀点可以⽤BiRNN、BiRNN with LSTM、BiRNN with GRU、多层RNN等模型来表⽰,输⼊序列最终表⽰为最后⼀个word的hidden state vector。
decoder部分是以encoder⽣成的hidden state vector作为输⼊“解码”出⽬标⽂本序列,本质上是⼀个语⾔模型,最常见的是⽤Recurrent Neural Network Language Model (RNNLM),只要涉及到RNN就会有训练的问题,也就需要⽤LSTM、GRU和⼀些⾼级的model来代替。⽬标序列的⽣成和LM做句⼦⽣成的过程类似,只是说计算条件概率时需要考虑encoder向量。
这⾥,每⼀种模型⼏乎都可以出⼀篇paper,尤其是在这个技术刚刚开始应⽤在各个领域中的时候,⼤家通过尝试不同的模型组合,得到state-of-the-art结果。
所谓encoder-decoder模型,⼜叫做编码-解码模型。这是⼀种应⽤于seq2seq问题的模型。
那么seq2seq⼜是什么呢?简单的说,就是根据⼀个输⼊序列x,来⽣成另⼀个输出序列y。seq2seq有很多的应⽤,例如翻译,⽂档摘取,问答系统等等。在翻译中,输⼊序列是待翻译的⽂本,输出序列是翻译后的⽂本;在问答系统中,输⼊序列是提出的问题,⽽输出序列是答案。
为了解决seq2seq问题,有⼈提出了encoder-decoder模型,也就是编码-解码模型。所谓编码,就是将输⼊序列转化成⼀个固定长度的向量;解码,就是将之前⽣成的固定向量再转化成输出序列。
当然了,这个只是⼤概的思想,具体实现的时候,编码器和解码器都不是固定的,可选的有CNN/RNN/BiRNN/GRU/LSTM等等,你可以⾃由组合。⽐如说,你在编码时使⽤BiRNN,解码时使⽤RNN,或者在编码时使⽤RNN,解码时使⽤LSTM等等。
这边为了⽅便阐述,选取了编码和解码都是RNN的组合。在RNN中,当前时间的隐藏状态是由上⼀时间的状态和当前时间输⼊决定的,也就是
ht=f(ht−1,xt)
获得了各个时间段的隐藏层以后,再将隐藏层的信息汇总,⽣成最后的语义向量
C=q(h1,h2,h3,…,hTx)
⼀种简单的⽅法是将最后的隐藏层作为语义向量C,即
C=q(h1,h2,h3,…,hTx)=hTx
解码阶段可以看做编码的逆过程。这个阶段,我们要根据给定的语义向量C和之前已经⽣成的输出序列y1,y2,…yt−1来预测下⼀个输出的单词yt,即
yt=argmaxP(yt)=∏t=1Tp(yt|{y1,…,yt−1},C)
也可以写作
yt=g({y1,…,yt−1},C)
⽽在RNN中,上式⼜可以简化成
yt=g(yt−1,st,C)
其中s是输出RNN中的隐藏层,C代表之前提过的语义向量,yt−1表⽰上个时间段的输出,反过来作为这个时间段的输⼊。⽽g则可以是⼀个⾮线性的多层的神经⽹络,产⽣词典中各个词语属于yt的概率。
encoder-decoder模型虽然⾮常经典,但是局限性也⾮常⼤。最⼤的局限性就在于编码和解码之间的唯⼀联系就是⼀个固定长度的语义向量C。也就是说,编码器要将整个序列的信息压缩进⼀个固定长度的向量中去。但是这样做有两个弊端,⼀是语义向量⽆法完全表⽰整个序列的信息,还有就是先输⼊的内容携带的信息会被后输⼊的信息稀释掉,或者说,被覆盖了。输⼊序列越长,这个现象就越严重。这就使得在解码的时候⼀开始就没有获得输⼊序列⾜够的信息, 那么解码的准确度⾃然也就要打个折扣了
2019年3⽉16⽇补充:
⽐较好的⽂章:
Encoder-Decoder模型和Attention模型
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论