如何生成文本: 通过 Transformers 用不同的解码方法生成文本

如何生成文本: 通过 Transformers 用不同的解码方法生成文本

假设 $p=0.92$,Top-p 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 $p=92%$ 的单词集作为采样池,定义为 $V_{\text{top-p}}$。在 $t=1$ 时 $V_{\text{top-p}}$ 有 9 个词,而在 $t=2$ 时它只需要选择前 3 个词就超过了 92%。其实很简单吧!可以看出,在单词比较不可预测时,它保留了更多的候选词, $P(w | \text{“The”})$,而当单词似乎更容易预测时,只保留了几个候选词, $P(w | \text{“The”}, \text{“car”})$。近年来,随着以 OpenAI GPT2 模型 为代表的基于数百万网页数据训练的大型 Transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注。开放域中的条件语言生成效果令人印象深刻,典型的例子有: GPT2 在独角兽话题上的精彩续写,XLNet 以及 使用 CTRL 模型生成受控文本 等。促成这些进展的除了 transformer 架构的改进和大规模无监督训练数据外,更好的解码方法 也发挥了不可或缺的作用。

本文简述了不同的解码策略,同时向读者展示了如何使用流行的 transformers​ 库轻松实现这些解码策略!

下文中的所有功能均可用于 自回归 语言生成任务 (点击 此处 回顾)。简单复习一下, 自回归 语言生成是基于如下假设: 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积。

$P(w_{1:T} | W_0 ) = \prod_{t=1}^T P(w_{t} | w_{1: t-1}, W_0) \text{ , 其中 } w_{1: 0} = \emptyset,$

本文绍目前最常用的解码方法,主要有 贪心搜索 (Greedy search)波束搜索 (Beam search)Top-K 采样 (Top-K sampling) 以及 Top-p 采样 (Top-p sampling)

贪心搜索

贪心搜索在每个时间步 $t$ 都简单地选择概率最高的词作为当前输出词: $w_t = argmax_{w}P(w | w_{1:t-1})$ ,如下图所示。

greedy_search

从单词 $\text{“The”}$ 开始,算法在第一步贪心地选择条件概率最高的词 $\text{“nice”}$ 作为输出,依此往后。最终生成的单词序列为 $(\text{“The”}, \text{“nice”}, \text{“woman”})$,其联合概率为 $0.5 \times 0.4 = 0.2$。贪心搜索的主要缺点是它错过了隐藏在低概率词后面的高概率词,如上图所示:

条件概率为 $0.9$ 的单词 $\text{“has”}$ 隐藏在单词 $\text{“dog”}$ 后面,而 $\text{“dog”}$ 因为在 `t=1`​ 时条件概率值只排第二所以未被选择,因此贪心搜索会错过序列 $\text{“The”}, \text {“dog”}, \text{“has”}$ 。

波束搜索

波束搜索通过在每个时间步保留最可能的 num_beams​ 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。以 num_beams=2​ 为例:

beam_search

在时间步 1,除了最有可能的假设 $(\text{“The”}, \text{“nice”})$,波束搜索还跟踪第二可能的假设 $(\text{“The”}, \text{“dog”})$。在时间步 2,波束搜索发现序列 $(\text{“The”}, \text{“dog”}, \text{“has”})$ 概率为$0.36$,比 $(\text{“The”}, \text{“nice”}, \text{“woman”})$ 的 $0.2$ 更高。太棒了,在我们的例子中它已经找到了最有可能的序列!波束搜索一般都会找到比贪心搜索概率更高的输出序列,但仍不保证找到全局最优解。

让我们看看如何在 transformers​ 中使用波束搜索。我们设置 num_beams > 1​ 和 early_stopping=True​ 以便在所有波束达到 EOS 时直接结束生成。

# activate beam search and early_stopping
beam_output = model.generate(
    input_ids, 
    max_length=50, 
    num_beams=5, 
    early_stopping=True
)

print("Output:\n" + 100 * '-')
print(tokenizer.decode(beam_output[0], skip_special_tokens=True))

Output:
----------------------------------------------------------------------------------------------------
I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.

I'm not sure if I'll ever be able to walk with him again. I'm not sure if I'll

虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 n-grams (即连续 n 个词的词序列) 惩罚,该方法是由 Paulus 等人 (2017) 和 Klein 等人 (2017) 引入的。最常见的 n-grams 惩罚是确保每个 n-gram 都只出现一次,方法是如果看到当前候选词与其上文所组成的 n-gram 已经出现过了,就将该候选词的概率设置为 0。但是,n-gram 惩罚使用时必须谨慎,如一篇关于纽约这个城市的文章就不应使用 2-gram 惩罚,否则,城市名称在整个文本中将只出现一次!

波束搜索的另一个重要特性是我们能够比较概率最高的几个波束,并选择最符合我们要求的波束作为最终生成文本。

开放域文本生成的研究人员最近提出了几个理由来说明对该领域而言波束搜索可能不是最佳方案:

  • 在机器翻译或摘要等任务中,因为所需生成的长度或多或少都是可预测的,所以波束搜索效果比较好 - 参见 Murray 等人 (2018) 和 Yang 等人 (2018) 的工作。但开放域文本生成情况有所不同,其输出文本长度可能会有很大差异,如对话和故事生成的输出文本长度就有很大不同。
  • 我们已经看到波束搜索已被证明存在重复生成的问题。在故事生成这样的场景中,很难用 n-gram 或其他惩罚来控制,因为在“不重复”和最大可重复 n-grams 之间找到一个好的折衷需要大量的微调。
  • 正如 Ari Holtzman 等人 (2019) 所论证的那样,高质量的人类语言并不遵循最大概率法则。换句话说,作为人类,我们希望生成的文本能让我们感到惊喜,而可预测的文本使人感觉无聊。论文作者画了一个概率图,很好地展示了这一点,从图中可以看出人类文本带来的惊喜度比波束搜索好不少。

Screen_Shot_2019_05_08_at_3_06_36_PM-1557342561886

因此,让我们开始玩点刺激的,引入一些随机性🤪。

采样

在其最基本的形式中,采样意味着根据当前条件概率分布随机选择输出词 $w_t$: $w_t \sim P(w|w_{1:t-1})$

继续使用上文中的例子,下图可视化了使用采样生成文本的过程。

sampling_search

很明显,使用采样方法时文本生成本身不再是 确定性的。单词 $\text{“car”}$ 从条件概率分布 $P(w | \text{“The”})$ 中采样而得,而 $\text{“drives”}$ 则采样自 $P(w | \text{“The”}, \text{“car”})$。在 transformers​ 中,我们设置 do_sample=True​ 并通过设置 top_k=0​ 停用 Top-K 采样 (稍后详细介绍)。在下文中,为便于复现,我们会固定 random_seed=0​,但你可以在自己的模型中随意更改 random_seed​。

# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)

# activate sampling and deactivate top_k by setting top_k sampling to 0
sample_output = model.generate(
    input_ids, 
    do_sample=True, 
    max_length=50, 
    top_k=0
)

print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))

Output:
----------------------------------------------------------------------------------------------------
I enjoy walking with my cute dog. He just gave me a whole new hand sense."

But it seems that the dogs have learned a lot from teasing at the local batte harness once they take on the outside.

"I take

生成的文本看起来不错 - 但仔细观察会发现它不是很连贯。3-gramsnew hand senselocal batte harness 非常奇怪,看起来不像是人写的。这就是对单词序列进行采样时的大问题: 模型通常会产生不连贯的乱码,参见​Ari Holtzman 等人 (2019) 的论文。

缓解这一问题的一个技巧是通过降低所谓的 softmax 的“温度”使分布 $P(w|w_{1:t-1})$ 更陡峭。而降低“温度”,本质上是增加高概率单词的似然并降低低概率单词的似然。将温度应用到于我们的例子中后,结果如下图所示。

sampling_search_with_temp

$t=1$ 时刻单词的条件分布变得更加陡峭,几乎没有机会选择单词 $\text{“car”}$ 了。

# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)

# use temperature to decrease the sensitivity to low probability candidates
sample_output = model.generate(
    input_ids, 
    do_sample=True, 
    max_length=50, 
    top_k=0, 
    temperature=0.7
)

print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))

Output:
----------------------------------------------------------------------------------------------------
I enjoy walking with my cute dog, but I don't like to be at home too much. I also find it a bit weird when I'm out shopping. I am always away from my house a lot, but I do have a few friends

奇怪的 n-gram 变少了,现在输出更连贯了!虽然温度可以使分布的随机性降低,但极限条件下,当“温度”设置为 $0$ 时,温度缩放采样就退化成贪心解码了,因此会遇到与贪心解码相同的问题。

Top-K 采样

Fan 等人 (2018) 的论文介绍了一种简单但非常强大的采样方案,称为 Top-K 采样。在 Top-K 采样中,概率最大的 K 个词会被选出,然后这 K 个词的概率会被重新归一化,最后就在这重新被归一化概率后的 K 个词中采样。 GPT2 采用了这种采样方案,这也是它在故事生成这样的任务上取得成功的原因之一。

我们将上文例子中的候选单词数从 3 个单词扩展到 10 个单词,以更好地说明 Top-K 采样。

top_k_sampling

设 $K = 6$,即我们将在两个采样步的采样池大小限制为 6 个单词。我们定义 6 个最有可能的词的集合为 $V_{\text{top-K}}$。在第一步中,$V_{\text{top-K}}$ 仅占总概率的大约三分之二,但在第二步,它几乎占了全部的概率。同时,我们可以看到在第二步该方法成功地消除了那些奇怪的候选词 $(\text{“not”}, \text{“the”}, \text{“small”}, \text{“told”})$。现在还有一个问题,Top-K 采样不会动态调整从需要概率分布 $P(w|w_{1:t-1})$ 中选出的单词数。这可能会有问题,因为某些分布可能是非常尖锐 (上图中右侧的分布),而另一些可能更平坦 (上图中左侧的分布),所以对不同的分布使用同一个绝对数 K 可能并不普适。在 $t=1$ 时,Top-K 将 $(\text{“people”}, \text{“big”}, \text{“house”}, \text{“cat”})$ 排出了采样池,而这些词似乎是合理的候选词。另一方面,在$t=2$ 时,该方法却又把不太合适的 $(\text{“down”}, \text{“a”})$ 纳入了采样池。因此,将采样池限制为固定大小 K 可能会在分布比较尖锐的时候产生胡言乱语,而在分布比较平坦的时候限制模型的创造力。这一发现促使 Ari Holtzman 等人 (2019) 发明了 Top-p- 或 - 采样。

Top-p (核) 采样

Top-p 中,采样不只是在最有可能的 K 个单词中进行,而是在累积概率超过概率 p 的最小单词集中进行。然后在这组词中重新分配概率质量。这样,词集的大小 (又名 集合中的词数) 可以根据下一个词的概率分布动态增加和减少。好吧,说的很啰嗦,一图胜千言。

top_p_sampling

假设 $p=0.92$,Top-p 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 $p=0.92$ 的单词集作为采样池,定义为 $V_{\text{top-p}}$。在 $t=1$ 时 $V_{\text{top-p}}$ 有 9 个词,而在 $t=2$ 时它只需要选择前 3 个词就超过了 92%。其实很简单吧!可以看出,在单词比较不可预测时,它保留了更多的候选词, $P(w | \text{“The”})$,而当单词似乎更容易预测时,只保留了几个候选词, $P(w | \text{“The”}, \text{“car”})$。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/318283.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

串行Nor Flash的结构和参数特性

文章目录 引言1、Nor Flash的结构2、Nor Flash的类别3.标准Serial Nor Flash的特征属性1.Wide Range VCC Flash2.Permanent Lock3.Default Lock Protection4.Standard Serial Interface5.Multi-I/O6.Multi-I/O Duplex (DTR)7.XIP(片上执行) 4.标准Serial…

Java SE入门及基础(11)

程序调试 1. 什么是程序调试 当程序出现问题时,我们希望程序能够暂停下来,然后通过我们操作使代码逐行执行,观察整个过程中变量的变化是否按照我们设计程序的思维变化,从而找问题并解决问题,这个过程称之为程序调试…

Openstack组件glance对接swift

2、glance对接swift (1)可直接在数据库中查看镜像存放的位置、状态、id等信息 (2)修改glance-api的配置文件,实现对接swift存储(配置文件在/etc/glance/glance-api.conf,建议先拷贝一份&#x…

基于反卷积方法的重大突破:结构光系统中的测量误差降低3倍

作者:小柠檬 | 来源:3DCV 在公众号「3DCV」后台,回复「原论文」可获取论文pdf 结构光三维测量技术在工业自动化、逆向工程和图形学领域越来越受欢迎。然而,现有的测量系统在成像过程中存在不完美,会导致在不连续边缘周…

nuxt pm2使用、启动、问题解决方案

pm2简介 pm2是一个进程管理工具,可以用它来管理node进程,并查看node进程的状态,当然也支持性能监控,进程守护,负载均衡等功能,在前端和nodejs的世界中用的很多 pm2安装 安装pm2: $ npm install -g pm2查看pm2的安装…

Kafka基本介绍

消息队列 产生背景 消息队列:指的数据在一个容器中,从容器中一端传递到另一端的过程 消息(message): 指的是数据,只不过这个数据存在一定流动状态 队列(queue): 指的容器,可以存储数据,只不过这个容器具备FIFO(先进…

Linux技术,winSCP连接服务器超时故障解决方案

知识改变命运,技术就是要分享,有问题随时联系,免费答疑,欢迎联系! 故障现象 使用 sftp 协议连接主机时, 明显感觉缓慢且卡顿,并且时常出现如下报错: 点击重新连接后,又有概率重新连接上; 总之在"连接上"和&…

蓝桥杯练习题(六)

📑前言 本文主要是【算法】——蓝桥杯练习题(六)的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 …

分布式系统的三字真经CAP

文章目录 前言C(Consistency 数据一致性)A(Availability 服务可用性)P(Partition Tolerance 分区容错性)CAP理论最后 前言 你好,我是醉墨居士,我一起探索一下分布式系统的三字真经C…

Linux完全卸载Anaconda3和MiniConda3

如何安装Anaconda3和MiniConda3请看这篇文章: 安装Anaconda3和MiniConda3_minianaconda3-CSDN博客文章浏览阅读474次。MiniConda3官方版是一款优秀的Python环境管理软件。MiniConda3最新版只包含conda及其依赖项如果您更愿意拥有conda以及超过720个开源软件包&…

怎么安装es、kibana(单点安装)

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络: docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大&#xff0c…

增删改查管理系统 总结1

//提醒: 管理员也要有增删改查 新增员工代码完善2可能需要用到 目录 细节1 pom文件出现奇怪页面? 细节2 如何联系DataGrip与idea? 细节3 Yapi?接口文档?如何有以下画面? ​细节4 如何将时间转化为好看的时间&…

PostgreSQL认证考试PGCA、PGCE、PGCM

PostgreSQL认证考试PGCA、PGCE、PGCM 【重点!重点!重点!】PGCA、PGCE、PGCM 直通车快速下正,省心省力,每2个月一次考试 PGCE考试通知 (2024) 一、考试概览 (一) 报名要…

必练的100道C语言程序设计练习题(上)

前言: 在计算机编程的世界中,C语言一直是一门备受推崇的语言。它的简洁性、高效性以及广泛应用使得学习C语言成为每一位程序员的必由之路。然而,掌握这门语言并不是一蹴而就的事情,它需要不断的练习和实践。为了帮助各位编程爱好者更好地理解…

kafka之java客户端实战

1. kafka的客户端 Kafka提供了两套客户端API,HighLevel API和LowLevel API。 HighLevel API封装了kafka的运行细节,使用起来比较简单,是企业开发过程中最常用的客户端API。 而LowLevel API则需要客户端自己管理Kafka的运行细节,Pa…

通过shell脚本确定当前平台

shell中的变量OSTYPE存储操作系统的名称,也可以使用uname命令来确认当前所在的平台。 shell中的变量HOSTTYPE存储操作系统的架构。 测试代码如下所示: #! /bin/bashecho "use OSTYPE:" if [[ "$OSTYPE" "linux-gnu&quo…

canvas设置渐变色文字(线性、径向)

查看专栏目录 canvas示例教程100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

ssm基于JAVA的酒店客房管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本酒店客房管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息…

JAVA实现循环日期加一天

一、业务背景 现在数据库新增字段需要区分平日(0)和假期(1)的数据,之前有一批去年的数据都没有算过,所以得用日期循环来根据实际的时间来修改对应的数值,废话不多说看具体操作方法。 二、操作方法 // 初始日期 String dateString "20…

谷粒商城项目|es的应用场景及常见问题

es是什么 es多被用于搜索聚合分析引擎 是分布式的可以高性能查询的引擎 es应用场景 为什么不用MYSQL而用es es将数据存在内存中且可以分布式的存储数据 商品上架 商品在es中的保存 1.在es中建立索引 spu sku spu sku保存在一起防止分布查询 为了防止对象数组扁平化&#xff…