版权声明:欢迎转载,但请务必注明原文出处及作者信息。
目录(?)[-]
@author: huangyongye
对于RNN,我看到讲得最通俗易懂的应该是Andrej发的博客:
The Unreasonable Effectiveness of Recurrent Neural Networks
这里有它的中文翻译版本:
递归神经网络不可思议的有效性
如果想了解 LSTM 的原理,可以参考这篇文章:(译)理解 LSTM 网络 (Understanding LSTM Networks by colah)。
下面的连接中对RNN还有BPTT(RNN的反向传播算法),LSTM和GRU的原理和实现讲解得也是非常棒:
http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/
首先介绍几篇比较重要的 seq2seq 相关的论文:
[1] Cho et al., 2014 . Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation
[2] Sutskever et al., 2014. Sequence to Sequence Learning with Neural Networks
[3] Bahdanau et al., 2014. Neural Machine Translation by Jointly Learning to Align and Translate
[4] Jean et. al., 2014. On Using Very Large Target Vocabulary for Neural Machine Translation
[5] Vinyals et. al., 2015. A Neural Conversational Model[J]. Computer Science
顾名思义,seq2seq 模型就像一个翻译模型,输入是一个序列(比如一个英文句子),输出也是一个序列(比如该英文句子所对应的法文翻译)。这种结构最重要的地方在于输入序列和输出序列的长度是可变的。
举个栗子
在机器翻译:输入(hello) -> 输出 (你好)。输入是1个英文单词,输出为2个汉字。
在对话机器中:我们提(输入)一个问题,机器会自动生成(输出)回答。这里的输入和输出显然是长度没有确定的序列(sequences).
要知道,在以往的很多模型中,我们一般都说输入特征矩阵,每个样本对应矩阵中的某一行。就是说,无论是第一个样本还是最后一个样本,他们都有一样的特征维度。但是对于翻译这种例子,难道我们要让每一句话都有一样的字数吗,那样的话估计五言律诗和七言绝句又能大火一把了,哈哈。但是这不科学呀,所以就有了 seq2seq 这种结构。
论文[1]Cho et al. 算是比较早提出 Encoder-Decoder 这种结构的,其中 Encoder 部分应该是非常容易理解的,就是一个RNNCell(RNN ,GRU,LSTM 等) 结构。每个 timestep, 我们向 Encoder 中输入一个字/词(一般是表示这个字/词的一个实数向量),直到我们输入这个句子的最后一个字/词 XT ,然后输出整个句子的语义向量 c(一般情况下, c=hXT , XT 是最后一个输入)。因为 RNN 的特点就是把前面每一步的输入信息都考虑进来了,所以理论上这个 c 就能够把整个句子的信息都包含了,我们可以把 c 当成这个句子的一个语义表示,也就是一个句向量。在 Decoder 中,我们根据 Encoder 得到的句向量 c , 一步一步地把蕴含在其中的信息分析出来。
论文[1] 中的公式表示如下:
同样,根据 h<t> 我们就能够求出 yt 的条件概率:
这里有两个函数 f 和 g , 一般来说, f 函数结构应该是一个 RNNCell 结构或者类似的结构(论文[1]原文中用的是 GRU); g 函数一般是 softmax (或者是论文 [4] 中提出的 sampled_softmax 函数)。我们可以先这样来理解:在 Encoder 中我们得到了一个涵盖了整个句子信息的实数向量 c ,现在我们一步一步的从 c 中抽取信息。首先给 Decoder 输入一个启动信号 y0(如特殊符号<START>) , 然后Decoder 根据 h<0>,y0,c ,就能够计算出 y1 的概率分布了,同理,根据 h<1>,y1,c 可以计算 y2 的概率分布…以此类推直到预测到结束的特殊标志 <END> ,才结束预测。
论文[1]Cho et al. 中除了提出 Encoder-Decoder 这样一个伟大的结构以外,还有一个非常大的贡献就是首次提出了 Gated Recurrent Unit (GRU)这个使用频率非常高的 RNN 结构。
注意到在论文[1]Cho et al. 的模型结构中(如 图1 所示),中间语义 c 不仅仅只作用于 decoder 的第 1 个时刻 ,而是每个时刻都有 c 输入 (具体的公式见本文第三部分)。所以,在这篇论文中, Decoder 预测第 t 个 timestep 的输出时可以表示为:
而在论文[2] 中,Decoder 预测第 t 个 timestep 的输出时可以表示为:
论文[2]Sutskever et al. 中的 Encoder-Decoder 其实是最简单的,我在 github 上面找到下面这张非常棒的图,描述了这个模型的结构,由于该图最初来源网址打不开了,所以详细的介绍我也看不了,在 github 的网址为: https://github.com/nicolas-ivanov/tf_seq2seq_chatbot
图3 中展示的是一个邮件对话的应用场景,图中的 Encoder 和 Decoder 都只展示了一层的普通的 LSTMCell。从上面的结构中,我们可以看到,整个模型结构还是非常简单的。 EncoderCell 最后一个时刻的状态 [cXT,hXT] 就是上面说的中间语义向量 c ,它将作为 DecoderCell 的初始状态。然后在 DecoderCell 中,每个时刻的输出将会作为下一个时刻的输入。以此类推,直到 DecoderCell 某个时刻预测输出特殊符号 <END> 结束。
论文 [2]Sutskever et al. 也是我们在看 seq2seq 资料是最经常提到的一篇文章, 在原论文中,上面的Encoder 和 Decoder 都是 4 层的 LSTM,但是原理其实和 1 层 LSTM 是一样的。原文有个小技巧思想在上面的邮件对话模型结构没展示出来,就是原文是应用在机器翻译中的,作者将源句子顺序颠倒后再输入 Encoder 中,比如源句子为“A B C”,那么输入 Encoder 的顺序为 “C B A”,经过这样的处理后,取得了很大的提升,而且这样的处理使得模型能够很好地处理长句子。此外,Google 那篇介绍机器对话的文章(论文[5] )用的就是这个 seq2seq 模型。
在 CS224n lecture1 中, 也介绍了论文[2]的这个模型,下图是该课件中展示的模型结构。原文中提到的模型是 4 层的,课件上只是展示了三层,但是已经足够帮助我们理解模型结构了。
论文[3] Bahdanau et al. 是在 Encoder 和 Decoder 的基础上提出了注意力机制。在上面提到的结构中,每次预测都是从句向量 c 中进行信息提取。但是如果句子很长的话, c 未必能把所有的信息都保留好呀,所以就有了 Attention Model 这样一种东西出现了,它的出现让机器翻译的效果大大地提升了。引入注意力机制的原理其实还是挺好理解的:
如果你已经对论文[1]的模型结构充分理解,那么理解引入注意力机制的这个模型还是很容易的。在论文[1] 的 decoder 中,每次预测下一个词都会用到中间语义 c ,而这个 c 呢,主要就是最后一个时刻的隐藏状态。在论文[3] 中,我们可以看到在Decoder进行预测的时候,Encoder 中每个时刻的隐藏状态都被利用上了。这样子,Encoder 就能利用多个语义信息(隐藏状态)来表达整个句子的信息了。
此外,在论文[3] 中,Encoder用的是双端的 GRU,这个结构其实非常直观,在这种 seq2seq 中效果也要比单向的 GRU 要好。至于模型的细节可以看原论文来进行理解,在这里我就不做展开,有兴趣的也可以参考下面这篇文章,讲得非常好:张俊林: 自然语言处理中的Attention Model:是什么及为什么
论文[4]介绍了机器翻译在训练时经常用到的一个方法(小技巧)sample_softmax ,主要解决词表数量太大的问题。
关于seq2seq是什么,下面这篇文章讲得挺不错的,我最开始就是看了这篇文章,可以参考。
使用机器学习进行语言翻译:神经网络和seq2seq为何效果非凡?
seq2seq其实可以用在很多地方,比如机器翻译,自动对话机器人,文档摘要自动生成,图片描述自动生成。比如Google就基于seq2seq开发了一个对话模型([5]A Neural Conversational Model),和论文[1,2]的思路基本是一致的,使用两个LSTM的结构,LSTM1将输入的对话编码成一个固定长度的实数向量,LSTM2根据这个向量不停地预测后面的输出(解码)。只是在对话模型中,使用的语料是((input)你说的话-我答的话(input))这种类型的pairs 。而在机器翻译中使用的语料是(hello-你好)这样的pairs。
此外,如果我们的输入是图片,输出是对图片的描述,用这样的方式来训练的话就能够完成图片描述的任务。等等,等等。
可以看出来,seq2seq具有非常广泛的应用场景,而且效果也是非常强大。同时,因为是端到端的模型(大部分的深度模型都是端到端的),它减少了很多人工处理和规则制定的步骤。在 Encoder-Decoder 的基础上,人们又引入了attention mechanism等技术,使得这些深度方法在各个任务上表现更加突出。
由于自己还没有编程实现过模型,所以现在只是根据论文做一些理解,可能有些地方不太正确,还得经过自己实践才能理解透彻。
下面对论文[1] 和论文[2] 的模型进行细致的分析和比较。
在论文[1] 的原文中, 作者采用的是 GRUCell,这是 LSTMCell 的一个变种,图6 所示是 GRU 的模型结构。(注意下图中第四个式子和原文中的公式是有点不同的地方,就是 1−zt 和 zt 的位置和原文刚好相反,但是二者其实效果是一样的 ,后面的分析都是根据下面图示的结构来分析)
在 EncoderCell 中,模型结果就是上面图示的那样,理解应该没什么问题。最后一个输入 XT 输入模型后,得到最后的隐藏状态为 hXT 。但是跟论文[2] 不完全相同,这个 hXT 还要做一次 tanh 变换后才得到最后的中间语义向量 c 。
在 DecoderCell 中 ,我们从 EncoderCell 中已经拿到了刚刚输入的句子的语义向量 c ,现在要逐步从 c 中把信息提取出来。在原文中,这个 c 也不是直接拿来当做 DecoderCell 的初始状态,而是 :
其实和图5. 中的结构没有太大的区别,只是在每一步的输入中都加入了 c 而已。假设输入词向量长度都是 embedding_size = 1000; 每层隐藏节点数都是 hidden_size = 1000 。那么就有:
论文[2] 相比论文[1] 要更容易理解一些,因为在 DecoderCell 中,直接用 Encoder 最后一个时间步的状态 [CXT,hXT] 作为整个句子的中间语义 c ,然后 c 直接作为Decoder 的初始状态。然后后面的计算中就没有再用到 c 。
下面来推算一下改论文中说的模型参数规模。在论文中,主要实现了英文(source)到法文(target)的翻译。其中英文词典大小 source_vocab_size = 160,000,法文词典大小 target_vocab_size = 80,000,二者的词向量长度都是 embedding_size = 1,000。
所以一共大约有 64 + 240 + 80 = 384 M 参数,所以应该就是这样没错。
好吧,说了这么多细节都是纸上谈兵,还得赶紧实践一下才能真正理解呀。
转自:http://blog.csdn.net/jerr__y/article/details/53749693#