分词算法BBPE详解和Qwen的应用

article/2025/7/5 16:56:29

一、TL;DR

  1. BPE有什么问题:依旧会遇到OOV问题,并且中文、日文这些大词汇表模型容易出现训练中未出现过的字符
  2. Byte-level BPE怎么解决:与BPE一样是高频字节进行合并,但BBPE是以UTF-8编码UTF-8编码字节序列而非字符序列
  3. Byte-level BPE利用utf-8编码,利用动态规划解码,最大程度的还原字符的语义和上下文信息(这是我理解为什么LLM能够通过NTP进行理解的最主要原因)
  4. Qwen是使用BBPE算法,增加了中文的能力,词汇表包括151,643 tokens

二、实际业务的使用

字节级别字节对编码(BBPE)是一种高效的分词算法,它将输入文本分割为可变长度的字节 n-gram(子词),并将其映射为词汇表中的 token ID。以下是 BBPE 分词算法将输入文本转换为 token ID 的详细过程,以及如何结合词表进行文件操作:

2.1  输入文本的字节表示

  • UTF-8 编码:首先,输入文本(如一行字符串)会被转换为 UTF-8 字节序列。UTF-8 编码将每个 Unicode 字符映射为 1 到 4 个字节。

  • 示例:假设输入文本是 "Hello, 世界",其 UTF-8 字节序列为:

    [72, 101, 108, 108, 111, 44, 32, 228, 189, 160, 229, 165, 189]

    其中,"Hello," 是 ASCII 字符,每个字符占用 1 个字节;而 "世界" 是 UTF-8 编码的中文字符,每个字符占用 3 个字节。

2.2 BBPE 分词

  • 学习词汇表:BBPE 通过迭代合并最频繁出现的字节对来构建词汇表。词汇表中包含基本字节(0-255)和通过 BPE 合并生成的字节 n-gram。

  • 分词过程:输入的字节序列会被分割成词汇表中存在的子词(字节 n-gram)。这些子词是通过 BPE 合并规则生成的。

  • 示例:假设词汇表中有以下条目:

72, 101, 108, 108, 111, 44, 32, 228, 189, 160, 229, 165, 189
72 101, 108 108, 111 44, 32 228, 189 160, 229 165 189

2.3 映射为 Token ID

  • 词汇表文件:BBPE 的词汇表通常存储在一个文件中,文件格式类似于:

  • 72
    101
    108
    108 108
    111
    44
    32
    228
    189
    160
    229 165 189
  • 映射过程:分词器将分割后的子词与词汇表文件进行匹配,找到对应的 token ID。

  • 示例:假设分词后的子词为 [72 101, 108 108, 111 44, 32 228, 189 160, 229 165 189],其对应的 token ID 可能是:

    [10, 15, 20, 25, 30, 35]

    其中,72 101 在词汇表中的行号是 10,108 108 的行号是 15,依此类推。

 2.4 文件操作

  • 加载词汇表:分词器在初始化时会加载词汇表文件,将其内容存储到内存中,以便快速查找。

# 假设词汇表文件名为 vocab.txt
with open('vocab.txt', 'r', encoding='utf-8') as f:vocab = [line.strip() for line in f.readlines()]# 将子词映射为 token ID
def tokenize(input_text):# 将输入文本转换为 UTF-8 字节序列byte_sequence = input_text.encode('utf-8')# 分词(这里简化为直接匹配,实际分词器会更复杂)tokens = []for subword in byte_sequence.split():subword_str = ' '.join(map(str, subword))token_id = vocab.index(subword_str)tokens.append(token_id)return tokensinput_text = "Hello, 世界"
token_ids = tokenize(input_text)
print(token_ids)

2.5 总结

  • 输入文本UTF-8 字节序列BBPE 分词映射为 Token ID

  • 词汇表文件是 BBPE 分词的核心,它存储了所有可能的子词及其对应的 token ID。

三、Byte-level BPE算法原理

paper链接: https://arxiv.org/pdf/1909.03341

papr:Neural Machine Translation with Byte-Level Subwords

3.1 为什么要开发Byte-level BPE

  1. 解决不了中文/日语这种语言:几乎所有的分词算法都是基于字符级词汇表构建的(字符、子词或单词),但对于日语和中文的字符丰富且存在噪声文本的语言,罕见字符可能会不必要地占据词汇表的槽位,从而限制其紧凑性
  2. 字节表示会引入计算成本:使用字节级别表示文本,并将 256 个字节集作为词汇表可以解决这个问题,但是会引入高昂的计算成本

3.2 实际合并方法和举例

与BPE算法的差异:

来自日语 - 英语的不同词汇表分词示例。

空格被下划线替换,而空格用于分隔词元。,随着分词粒度从细到粗,词元的形态是如何变化的:字节(256)→ 字节级别字节对编码(BBPE,1K、2K、4K、8K)→ 字符(8K)→ 字节级别字节对编码(BBPE,16K、32K)→ 字节对编码(BPE,16K、32K)。

BBPE算法在基于字节(Byte)进行合并过程和BPE一致、也是选取出现频数最高的字符对进行合并,合并过程如下图所示: 关注到红色箭头,输入是日文当词表大小是1K时,A8 BC 两个字节并没有合并成一个 Token,在词表大小是2K时,A8BC被BBPE合并成一个Token。

3.3 原理上具体怎么做?

别看了,直接用就好,最重要的还是理解对input text进行分词后查表再转成encoder的过程

字节级别表示的编码:

  1. 使用 UTF-8 编码文本,它将每个 Unicode 字符编码为 1 到 4 个字节。这使得我们可以将句子建模为字节序列,而不是字符序列。
  2.  13.8 万个 Unicode 字符覆盖了 150 多种语言,但我们使用 UTF-8 字节(256 个可能字节中的 248 个)来表示任何语言的句子。

如何解决计算成本高昂的问题?

字节级别的n-gram方法来减少计算成本:

编码过程:

  1. 将Unicode字符映射为1-4个字节
  2. 将字节序列分割为可变长度的 n 元组(字节级别的“子词”)
  3. 使用深度卷积层或双向循环层与门控循环单元(GRU)来对 BBPE  embedding进行上下文化

解码过程:

  1. 采用动态规划算法从字节序列恢复Unicode字符
  2. 对于给定的字节序列 {B}kN​,我们用 f(k) 表示我们可以从中恢复的最大字符数。然后 f(k) 具有最优子结构

        如果 {B}kj​ 对应一个有效的字符,则 g(i,j)=1,否则为 0。当 f(k) 递归计算时,我们还在每个位置 k 记录选择,以便通过回溯恢复解决方案。

解码过程中-说人话

  1. 使用动态规划去恢复最有效(g代表有效性指示函数)和可恢复的最大字符数(动态词汇表便于最大化的数据还原

四、Qwen的应用

4.1 Qwen3的技术报告原文:

4.2 Qwen实际代码实现:

参考:https://github.com/QwenLM/Qwen/blob/main/tokenization_note.md

from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen-7B', trust_remote_code=True)

特殊字符的处理:

特殊标记对模型具有特殊功能,例如表示文档结束。理论上,这些标记在输入文本中不存在,仅在输入文本经过处理后才会出现。

可以在微调或其他需要它们的框架中这样指定特殊标记:

from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen-7B', trust_remote_code=True, pad_token='<|endoftext|>')

http://www.hkcw.cn/article/bOhuJwYGMN.shtml

相关文章

小云天气APP:精准预报,贴心服务

在快节奏的现代生活中&#xff0c;天气变化对我们的日常生活、出行安排以及健康状况都有着重要影响。一款精准、便捷且功能丰富的天气预报应用&#xff0c;无疑是提升生活品质的必备工具。小云天气APP正是这样一款为安卓用户量身定制的天气预报应用&#xff0c;凭借其精准的天气…

阿里云服务器ECS详细购买流程

1、打开云服务器ECS官方页面 打开阿里云服务器ECS页面 点击进入阿里云服务器 2、付费类型选择 阿里云服务器付费类型 3、地域节点 阿里云服务器全球28个地域&#xff0c;中国大陆地域如华北2&#xff08;北京&#xff09;、华东1&#xff08;杭州&#xff09;、华南1&#xf…

FastAPI+Pyomo实现线性回归解决饮食问题

之前在 FastAPI介绍-CSDN博客 中介绍过FastAPI&#xff0c;在 Pyomo中线性规划接口的使用-CSDN博客 中使用Pyomo解决饮食问题&#xff0c;这里将两者组合&#xff0c;即FastAPI在服务器端启动&#xff0c;通过Pyomo实现线性回归&#xff1b;客户端通过浏览器获取饮食的最优解。…

【C++篇】STL适配器(上篇):栈与队列的底层(deque)奥秘

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

leetcode刷题日记——二叉树的层次遍历

[ 题目描述 ]&#xff1a; [ 思路 ]&#xff1a; BFS&#xff0c;利用队列特性完成对树的层次遍历运行如下 int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {if (!root) {*returnSize 0;return NULL;}struct TreeNode* queue[2000];…

【优选算法 | 队列 BFS】构建搜索流程的核心思维

算法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;双指针滑动窗口二分查找前缀和位运算模拟链表哈希表字符串模拟栈模拟(非单调栈)优先级队列 很多人学 BFS 的时候都知道“用队列”&#xff0c;但为什么一定是队列&#xff1f;它到底在整个搜索流程中起了什么作…

Retrievers检索器+RAG文档助手项目实战

导读&#xff1a;作为企业级应用开发中的关键技术&#xff0c;LangChain检索器&#xff08;Retrievers&#xff09;正成为构建高效RAG系统的核心组件。本文将深入探讨检索器的技术架构与实战应用&#xff0c;帮助开发者掌握这一重要的AI工程技术。 检索器的价值在于提供统一的检…

word中如何快速调整全部表格大小

Step1: 选中一个表格&#xff0c;然后在自动调整选项卡中选择“根据窗口调整表格大小” Step2&#xff1a;选中其他表格 Step3: 按F4即可快速调整

设计模式——中介者设计模式(行为型)

摘要 文章详细介绍了中介者设计模式&#xff0c;这是一种行为型设计模式&#xff0c;通过中介者对象封装多个对象间的交互&#xff0c;降低系统耦合度。文中阐述了其核心角色、优缺点、适用场景&#xff0c;并通过类图、时序图、实现方式、实战示例等多方面进行讲解&#xff0…

20250602在荣品的PRO-RK3566开发板的Android13下的uboot启动阶段配置BOOTDELAY为10s

20250602在荣品的PRO-RK3566开发板的Android13下的uboot启动阶段配置BOOTDELAY为10s 2025/6/2 18:15 缘起&#xff1a;有些时候&#xff0c;需要在uboot阶段做一些事情。 于是&#xff0c;希望在荣品的PRO-RK3566开发板的Android13下的uboot启动停下。 1、【原始的LOG&#xff…

汽车安全体系:FuSa、SOTIF、Cybersecurity 从理论到实战

汽车安全&#xff1a;功能安全&#xff08;FuSa&#xff09;、预期功能安全&#xff08;SOTIF&#xff09;与网络安全(Cybersecurity) 从理论到实战的安全体系 引言&#xff1a;自动驾驶浪潮下的安全挑战 随着自动驾驶技术从L2向L4快速演进&#xff0c;汽车安全正从“机械可靠…

学习经验分享【40】目标检测热力图制作

目标检测热力图在学术论文&#xff08;尤其是计算机视觉、深度学习领域&#xff09;中是重要的可视化分析工具和论证辅助手段&#xff0c;可以给论文加分不少。主要作用一是增强论文的可解释性与说服力&#xff1a;论文中常需解释模型 “如何” 或 “为何” 检测到目标&#xf…

C++ 检查一条线是否与圆接触或相交(Check if a line touches or intersects a circle)

给定一个圆的圆心坐标、半径 > 1 的圆心坐标以及一条直线的方程。任务是检查给定的直线是否与圆相交。有三种可能性&#xff1a; 1、线与圆相交。 2、线与圆相切。 3、线在圆外。 注意&#xff1a;直线的一般方程是 a*x b*y c 0&#xff0c;因此输入中只给出常数 a、b、…

判断用户输入昵称是否存在(Python)

一、运行结果 二、源代码 # 创建一个存储昵称的列表&#xff1b; name_list [章鱼, 张愚, 宇文弑]# 循环输入判断用户输入昵称是否存在 while True:# 获取用户输入的昵称&#xff1b;name input(请输入昵称&#xff1a;)# 判断昵称是否存在&#xff1b;if name in name_list…

RAG理论基础总结

目录 概念 流程 文档收集和切割 读取文档 转换文档 写入文档 向量转换和存储 搜索请求构建 向量存储工作原理 向量数据库 文档过滤和检索 检索前 检索 检索后 查询增强和关联 QuestionAnswerAdvisor查询增强 高级RAG架构 自纠错 RAG&#xff08;C-RAG&#xf…

pikachu靶场通关笔记09 XSS关卡05-DOM型XSS-X

目录 一、XSS 二、DOM型XSS 三、源码分析 1、打开DOM-X型XSS关卡 2、XSS探测 3、源码分析 四、渗透实战 1、Payload1 2、Payload2 3、Payload3 五、DOM型XSS与DOM-X型XSS区别 本系列为通过《pikachu靶场通关笔记》的XSS攻击关卡(共10关&#xff09;渗透集合&#xf…

3. TypeScript 中的数据类型

在 TypeScript 中&#xff0c;类型&#xff08;Types&#xff09;允许你定义并强制执行应用中数据的结构。通过使用类型&#xff0c;你可以在编译阶段捕捉错误&#xff0c;而不是等到运行时才发现&#xff0c;从而让代码更加可预测&#xff0c;也更不容易出现 bug。TypeScript …

【Java Web】速通Tomcat

参考笔记:JavaWeb 速通Tomcat_tomcat部署java项目-CSDN博客 目录 一、Tomcat服务 1. 下载和安装 2. 启动Tomcat服务 3. 启动Tomcat服务的注意事项 4. 关闭Tomcat服务 二、Tomcat的目录结构 1. bin 🌟 2. conf 🌟 3. lib 4. logs 5. temp 6. webapps 7. work 三、Web项目…

从零实现Python扫雷游戏:完整开发指南与深度解析

目录 一、游戏架构设计 1.1 核心组件 1.2 类结构设计 二、核心算法实现 2.1 地雷生成算法 2.2 数字计算算法 2.3 空白区域展开算法 三、图形界面开发 3.1 主界面布局 3.2 交互事件处理 左键点击事件 右键点击事件 3.3 游戏状态显示 四、游戏功能扩展 4.1 多难度…

hooks组件-useState

hooks组件-useState hook组件的本质就是函数组件&#xff0c;但是基于各种hook让其动态化&#xff01; 常用hook&#xff1a; useReducer&#xff1a;redux useCallback useMemo&#xff1a;去做一些优化。 useRef&#xff1a;使用ref useImperativeHandle&#xff1a;拿到子组…