从不同解码策略看机器如何生成文本
写在前面
最近,由于在大规模语料集上训练的大型Transformer-based语言模型的兴起(如著名的OpenAI-GPT2模型),社区对开放式语言生成的兴趣日益增加。 GPT2、XLNet、CTRL这些开放式语言生成的结果令人印象深刻,除了得益于优化的transformer架构和大量无监督的训练数据外,更好的解码方法也发挥了重要作用。
这篇文章我们简要概述了不同的解码策略,更重要的是展示了如何使用流行的transformers库轻松实现它们!
语言模型
自回归(auto-regressive)语言生成是基于这样一个假设,即整个序列的概率分布可以分解为下一个词条件分布的乘积,
P(w1:T∣W0)=∏t=1TP(wt∣w1:t−1,W0),with w1:0=∅P\left(w_{1: T} | W_{0}\right)=\prod_{t=1}^{T} P\left(w_{t} | w_{1: t-1}, W_{0}\right), \text { with } w_{1: 0}=\emptysetP(w1:T∣W0)=t=1∏TP(wt∣w1:t−1,W0), with w1:0=∅
其中W0W_{0}W0为初始上下文序列,TTT为你想要生成序列的长度(可调整)。
接下去我们将会详细介绍目前主流的解码方法,包括
- Greedy search
- Beam search
- Top-K sampling
- Top-p sampling
此外,为了防止干燥的原理讲解,我们还会给出对应的实践代码。那就先让我们加载模型吧,这里以GPT2为例,
Greedy Search
贪婪搜索简单地选择具有最高概率的单词作为它的下一个单词,在每一步考虑,
wt=argmaxwP(w∣w1:t−1)w_{t}=\operatorname{argmax}_{w} P\left(w | w_{1: t-1}\right)wt=argmaxwP(w∣w1:t−1)
下面的示意图清晰展示了贪婪搜索的工作原理,
从单词“ The”开始,该算法贪婪地选择下一个概率最高的单词“ nice”,依此类推,最终生成的单词序列为 { “ The”,“ nice”,“ woman”},其总体概率为0.5∗0.4=0.20.5*0.4=0.20.5∗0.4=0.2。
接下去我们以初始上下文,(“I”, “enjoy”, “walking”, “with”, “my”, “cute”, “dog”)为例,来看看GPT2的贪婪解码效果。
haha,仅仅使用两行代码我们就可以利用GPT2生成一个简短文本。从生成结果可以看到,根据上下文生成的单词是合理的,但是模型很快就会开始重复。 一般来说,这是语言生成中一个非常普遍的问题,尤其是在greedy search和beam search中。如果你想更深入了解,可以参考
- Diverse Beam Search: Decoding Diverse Solutions from Neural Sequence Models
- Generating High-Quality and Informative Conversation Responses with Sequence-to-Sequence Models
贪婪搜索的主要缺点是,它直接忽略了隐藏在低概率词后面的高概率词,如上图所示:
具有高条件概率0.9的单词{“ has”}隐藏在单词{“ dog”}后面,后者仅具有第二高的条件概率,因此贪婪搜索错过单词序列{“ The”,“ dog”,“ has”}。
为了缓解上面这个问题,我们可以使用beam search!
Beam Search
Beam Search通过在每个时间步保留最可能的几个假设数,并最终选择总体概率最高的一组假设,从而降低了丢失隐藏的高概率单词序列的风险。 举个栗子,我们设定num_beams = 2:
- 当timesetp=1timesetp=1timesetp=1,除了最可能的假设 {“ The”,“ woman”}外,beam search还跟踪第二个最可能的{“ The”,“ dog” };
- 当timestep=2timestep=2timestep=2,beam search发现单词序列{“ The”,“ dog”,“ has”}的概率为0.4∗0.9=0.360.4*0.9=0.360.4∗0.9=0.36,比{ “ The”,“ nice”,“ woman”}的概率大。
beam search将始终找到比greedy search具有更高概率的输出序列,但不能保证找到最可能的输出。让我们看看如何在transformers中使用beam search,
可以看出,虽然结果相较于greedy search更流畅,但输出仍包含重复的相同单词序列。
一种简单可用的补救方法是引入n-gram penalty 。 最常见的n-gram penalty 是通过将可能创建已经看到的n-gram的下一个单词的概率设置为0,来确保没有n-gram出现两次,可以参考
- OpenNMT: Open-Source Toolkit for Neural Machine Translation
- A Deep Reinforced Model for Abstractive Summarization
让我们通过设置no_repeat_ngram_size = 2
来尝试一下,以免2-gram
重复出现:
Nice,看起来好多了! 我们可以看到重复序列没有再出现。 但是,必须谨慎使用n-gram penalty,例如在生成有关New York
相关的文章不应使用2-gram penalty,否则城市名称在全文中只会出现一次。
beam search的另一个重要功能是,我们可以比较生成后的所有top beams徐磊,并选择最适合我们目的的已生成序列。
在transformers
中,我们只需将参数num_return_sequences
设置为应返回的最高得分序列的数量即可。 确保num_return_sequences <= num_beams
。
从结果可以看出,五个生成序列彼此之间只有些许不同,这在仅使用num_return_sequences=5
时并不奇怪。
在开放式生成任务中,beam search可能并不是最佳选择,主要有以下几个原因:
- beam search在机器翻译或摘要生成任务中表现较好,这是因为这些任务所生成的长度或多或少可预测的。 但是,对于开放式生成任务而言,情况并非如此,在这种情况下,所需的输出长度会发生很大变化,例如对话和故事生成;
- 我们已经看到,beam search严重受到重复生成的困扰。这很难用n-gram或其他惩罚来控制,因为要在强制的“不重复”和相同n-gram的重复循环之间找到良好的trade off,需要进行很多微调;
- 在ICLR2019的一篇论文The Curious Case of Neural Text Degeneration指出,高质量的人类语言不会遵循高概率的下一个单词的分布。 换句话说,作为人类,我们希望生成的文本使我们感到惊讶,而不是无聊或者可预测的,作者通过绘制概率图很好地证明了这一点。
哈哈,既然这样,那让我们停止无聊并加入一些随机性!
Sampling
采样意味着随机选择下一个单词,主要考虑其条件概率分布:
wt∼P(w∣w1:t−1)w_{t} \sim P\left(w | w_{1: t-1}\right)wt∼P(w∣w1:t−1)
以上面的示例为例,下图是采样时语言生成的可视化。
很明显,使用采样生成语言已不再是确定的了, 从条件概率分布P(w∣"The ")P\left(\left.w\right|"\text { The } "\right)P(w∣" The ")中采样单词出单词“ car”,然后从P(w∣"The ","car" )P(w | " \text { The } ", \text { "car" })P(w∣" The ", "car" )中采样出单词“ drives”。
在transformers
中,我们设置do_sample = True
并通过top_k = 0
停用Top-K采样(稍后会详细介绍)。 在下文中为了方便说明,我们设置random_seed = 0
,你可以随意更改random_seed
来尝试不同的生成效果。
尝试读一遍文本,会发现似乎还不错,但是仔细观察时,这并不太连贯和通顺。(怎么突然就"kill anybody"了,害怕) 在对单词序列进行采样时,会有一个大问题:这些模型经常产生语无伦次的胡言乱语,参考ICLR2020的一篇论文The Curious Case of Neural Text Degeneration。
一个技巧是使分布P(w∣w1:t−1)P\left(w | w_{1: t-1}\right)P(w∣w1:t−1)通过降低softmax temperature
来提高锐度,即增加高概率单词的可能性并降低低概率单词的可能性。
对上面示例添加temperature
后的可视化如下图,
让我们来看看代码吧,
看到了吗,奇奇怪怪的n-gram变少了,现在输出更加连贯了。使用temperature
可以使分布的随机性降低,当将temperature
设置为0 时,温度缩放的采样将等于贪婪解码,并且将遭受与以前相同的问题。
Top-K Sampling
来自FAIR的论文Hierarchical Neural Story Generation介绍了一种简单但十分有效的采样策略,称为Top-K Sampling
。在Top-K Sampling
中,将挑选出K个最有可能的下一个单词,并且仅在这K个下一个单词之间重新为它们分配概率。 GPT2就是采用了这种采样方案,这也是其生成故事效果不错的原因之一。
我们将上面示例中两个采样步中使用的单词范围从3个扩展到10个,以更好地说明Top-K采样。
上述设置K=6K=6K=6,将采样最有可能的6个单词,记为Vtop-K V_{\text {top-K }}Vtop-K 。在第一步采样中,Vtop-K V_{\text {top-K }}Vtop-K 包含了整体的2/3,第二步采样则包含了几乎全部,但是有效地去除了一些奇奇怪怪的单词。
哇这个结果非常棒,可以说是我们一路下来最真实的文本生成。 但是在使用Top-K采样时需要注意的一个问题是,它不会动态适应从下一个单词概率分布P(w∣w1:t−1)P\left(w | w_{1: t-1}\right)P(w∣w1:t−1)。 这可能是有问题的,因为某些单词可能是从非常尖锐的分布中采样的(上图右侧的分布),而另一些单词则是从更平坦的分布中采样的(上图左侧的分布)。
- 在第一步采样中,
Top-K Sampling
策略排除了对 {“ people”,“ big”,“ house”,“ cat”}进行采样的可能性 ,这些似乎是合理的候选单词; - 另一方面,在第二步采样中,在单词样本池中包括可能不合适的下一个单词{“down”,“ a”}。 因此,将样本池限制为固定大小KKK可能会危害模型以产生乱序的尖峰分布,并限制模型用于平坦分布的创造力。 这一motivation激发了
Top-p-sampling
或nucleus-sampling
,来自论文The Curious Case of Neural Text Degeneration。
Top-p (nucleus) sampling
在Top-p采样中,不是从仅最可能的K个单词中采样,而是从其累积概率超过一个阈值ppp的最小可能单词集中进行选择,然后将这组单词重新分配概率。 这样,单词集合的大小(也就是集合中单词的数量)可以根据下一个单词的概率分布动态地增加或减少。 上面的介绍有点枯燥,让我们来看看可视化图。
上图示例设置p=0.92p = 0.92p=0.92,定义为Vtop-p V_{\text {top-p }}Vtop-p ,所有单词累计概率超过0.92的最小单词子集。 在第一步采样中,包括了9个最有可能的单词,而在第二步采样中,只需选择前3个单词即可超过92%。 其实很简单! 上述过程可以看成,当下一个单词的可预测性不确定时,保留了较多的单词,例如 P(w∣′′The ′′)P\left(\left.w\right|^{\prime \prime} \text { The }^{\prime \prime}\right)P(w∣′′ The ′′);而当下一个单词看起来比较可预测时,只保留几个单词,例如P(w∣"The ",P(w | " \text { The } ",P(w∣" The ", “car”)。
Okay,code time!
从理论上讲,Top-p似乎比Top-K更为优雅,但两种方法在实践中均能很好地work, Top-p也可以与Top-K结合使用,这可以避免排名很低的单词,同时可以进行一些动态选择。让我们来看看综合使用Top-K和Top-P的生成效果,
随便唠唠
- 从我们上述实验看起来,Top-K和Top-P采样的方式似乎比传统的greedy search和beam search在开放式语言生成上效果要好;
- 不过,有研究表明NEURAL TEXT DEGENERATION WITH UNLIKELIHOOD TRAINING,greedy search和beam search的明显缺陷(产生重复的单词序列)主要是由模型训练方式而不是由解码方法引起的,当调整模型训练目标后,beam search可以生成比Top-P更流畅的文本;
- 在论文Consistency of a Recurrent Language Model With Respect to Incomplete Decoding中指出,Top-K和Top-P采样策略也会存在生成重复序列的缺陷;
- 最后,开放语言生成是一个快速发展的研究领域,通常情况下没有一种千篇一律的方法,因此必须了解哪种方法在特定的用例中最有效。
从不同解码策略看机器如何生成文本相关推荐
- 浅谈文本生成或者文本翻译解码策略《转》
原文链接,感谢原作者 目录 一.文本生成和翻译的基本流程 翻译类模型的训练和解码 训练过程 解码过程 生成类模型的训练和解码(GPT系列) 训练过程 解码过程 二.解码策略 1.贪心搜索(greedy ...
- 浅谈文本生成或者文本翻译解码策略
目录 一.文本生成和翻译的基本流程 翻译类模型的训练和解码 训练过程 解码过程 生成类模型的训练和解码(GPT系列) 训练过程 解码过程 二.解码策略 1.贪心搜索(greedy search) 2. ...
- 生成模型-解码策略小结
解码方法小结 本文是笔者花费闲暇时间根据工作经历以及阅读文献总结的,如果对于屏幕前的隔着读者有些许帮助,真是欣慰之至.当然,各位读者的支持也是笔者写作的动力.麻烦一键三连.点赞,评论,收藏. 1. 简 ...
- 李宏毅-2023春机器学习 ML2023 SPRING-学习笔记:3/24机器如何生成图像
目录 3/24 机器如何生成图像 速览图像生成常见模型 浅谈图像生成模型 Diffusion Model 原理 Stable Diffusion.DALL-E.Imagen 背后共同的套路 Varia ...
- Seq2Seq模型中的序列解码策略
导读:在序列生成类任务中,如机器翻译.自动摘要等,Seq2Seq是一种非常强大的模型.作为一种条件语言模型,它直接对P(y|x)进行建模,在生成y的过程中,始终有x作为条件.当训练好了一个这样的模型后 ...
- 一文看懂「生成对抗网络 - GAN」基本原理+10种典型算法+13种应用
生成对抗网络 – Generative Adversarial Networks | GAN 文章目录 GAN的设计初衷 生成对抗网络 GAN 的基本原理 GAN的优缺点 10大典型的GAN算法 GA ...
- 由扔骰子看平均概率生成
由扔骰子看平均概率生成 昨天读到一个帖子,说如何通过扔骰子的方法得到7件事的平均概率情况(扔骰子只能得到6件事的均概率),其中一种解法为,扔两次,分别记为x,y,则定义计算式m=(x-1)*6+y,可 ...
- 研究音频编解码要看什么书
前言...... 最近总是有人问研究音频编解码要看什么书 其实这是一个很难回答的问题,原因有很多. 首先,做工程首先一个问题就是和课本学习不同,不是看书能解决的. 其次,音频编解码技术在国内研究的人很 ...
- 人机对战的猜拳游戏,用户通过输 入(1.剪刀 2.石头 3.布),机器随机生成(1.剪刀 2.石头 3.布),胜者积分, n 局以后通过积分的多少判定胜负。
看到题目后可以发现这题并不算太难,在思考解题方法之前就可以先把总体的框架写出来了,比如:进行游戏的次数,机器随机生成的范围已经用户所能输入的东西.如图所示: 这个时候我们就可以新建一个类,开始具体的操 ...
最新文章
- 新站SEO优化如何吸引搜索引擎蜘蛛的爬行?
- 设计模式之四-Factory模式
- iOS数据存储简要笔记
- android:自己实现能播放网络视频url的播放器
- java公平索非公平锁_java中的非公平锁不怕有的线程一直得不到执行吗
- 动态换ip如何实现_三种方法解决动态换IP需求
- k8s查看pod的yaml文件_K8s-yaml的使用及命令
- Opencv--warpPerspective +remap结合
- java增强connection类_关于DriverManager.getConnection()里的增强实现
- python sorted下标_初学者掌握python 列表需要知道的操作
- python右对齐函数_Python这68个内置函数,建议你吃透!
- 弥散张量分析开源软件 DSI Studio 简体中文汉化版可以下载了
- 搜索引擎漫谈以及 Zinc 简介
- 列联表分析基于R语言
- UVA 3713 Astronauts
- 使用FastReport进行基于富盛SBO程序开发框架的报表开发
- FineBI 的登录锁定配置修改
- 第一个Andriod应用
- 九个小众实用设计预览网站
- Connext DDSQoS参考