写在前面

最近,由于在大规模语料集上训练的大型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∏T​P(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=argmax⁡wP(w∣w1:t−1)w_{t}=\operatorname{argmax}_{w} P\left(w | w_{1: t-1}\right)wt​=argmaxw​P(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-samplingnucleus-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采样策略也会存在生成重复序列的缺陷;
  • 最后,开放语言生成是一个快速发展的研究领域,通常情况下没有一种千篇一律的方法,因此必须了解哪种方法在特定的用例中最有效。

从不同解码策略看机器如何生成文本相关推荐

  1. 浅谈文本生成或者文本翻译解码策略《转》

    原文链接,感谢原作者 目录 一.文本生成和翻译的基本流程 翻译类模型的训练和解码 训练过程 解码过程 生成类模型的训练和解码(GPT系列) 训练过程 解码过程 二.解码策略 1.贪心搜索(greedy ...

  2. 浅谈文本生成或者文本翻译解码策略

    目录 一.文本生成和翻译的基本流程 翻译类模型的训练和解码 训练过程 解码过程 生成类模型的训练和解码(GPT系列) 训练过程 解码过程 二.解码策略 1.贪心搜索(greedy search) 2. ...

  3. 生成模型-解码策略小结

    解码方法小结 本文是笔者花费闲暇时间根据工作经历以及阅读文献总结的,如果对于屏幕前的隔着读者有些许帮助,真是欣慰之至.当然,各位读者的支持也是笔者写作的动力.麻烦一键三连.点赞,评论,收藏. 1. 简 ...

  4. 李宏毅-2023春机器学习 ML2023 SPRING-学习笔记:3/24机器如何生成图像

    目录 3/24 机器如何生成图像 速览图像生成常见模型 浅谈图像生成模型 Diffusion Model 原理 Stable Diffusion.DALL-E.Imagen 背后共同的套路 Varia ...

  5. Seq2Seq模型中的序列解码策略

    导读:在序列生成类任务中,如机器翻译.自动摘要等,Seq2Seq是一种非常强大的模型.作为一种条件语言模型,它直接对P(y|x)进行建模,在生成y的过程中,始终有x作为条件.当训练好了一个这样的模型后 ...

  6. 一文看懂「生成对抗网络 - GAN」基本原理+10种典型算法+13种应用

    生成对抗网络 – Generative Adversarial Networks | GAN 文章目录 GAN的设计初衷 生成对抗网络 GAN 的基本原理 GAN的优缺点 10大典型的GAN算法 GA ...

  7. 由扔骰子看平均概率生成

    由扔骰子看平均概率生成 昨天读到一个帖子,说如何通过扔骰子的方法得到7件事的平均概率情况(扔骰子只能得到6件事的均概率),其中一种解法为,扔两次,分别记为x,y,则定义计算式m=(x-1)*6+y,可 ...

  8. 研究音频编解码要看什么书

    前言...... 最近总是有人问研究音频编解码要看什么书 其实这是一个很难回答的问题,原因有很多. 首先,做工程首先一个问题就是和课本学习不同,不是看书能解决的. 其次,音频编解码技术在国内研究的人很 ...

  9. 人机对战的猜拳游戏,用户通过输 入(1.剪刀 2.石头 3.布),机器随机生成(1.剪刀 2.石头 3.布),胜者积分, n 局以后通过积分的多少判定胜负。

    看到题目后可以发现这题并不算太难,在思考解题方法之前就可以先把总体的框架写出来了,比如:进行游戏的次数,机器随机生成的范围已经用户所能输入的东西.如图所示: 这个时候我们就可以新建一个类,开始具体的操 ...

最新文章

  1. 新站SEO优化如何吸引搜索引擎蜘蛛的爬行?
  2. 设计模式之四-Factory模式
  3. iOS数据存储简要笔记
  4. android:自己实现能播放网络视频url的播放器
  5. java公平索非公平锁_java中的非公平锁不怕有的线程一直得不到执行吗
  6. 动态换ip如何实现_三种方法解决动态换IP需求
  7. k8s查看pod的yaml文件_K8s-yaml的使用及命令
  8. Opencv--warpPerspective +remap结合
  9. java增强connection类_关于DriverManager.getConnection()里的增强实现
  10. python sorted下标_初学者掌握python 列表需要知道的操作
  11. python右对齐函数_Python这68个内置函数,建议你吃透!
  12. 弥散张量分析开源软件 DSI Studio 简体中文汉化版可以下载了
  13. 搜索引擎漫谈以及 Zinc 简介
  14. 列联表分析基于R语言
  15. UVA 3713 Astronauts
  16. 使用FastReport进行基于富盛SBO程序开发框架的报表开发
  17. FineBI 的登录锁定配置修改
  18. 第一个Andriod应用
  19. 九个小众实用设计预览网站
  20. Connext DDSQoS参考

热门文章

  1. SAP License:SAP学习笔记
  2. LivePlayer.js免费直播、点播播放器如何自适应div宽高集成播放视频
  3. Samba服务器安装测试
  4. Spring的三大核心接口——BeanFactory、ApplicationContext、WebApplicationContext
  5. python-code-11
  6. Caffarelli 关于自由边界正则性的论文C1
  7. HTML5全屏浏览器兼容方案
  8. LINUX yum用法
  9. 20145227《Java程序设计》第10周学习总结
  10. 关于Dijkstra最短路径算法