流畅chatbot采样

coherent&surprise response

Posted by OD on December 6, 2020

流畅chatbot采样

1. introduction

​  这篇博客可以作为chatbot旅程的终点了,前面已经介绍了模型相关的工作,那么做完模型训练以后,剩下的就是生成了。要注意的是,模型生成的内容并不是和训练过程类似的,要想生成流畅且通顺的response还是需要一些额外的处理,这里会介绍一些生成相关的工作,以便让自己训练的模型有用武之地,毕竟,辛辛苦苦做出来的东西,能用且可用才是最让自己有成就感的。

2. 生成方法

 每次预测的时候选择概率最大的那个token,最简单,不过效果比较差。

 采样公式:

\[w_{t}=argmax_{w}P(w|w_{1:t-1}) \quad 时间步t采样\]

采样图示,红线为采样路径

 该方法其实是贪心算法的应用,缺陷在于虽然每个t都取最优值,不过最终得到的句子可能并不是最优的。真实应用的时候产生的response通常质量并不高,比如使用gpt2模型从“I enjoy walking with my cute dog”开始生成文本,其结果可能是“I enjoy walking with my cute dog, but I’m not sure if I’ll ever be able to walk with my dog. I’m not sure if I’ll ever be able to walk with my dog.”

 差不多相当于多路greedy search

beam search:保留num_beams路序列,每次从上个num_beams路序列生成下个num_beams路序列,上图为num_beams=2路序列生成过程,生成完成以后从num_beams个序列中根据需要选择适合自己任务的序列。

beam search表现要强于greedy search,不过,它也不是完美的:

  • beam search会消耗更多资源,num_beams越大则资源消耗越大。
  • beam search在生成的序列长度或多或少是可以预测的任务,比如机器翻译等任务重表现很好,不过在生成的序列长度变化非常大的开放类生成任务比如会话或者故事生成中表现并不是太好。
  • Ari Holtzman et al. (2019)等人提出,高质量的人类语言并不遵循下个词的高概率分布。换句话说,作为人类,我们希望生成的文本能给我们带来惊喜,而不是枯燥/可预测的,概率高的句子可能并不是最好的,因为概率最高的句子通常是generic, repetitive, and awkward

模型会给出的文本输出与beam search给出的输出的对比。

2.3 sampling

 要想生成的文本更具surprise,一个很自然的想法就是引入randomness。最简单的sampling即是根据条件概率分布随机取下一个word $w_{t}$,不过,这样做的话基本可以预料到结果不会很理想,因为随机采样到话无法避免选到一个概率很低的word,一旦出现这种情况,由于后续的word要依赖于前面的word,这必然会导致输出的文本变得语义不明,令人费解。

 [Ari Holtzman et al. (2019)将这种现象称之为:an unreliable tail,需要进行truncate处理。

2.4 temperature sampling

 随机的sampling有概率采到tail的无关的词,那么可以通过对softmax引入temperature加以缓解:

\[P(x|x_{1:t-1})=\frac {exp(\mu _{t}/t)}{\sum_{t^{'}}exp(\mu_{t^{'}}/t)}\quad t \in[0,1)\]

 考虑到softmax函数的特性可知,当temperature t<1的时候,新的概率分布是变的比较sharp的,也就是大的更大,小的更小,符合马太效应,这时候模型就会有更高的概率选择高频词,而忽略低频词。

 另外注意,对该供水,当 [公式] 时,就变成了greedy decoding;当 [公式] 时,就变成了uniform sampling。这样通过调整t的大小,就可以缓解(而不是解决)sampling from tail distribution

2.5 Top-K sampling

Facebook于2018年提出的算法,本来是用于辅助他们的seq2seq模型的,不过可以泛化到其他模型中去。

 其思路非常简单,不过效果却更好。其做法是在选取下一个token的时候,选取概率最高的ktokens,然后做归一化得到新的概率分布$P^{‘}$,然后以$P^{‘}$从ktokens中随机选取。

 这种方法存在的问题是,k需要事先确定,而由于概率分布是多样的,同样的k在某个概率分布下加和可能比较大,比如达到0.8,而在有的概率分布下可能只有0.6,加和不大的情况可能导致我们漏选了后面的许多token,缺乏灵活性。

固定的k无法动态适应概率分布变化较大的情况

 如上图所示,设k=10,第一句话“She said, ‘I never”后面可以跟的选项能有很大的diversity,此时10个tokens或许不足以包含全部可能的选择;而第二句话“I ate the pizza while it was still”后面可以跟的选项则不能有太大的diversity,否则会使得整个句子含义表达错乱,此时10个tokens就变得过多了,会让模型陷入sample from tail distribution的风险。

2.6 Top-P sampling

 针对top-k的问题的改进算法,保证选取的tokens的概率加和$>=$一个实现设定的常数概率阈值:$p^{‘}\in(0,1)$,这种处理方式可以比较好的动态适应不同的概率分布情况。

 transformers库中top-k和top-p不是互斥的,可以结合使用。

 不过注意,top-k与top-p的引进毕竟也会导致超参数,所以也需要精细调节,不然采样的效果也不怎么样,实践中一般top-k与top-p不结合使用,常用的是top-k=0, top-p=0.9,如果设置有温度概念,常用的temperature=0.7

3.conclusion

 目前来说,top-p sampleing是最好的,不过不排除未来会出现更好的采样算法,另外就是有研究表明top类算法也会产生重复,这个需要自己结合自己的项目去验证了。