赞
踩
在自然语言生成的任务中,如何对训练好的模型进行解码(decode)是一个火热的研究话题。
例如,在自回归式的生成中,模型预测的生成序列 y 的第 t 个值 yt 往往是预测出一个概率分布 p(yt|y<t) ,亦或是条件式的p(yt|x,y<t)。 p 往往是通过模型对词表 V 中的每个词预测一个未经过归一化的激活值 q(yt|y<t) ,然后进行softmax获得,即p(yt|y<t)=eq(yt|y<t)∑v∈Veq(v|y<t))。我们还可以通过加入温度 τ 来让整个分布的熵增加或者减少,即 p(yt|y<t)=eq(yt|y<t)/τ∑v∈Veq(v|y<t))/τ 。在温度比较大时, p 更偏向于均匀分布。
对自回归的生成来说,在确定了如何表示 p 之后,就可以制定解码策略了。最简单的两个策略是(1)greedy decoding,每一步都直接选取概率最高的词;(2)beam search,每一步保留若干个概率最高的序列。对这两种方法不太熟悉的朋友也可以先看这篇很好的简介。近几年的很多工作都提到,这两种策略在自然语言生成中并非最佳,往往会生成很多空序列、无意义序列、重复序列等等 [1, 2, 4, 5]。
上述两种策略都是确定性的解码,固定模型和温度之后,每次得到的序列都是相同的,而另一种方案是使用随机解码,比如采样(sampling),即每一步都直接利用 p 采样生成的词。采样可以增加生成的多样性,但是概率分布的长尾也增加了生成句子不连贯的可能性。为了解决这一问题,top-k [1],top-p (nucleus) [2], typical [3]等方法在采样前对 p 进行剪枝。本文就逐一介绍这三种方法,以及如何在PyTorch较为高效地实现它们。本文主要参考了Huggingface的实现,在实际使用中,如果使用Huggingface,可以直接使用实现好的各种LogitsWarper,不必重复造轮子。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。