点击蓝字,关注我们
全文3646字,预计阅读时间10分钟。
GEEK TALK
01
对比搜索(contrastive_search)
对比搜索给定前缀文本
语言模型输出的概率分布
第一项,即 模型置信度 (model confidence),是语言模型预测的每个候选词元 v 的概率。
第二项, 退化惩罚 (degeneration penalty),用于度量候选token v 与上文
总结来说,对比搜索在生成输出时会同时考虑:
语言模型预测的概率,以保持生成文本和前缀文本之间的语义连贯性。
与上文的相似性以避免模型退化。
# generate the result with contrastive search
output = model.generate(
input_ids,
penalty_alpha=0.6, # 对比搜索中的超参 $\alpha$
top_k=4, # 对比搜索中的超参 $k$。
max_length=512
)
GEEK TALK
02
贪心搜索(greedy_search)
贪心搜索在每个时间步
问题:
容易输出重复的文本,这在语言生成中是一个非常普遍的问题,在贪心搜索和波束搜索中似乎更是如此
主要缺点是它错过了隐藏在低概率词后面的高概率词:The -> dog -> has (0.4*0.9=0.36),The -> nice -> wman (0.5*0.4=0.20),波束搜索可以缓解此类问题
GEEK TALK
03
波束搜索(beam_search)
波束搜索整个过程可以总结为: 分叉、排序、剪枝,如此往复。波束搜索通过在每个时间步保留最可能的 num_beams 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。
下图示例 num_beams=2:
波束搜索一般都会找到比贪心搜索概率更高的输出序列,但仍不保证找到全局最优解。
虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 n-grams (即连续 n 个词的词序列) 惩罚:最常见的 n-grams 惩罚是确保每个 n-gram 都只出现一次,方法是如果看到当前候选词与其上文所组成的 n-gram 已经出现过了,就将该候选词的概率设置为 0。通过设置 no_repeat_ngram_size=2 来试试,这样任意 2-gram 不会出现两次:
beam_output = model.generate(
max_length=50,
num_beams=5,
no_repeat_ngram_size=2, # n-grams
early_stopping=True
)
但是,n-gram 惩罚使用时必须谨慎,如一篇关于纽约这个城市的文章就不应使用 2-gram 惩罚,否则,城市名称在整个文本中将只出现一次!
波束搜索已被证明依然会存在重复生成的问题。在『故事生成』这样的场景中,很难用 n-gram 或其他惩罚来控制,因为在“不重复”和最大可重复 n-grams 之间找到一个好的折衷需要大量的微调。正如 Ari Holtzman 等人 (2019) (https://arxiv.org/abs/1904.09751)所论证的那样,高质量的人类语言并不遵循最大概率法则。这是因为人类语言具有创造性和惊喜性,而不仅仅是简单的预测性。
因此,引入随机性和创造性元素是生成更有趣和多样性文本的关键。
GEEK TALK
04
采样(sampling)
4.1 采样
使用采样方法时文本生成本身不再是确定性的(do_sample=True)。
# activate sampling and deactivate top_k by setting top_k sampling to 0
sample_output = model.generate(
do_sample=True,
max_length=50,
top_k=0
)
对单词序列进行采样时的问题:模型通常会产生不连贯的乱码,缓解这一问题的一个技巧是通过降低 softmax的“温度”使分布
sample_output = model.generate(
do_sample=True,
max_length=50,
top_k=0,
temperature=0.7
)
虽然温度可以使分布的随机性降低,但极限条件下,当“温度”设置为 0 时,温度缩放采样就退化成贪心解码了,因此会遇到与贪心解码相同的问题。
4.2 Top-k 采样
在 Top-K 采样中,概率最大的 K 个词会被选出,然后这 K 个词的概率会被重新归一化,最后就在这重新被归一化概率后的 K 个词中采样。GPT2 采用了这种采样方案,这也是它在故事生成这样的任务上取得成功的原因之一。
假设 p=0.92,Top-p 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 p=92% 的单词集作为采样池,定义为
可以看出,在单词比较不可预测时(例如更平坦的左图),它保留了更多的候选词,如
# deactivate top_k sampling and sample only from 92% most likely words
sample_output = model.generate(
do_sample=True,
max_length=50,
top_p=0.92,
top_k=0
)
虽然从理论上讲, Top-p 似乎比 Top-K 更优雅,但这两种方法在实践中都很有效。Top-p 也可以与 Top-K 结合使用,这样可以避免排名非常低的词,同时允许进行一些动态选择。如果 k 和 p 都启用,则 p 在 k 之后起作用。
# 配置 top_k = 50 、 top_p = 0.95 、 num_return_sequences = 3
sample_outputs = model.generate(
input_ids,
do_sample=True,
max_length=50,
top_k=50,
top_p=0.95,
num_return_sequences=3
)
END