论文分享 -- NLP -- grid beam search

博客内容将首发在微信公众号"跟我一起读论文啦啦",上面会定期分享机器学习、深度学习、数据挖掘、自然语言处理等高质量论文,欢迎关注!
在这里插入图片描述

本篇博文主要总结论文 Lexically Constrained Decoding for Sequence Generation Using Grid Beam Search,论文链接 gbs,参考的实现代码 codes。

首先不得不说,对于初学者来说,beamsearch是一种稍微难理解的算法,而在此算法上衍生的grid beam search就更复杂了,因此本论文读起来有一定的难度。

论文动机

  • 普通的beamsearch是由贪心的方法找到目前最优的生成序列,但是这种方法在交互翻译场景可能并不适用,例如交互翻译中的输入提示,又或者可以根据一些先验额外的知识,限定生成的句子里必须包含一些约束词,这时普通的beamsearch无法完成。
  • 本论文提出了一种非常通用的方法,可以在不需要修改模型参数或训练数据的情况下,将附加的先验知识加入到模型的输出中(也就是仅仅应用在预测阶段)。论文中的实验证明了该方法在一些交互翻译预测场景中的有效性。

模型

这里先对几个术语进行明确

  • hypothesis : 一个搜索路径
  • beam:一束搜索路径,可以理解为上一个timestep得到的top_BeamSize个hyps组成的。

beam 是一束搜索路径,每一个搜索路径(hypothesis)都会生成一个序列。所以一个 beam 会生成 B 个序列。每个hypothesis 在一个step都会产生 topk 个 hypotheses,一个 beam 就会产生 B * k 个hypothesis,但是会从里面再选择 B 个做成一个新的beam

BeamSearch简介

下面以beamsize=3, k=6举例
论文分享 -- NLP -- grid beam search_第1张图片
这里其实可以证明,在beamsize=3时,k=3或k=6都能取到最优解,但是k<3时则不能。
论文分享 -- NLP -- grid beam search_第2张图片

grid beam search

  • constraint tokens:由token组成的约束词,里面可能有短语(既某几个token必须连续出现)
  • t:timestep
  • c:表示当前beam(下图的一个方框)内的hypothesis已经覆盖了多少个约束词。
  • 注意,每个timestep的c只能覆盖一个token(不能一次覆盖一个短语),也就是constraints是一个序列数组, c o n s t r a i n t s i , j constraints_{i,j} constraintsi,j 表示 词表中第j个token为第i个约束词。
  • numC:表示所有约束词数量
    论文分享 -- NLP -- grid beam search_第3张图片

上面算法流程中,Grid可以理解为一个二维数组,如下图:

论文分享 -- NLP -- grid beam search_第4张图片
横轴为timesteps维度,纵轴为c维度,表示当前step已经覆盖了几个约束词。Grid[i][j] 表示在第i个step上,覆盖了j个约束词的所有hyps,一个方格可以理解为一个beam;

算法流程有三层遍历,最外层为timestep上的遍历,次外层为在c维度上的遍历(这里需要注意c维度上遍历,遍历范围并不是(0-c),而是在不同的timestep上,c的范围不一样,如上图中实线所示。),最内层为在beam(方格)内所有hyps上的遍历。

这里注意下 第二层遍历的范围:

for  c = max(0, (numC+t) -maxLen), c++, c<= min(t, numC)

第二层遍历是在纵轴上(竖向)上遍历

  • c < = m i n ( t , n u m C ) c <= min(t, numC) c<=min(t,numC) 显然在每个timestep上,当约束词个数达到numC时,c不增加了。当t
  • c = m a x ( 0 , ( n u m C + t ) − m a x L e n c = max(0, (numC+t) - maxLen c=max(0,(numC+t)maxLen,思考一个临界步长t,当timestep到达一定t时,还没有生成一个约束词时,这个hyp往后需要一直生成约束词直到达到max_steps,而在这个临界步长t之前,可以一直不生成约束词,故此时c=0,临界步长t之后,c= (numC+t) - maxLen。

当需要求Grid[i][j[的所有hyps时,可以由以下三种策略获取:

  • start_constraint:遍历Grid[i-1][j-1] 内的所有hyps,过滤掉have_unfinished_constraint状态(不是生成短语的第一个词的状态)的hyp,在模型词表分布上,让每个hyp从其还没生成的约束词里选一个约束词生成,形成长度加1的hyp,这样的新hyp就是Grid[i][j]里面的hyps的一部分
  • continue_constraint:遍历Grid[i-1][j-1] 内的have_unfinished_constraint状态(不是生成短语的第一个词的状态)的hyps,让每个hyp在生成后一个指定的约束词,这样组形成长度加1的hyp,这样的新hyp就是Grid[i][j]里面的hyps的一部分
  • generate:遍历Grid[i-1][j] 内的hyps,和普通的beamsearch一样,在词表概率分布上生成一个词,这个词不是约束词,这样组形成长度加1的hyp,这样的新hyp就是Grid[i][j]里面的hyps的一部分。显然当一个hyp在没有达到max_steps时,并且已经生成所有约束词后,后面的steps只能以generate方式生成。

由上面分析可知:上图中每列的每个方格(beam)是独立的

经过上面的总结,我们可知,一个beam内的hyps 可以分为以下两种方式:

  • open hypothesis:start_constraint 和 generate 的生成方式,在模型词表分布上选取一个词生成,只不过start只能从约束词集里选
  • closed hypothesis:短语的中间状态,只能生成下一个指定的词

一旦一个hypothesis生成了EOS,则终止该hyp,并将其装进 “已完成的hyps集合中,该集合内的每个hyp都覆盖了所有约束词”,最终模型在这个集合中选取平均概率最大hyp作为生成序列。

时间复杂度分析

普通的beamsearch的时间复杂度为 O ( k t ) O(kt) O(kt),grid-beam-search时间复杂度为 O ( k t c ) O(ktc) O(ktc),其中k为beamsize,t为timesteps,c为约束词数量。由于每列的方格(beam)是独立的,可以并行计算,同时耗时最多的为在hyps在约束词上的计算,减小beamsize可以大幅加快计算。

代码实现

代码实现略复杂

首先肯定得写个类,描述下hypothesis

论文分享 -- NLP -- grid beam search_第5张图片

其次要写个类,描述Beam

论文分享 -- NLP -- grid beam search_第6张图片

最后是GBSDecoder类

论文分享 -- NLP -- grid beam search_第7张图片

你可能感兴趣的:(论文,自然语言处理)