百度工程师浅析解码策略
作者 | Jane
导读
生成式模型的解码方法主要有2类:确定性方法(如贪心搜索和波束搜索)和随机方法。确定性方法生成的文本通常会不够自然,可能存在重复或过于简单的表达。而随机方法在解码过程中引入了随机性,以便生成更多样化、更自然的文本。两种常见的随机方法是:
1、Top-k 采样:在每个解码步骤中,模型会选择可能性排名在前的前 k 个单词,然后从这些单词中随机选择一个作为下一个生成的单词。这样可以增加文本的多样性,但仍然保持一定的可控性。
2、核采样(Top-p 采样):在这种方法中,模型会根据累积概率从词汇表中选择下一个单词。累积概率是指按照概率从高到低排列的单词概率之和。这可以减少重复性,并且相对于固定的 k 值,它可以自适应地选择更少或更多的候选词。
虽然核采样可以生成(缓解)没有重复的文本,但生成文本的语义一致性并不是很好,这种语义不一致的问题可以通过降低温度 (temperature) 来部分解决。降低温度是一个可以影响随机性的参数。较高的温度会导致更均匀的分布,使得生成的文本更多样化,而较低的温度会使分布更集中,更接近于确定性。这就引入了一个权衡,因为较高的温度可能会导致文本语义不一致,而较低的温度可能会失去一些多样性。
在实际应用中,要根据任务和期望的文本输出特性来选择合适的解码方法、随机性参数和温度值。不同的方法和参数组合可能适用于不同的情况,以平衡生成文本的多样性、准确性和一致性。
全文3646字,预计阅读时间10分钟。
01 对比搜索(contrastive_search)
对比搜索给定前缀文本 x < t x_{< t} x<t,按如下公式输出token x t x_{t} xt:
语言模型输出的概率分布 p θ ( v ∣ x < t ) p_{\theta}(v|x_{< t}) pθ(v∣x<t)表示下一个可能的token的预测概率,上式中 V ( k ) V^{(k)} V(k)表示概率分布中 k 个概率最大的候选token的集合。
-
第一项,即 模型置信度 (model confidence),是语言模型预测的每个候选词元 v 的概率。
-
第二项, 退化惩罚 (degeneration penalty),用于度量候选token v 与上文 x < t x{< t} x<t中每个token的相似性, v 的向量表征 h v h_{v} hv与其上文 x < t x {< t} x<t中每个token的向量表征计算余弦相似度,相似度最大值被用作退化惩罚。直观上理解,如果 v 的退化惩罚较大意味着它与上文更相似 (在表示空间中),因此更有可能导致模型退化问题。超参数 α \alpha α用于在这两项中折衷。当时 α = 0 \alpha=0 α=0,对比搜索退化为纯贪心搜索。
总结来说,对比搜索在生成输出时会同时考虑:
-
语言模型预测的概率,以保持生成文本和前缀文本之间的语义连贯性。
-
与上文的相似性以避免模型退化。
# generate the result with contrastive search
output = model.generate(input_ids, penalty_alpha=0.6, # 对比搜索中的超参 $\alpha$top_k=4, # 对比搜索中的超参 $k$。max_length=512)
02 贪心搜索(greedy_search)**
贪心搜索在每个时间步 都简单地选择概率最高的词作为当前输出词: w t = a r g m a x w P ( w ∣ w 1 : t − 1 ) w_t = argmax_{w}P(w | w_{1:t-1}) wt=argmaxwP(w∣w1:t−1)
△贪心搜索
问题:
-
容易输出重复的文本,这在语言生成中是一个非常普遍的问题,在贪心搜索和波束搜索中似乎更是如此
-
主要缺点是它错过了隐藏在低概率词后面的高概率词:The -> dog -> has (0.4*0.9=0.36),The -> nice -> wman (0.5*0.4=0.20),波束搜索可以缓解此类问题
03 波束搜索(beam_search)
波束搜索整个过程可以总结为: 分叉、排序、剪枝,如此往复。波束搜索通过在每个时间步保留最可能的 num_beams 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。
下图示例 num_beams=2:
△波束搜索 num_beams=2
波束搜索一般都会找到比贪心搜索概率更高的输出序列,但仍不保证找到全局最优解。
虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 n-grams (即连续 n 个词的词序列) 惩罚:最常见的 n-grams 惩罚是确保每个 n-gram 都只出现一次,方法是如果看到当前候选词与其上文所组成的 n-gram 已经出现过了,就将该候选词的概率设置为 0。通过设置 no_repeat_ngram_size=2 来试试,这样任意 2-gram 不会出现两次:
beam_output = model.generate(input_ids, max_length=50, num_beams=5, no_repeat_ngram_size=2, # n-gramsearly_stopping=True
)
但是,n-gram 惩罚使用时必须谨慎,如一篇关于纽约这个城市的文章就不应使用 2-gram 惩罚,否则,城市名称在整个文本中将只出现一次!
波束搜索已被证明依然会存在重复生成的问题。在『故事生成』这样的场景中,很难用 n-gram 或其他惩罚来控制,因为在“不重复”和最大可重复 n-grams 之间找到一个好的折衷需要大量的微调。正如 Ari Holtzman 等人 (2019) (https://arxiv.org/abs/1904.09751) 所论证的那样,高质量的人类语言并不遵循最大概率法则。这是因为人类语言具有创造性和惊喜性,而不仅仅是简单的预测性。
因此,引入随机性和创造性元素是生成更有趣和多样性文本的关键。
04 采样(sampling)
4.1 采样
使用采样方法时文本生成本身不再是确定性的(do_sample=True)。
# 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
)
对单词序列进行采样时的问题:模型通常会产生不连贯的乱码,缓解这一问题的一个技巧是通过降低 softmax的“温度”使分布 P ( w ∣ w 1 : t − 1 ) P(w|w_{1:t-1}) P(w∣w1:t−1)更陡峭。而降低“温度”,本质上是增加高概率单词的似然并降低低概率单词的似然。
sample_output = model.generate(input_ids, 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% 的单词集作为采样池,定义为 V top-p V_{\text{top-p}} Vtop-p。在 t=1 时 V top-p V_{\text{top-p}} Vtop-p有 9 个词,而在 t=2 时它只需要选择前 3 个词就超过了 92%。
可以看出,在单词比较不可预测时(例如更平坦的左图),它保留了更多的候选词,如 P ( w ∣ “The” ) P(w | \text{“The”}) P(w∣“The”),而当单词似乎更容易预测时(例如更尖锐的右图),只保留了几个候选词,如 P ( w ∣ “The” , “car” ) P(w | \text{“The”}, \text{“car”}) P(w∣“The”,“car”)。
# deactivate top_k sampling and sample only from 92% most likely words
sample_output = model.generate(input_ids, 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——
参考资料:
[1]一种简单有效的解码策略:Contrastive Search
[2]HF:如何生成文本: 通过 Transformers 用不同的解码方法生成文本
[3]https://docs.cohere.ai/docs/controlling-generation-with-top-k-top-p
[4]https://docs.cohere.ai/docs/temperature
推荐阅读:
百度工程师浅析强化学习
浅谈统一权限管理服务的设计与开发
百度APP iOS端包体积50M优化实践(五) HEIC图片和无用类优化实践
百度知道上云与架构演进
百度APP iOS端包体积50M优化实践(四)代码优化
百度App启动性能优化实践篇
相关文章:

百度工程师浅析解码策略
作者 | Jane 导读 生成式模型的解码方法主要有2类:确定性方法(如贪心搜索和波束搜索)和随机方法。确定性方法生成的文本通常会不够自然,可能存在重复或过于简单的表达。而随机方法在解码过程中引入了随机性,以便生成更…...
windows下实现查看软件请求ip地址的方法
一、关于wmic和nestat wmic是Windows Management Instrumentation的缩写,是一款非常常用的用于Windows系统管理的命令行实用程序。wmic可以通过命令行操作,获取系统信息、安装软件、启动服务、管理进程等操作。 netstat命令是一个监控TCP/IP网络的非常有…...

【JAVA】String 类
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 String 1. 字符串构造2. String对象的比…...

LoRA继任者ReLoRA登场,通过叠加多个低秩更新矩阵实现更高效大模型训练效果
论文链接: https://arxiv.org/abs/2307.05695 代码仓库: https://github.com/guitaricet/peft_pretraining 一段时间以来,大模型(LLMs)社区的研究人员开始关注于如何降低训练、微调和推理LLMs所需要的庞大算力…...

Elasticsearch 8.X reindex 源码剖析及提速指南
1、reindex 源码在线地址 为方便大家验证,这里给出 reindex github 源码地址。 https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java reindex 常见…...

前端组件库造轮子——Input组件开发教程
前端组件库造轮子——Input组件开发教程 前言 本系列旨在记录前端组件库开发经验,我们的组件库项目目前已在Github开源,下面是项目的部分组件。文章会详细介绍一些造组件库轮子的技巧并且最后会给出完整的演示demo。 文章旨在总结经验,开源…...
Day04-Vue基础-监听器-双向绑定-组件通信
Day04-Vue基础-监听器-双向绑定-组件通信 一 侦听器 语法一 <template><div>{{name}}<br><button @click="update1">修改1</button><...

Java小白基础自学阶段(持续更新...)
引言 Java作为一门广泛应用于企业级开发的编程语言,对初学者来说可能会感到有些复杂。然而,通过适当的学习方法和资源,即使是小白也可以轻松掌握Java的基础知识。本文将提供一些有用的建议和资源,帮助小白自学Java基础。 学习步骤…...
Vue自定义指令- v-loading封装
Vue自定义指令- v-loading封装 文章目录 Vue自定义指令- v-loading封装01-自定义指令自定义指令的两种注册语法: 02自定义指令的值03-自定义指令- v-loading指令封装 01-自定义指令 什么是自定义指令? 自定义指令:自己定义的指令,…...
C++中提供的一些关于查找元素的函数
C中提供的所有关于查找的函数 std::find(begin(), end(), key) std::find(begin(), end(), key):这个函数用于在一个范围内查找一个等于给定值的元素,返回一个指向该元素的迭代器,如果没有找到则返回范围的结束迭代器。 1.1 例如ÿ…...

Wlan——STA上线流程与802.11MAC帧讲解以及报文转发路径
目录 802.11MAC帧基本概念 802.11帧结构 802.11MAC帧的分类 管理帧 控制帧 数据帧 STA接入无线网络流程 信号扫描—管理帧 链路认证—管理帧 用户关联—管理帧 用户上线 不同802.11帧的转发路径 802.11MAC帧基本概念 802.11协议在802家族中的角色位置 其中802.3标…...

Python|爬虫和测试|selenium框架模拟登录示例(一)
前言: 上一篇文章Python|爬虫和测试|selenium框架的安装和初步使用(一)_晚风_END的博客-CSDN博客 大概介绍了一下selenium的安装和初步使用,主要是打开某个网站的主页,基本是最基础的东西,那么,…...
QT的概述
什么是QT Qt是一个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。 QT项目的创建 .pro文件 .pro 文件是一个Qt项目文件,用于定义…...
Hive 导入csv文件,数据中包含逗号的问题
问题 今天 Hive 导入 csv 文件时,开始时建表语句如下: CREATE TABLE IF NOT EXISTS test.student (name STRING COMMENT 姓名,age STRING COMMENT 年龄,gender STRING COMMENT 性别,other_info STRING COMMENT 其他信息 ) COMMENT 学生信息表 ROW FORM…...

1、Odoo开发起点
1.1.odoo的模块组成 init.py将一个文件夹编程python包manifestpyodoo模块定义的清单文件,用于对odoo模块管理详见model模型类文件,存放py文件security表级别权限管理static静态文件views视图文件。wizard瞬态模型向导文件位置 1.2.odoo的开发规范 非强…...
Ubuntu22.04 交叉编译树莓派CM4 kernel
通过这个文章记录一下如何在Ubuntu22.04编译树莓派CM4的kernel。 主要参考树莓派官网的方法,也总结了一些关于SD卡分区的知识。 1,虚拟机安装Ubuntu 22.04,就不介绍了。 2,先将树莓派官方系统烧录倒SD卡中,设备能正…...
稀疏矩阵搜索(两种方法解决:1.暴力+哈希 2.二分法)
题目: 有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。 示例: 输入: words ["at", "", "", "", "ball", "", &…...
NodeJS系列教程、笔记
NodeJS系列教程、笔记 点我进入专栏 Node.js安装与基本使用 NodeJS的Web框架Express入门 Node.js的sha1加密 Nodejs热更新 Nodejs配置文件 Nodejs的字节操作(Buffer) Node.js之TCP(net) Node.js使用axios进行web接口调用 …...

4.4TCP半连接队列和全连接队列
目录 什么是 TCP 半连接队列和全连接队列? TCP 全连接队列溢出 如何知道应用程序的 TCP 全连接队列大小? 如何模拟 TCP 全连接队列溢出的场景? 全连接队列溢出会发生什么 ? 如何增大全连接队列呢 ? TCP 半连接队列溢出 如何查看 TC…...

一键实现 Oracle 数据整库同步至 Apache Doris
在实时数据仓库建设或迁移的过程中,用户必须考虑如何高效便捷将关系数据库数据同步到实时数仓中来,Apache Doris 用户也面临这样的挑战。而对于从 Oracle 到 Doris 的数据同步,通常会用到以下两种常见的同步方式: OGG/XStream/Lo…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...

数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

Selenium 查找页面元素的方式
Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...