Seq2Seq 语言生成模型 - 自然语言处理 | 莫烦Python
切换视频源:

Seq2Seq 语言生成模型

作者: 莫烦 编辑: 莫烦 2020-07-29

学习资料:

怎么了

我们在这个短片简介中提到过。 机器怎么理解句子一直是一个难题,以前有人尝试将用句子中出现的词语频率来表达这个句子的含义(TF-IDF)。 也有人想把句子中的词语先向量化,然后再叠加句子中所有向量化的词语来表达一句话。 这些在的确都是一种计算机表达句子含义的方式,但是不一定会非常准确。因为他们都只是一种对词语理解的简单加工方式,有的忽略了词语的表达顺序, 有的忽略了词语的组合模式。这往往导致计算机不能非常准确的理解句子。

后来随着深度学习的快速发展,我们也能利用像循环神经网络或者自注意力这样的机制,去用模型直接理解整个句子,最终实现了End-to-End的句子理解。 如果用一句话来说明这样技术的核心,我会这样描述:向量表示是深度学习成功的关键。对句子的理解,就是在多维空间中给这个句子安排一个合适的位置。

每一个空间上的点,就代表了计算机对事物的某种理解。我们再将空间信息转换成其他信息,就能完成对这个句子理解后的应用了。

什么是Encoder和Decoder

在深度学习中,万物都可向量化,其中有两个问题:

  1. 怎么样从原始的数据变成向量数据
  2. 怎么样加工向量化的数据,将其变成各种其他的表达形式

sentence understanding

上面这张图就诠释了这样的一个过程:

  1. 我们用Encoder将原始的我爱莫烦Python转变成标准的向量表达;
  2. 在用各种Decoder将向量化表达转变成其他的表达形式,其中就可以是翻译,图片,情感和对话。

所以从上面例子可以看出,Encoder是一种压缩器,去繁从简,将最有用的特征给识别出来,用最简练的信息表达他们。 这一点在AutoEncoder中也有很好的体现。 而Decoder是解压器,但是它并不是将压缩好的信息还原,而是解压成另外一种形式,换一种表达方式。

翻译

在这节内容中,我带大家以翻译为例,将这种句子理解的EncoderDecoder机制给大家贯穿一下。在翻译的这个例子中,我们有个更具体的名词, 叫做seq2seq. 意思是将一个 sequence 转换成另一个 sequence。也就是用Encoder压缩并提炼第一个sequence的信息,然后用Decoder将这个信息转换成另一种语言。

seq2seq illustration

秀代码

我使用一个非常简单,好训练的日期转换的例子来展示一下seq2seq的威力。需要实现的功能如下:

# 中文的 "年-月-日" -> "day/month/year"
"98-02-26" -> "26/Feb/1998"

我们将中文的顺序日期,转成英文的逆序日期,数据区间是20世纪后期到21世纪前期。 为了施加一些难度,在中文模式下,我不会告诉机器这是哪一个世纪,需要计算机自己去判断转成英文的时候是 20 世纪还是 21 世纪。

先来看训练过程(只想看全套代码的请点这里), 其实也很简单,生成数据,建立模型,训练模型。

最后你能看到它的整个训练过程。最开始预测成渣渣,但是后面预测结果会好很多。

t:  0 | loss: 3.289 | input:  96-06-17 | target:  17/Jun/1996 | inference:  /2222222222
t:  70 | loss: 1.132 | input:  91-08-19 | target:  19/Aug/1991 | inference:  13/Mar/2001<EOS>
t:  140 | loss: 0.880 | input:  11-04-30 | target:  30/Apr/2011 | inference:  11/May/2003<EOS>
t:  210 | loss: 0.732 | input:  76-03-14 | target:  14/Mar/1976 | inference:  24/May/1988<EOS>
....
t:  910 | loss: 0.064 | input:  29-10-12 | target:  12/Oct/2029 | inference:  12/Oct/2029<EOS>
t:  980 | loss: 0.035 | input:  79-06-17 | target:  17/Jun/1979 | inference:  17/Jun/1979<EOS>

接着我们就来具体看看模型是怎样搭建的。首先第一步要搭建压缩器encoder,有了encoder就可以将原始的词向量按顺序组装起来变成句向量。 有了这个句向量之后才能进行decode工作。

在seq2seq中,decoder在训练是和句子生成时是不同的。为了方便训练,尤其是在刚开始训练时,decoder的输入如果是True label,那么就能大大减轻训练难度。 不管在训练时有没有预测错,下一步在decoder的输入都是正确的。 training

而在生产环境中预测时,真的在做翻译时,我们就希望有另一种decode的sample方式。使decoder下一步的预测基于decoder上一步的预测,而不是true label。

inference

所以在seq2seq中,为了加快训练速度,我们一般使用的training和inference的decode方式是有所不同的。 inference的时候,那没办法,只能拿着上次decode的词作为下一步的input,我们并没有多少额外的信息,也没有真实label可以参考。 但是在training时却可以拿着label过来加强训练的有效性,达到快速收敛的效果,training如果沿着错误的方向一致错下去,是很难纠正的。 所以我们对training的预测错误视而不见,每次还是用正确的标签作为decoder输入

还能优化吗

但是使用GreedyEmbeddingSampler()作为decode的方法是有局限性的,有时候会因为忽略了前期的低分数而错过了后期的整体高分策略, 类似于前面芝麻最好,所以捡了芝麻,但后面却错过了捡西瓜的机会。而这种因局部信息不全而导致的策略不优,可以靠Beam search的筛选策略弥补。 如果使用 beam search, 我们不仅仅关注当前最优策略, 而且每预测一个词时,还保持关注当时刻所有候选词的N个最优策略,结束预测时,就有很大概率能够找到全局比较优的路径。 举个例子,如果我们用beam search size = 2, 意味着每次预测都记录最优的两个预测,然后沿着这两个预测继续预测, 每次后续的预测都只挑选下一步最好的两个预测。 这样加大了搜索范围,使我们有机会接触到全局较优路径。

beam search

总结

这一节内容我们使用的是一种RNN模型来产生句向量的embedding,RNN是我们的encoder。那么通常在图像领域比较有优势的CNN能不能也拿来做encoder呢? 答案是肯定的,下节内容我们来见识一下CNN是怎么做encoder或者语言模型的。


降低知识传递的门槛

莫烦很常从互联网上学习知识,开源分享的人是我学习的榜样。 他们的行为也改变了我对教育的态度: 降低知识传递的门槛免费 奉献我的所学正是受这种态度的影响。 通过 【赞助莫烦】 能让我感到认同,我也更有理由坚持下去。