当前位置: 首页 > java >正文

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

一、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.xdnf.cn/news/10587.html

相关文章:

  • day 40 python打卡
  • Spring框架学习day6--事务管理
  • 【ISAQB大纲解读】信息隐藏指的是什么
  • 基于Qt的app开发的过渡期
  • PH热榜 | 2025-06-01
  • Flex弹性布局
  • langGraph多Agent
  • 【C语言入门级教学】冒泡排序和指针数组
  • ShardingSphere 分片策略深度解析
  • 导入典籍数据
  • 《仿盒马》app开发技术分享-- 购物车业务逻辑完善(端云一体)
  • java 多线程
  • 基于贝叶斯优化神经网络的光伏功率预测综述
  • Java JVM 内存模型详解
  • LeetCode 付费题157. 用 Read4 读取 N 个字符解题思路
  • deep forest安装及使用教程
  • 强大的PDF编辑工具,操作方便 ,长久使用
  • 第1天:认识RNN及RNN初步实验(预测下一个数字)
  • 【C盘瘦身】Docker安装目录占用C盘过大,一键移动给C盘瘦身
  • 大数据-275 Spark MLib - 基础介绍 机器学习算法 集成学习 随机森林 Bagging Boosting
  • 8、电解电容—数据手册解读
  • Unity使用Lua框架和C#框架开发游戏的区别
  • 2022年上半年软件设计师下午试题
  • 6月2日星期一今日早报简报微语报早读
  • 知识图谱系列(5):表示学习
  • 内网应用如何实现外网访问?无公网IP本地端口网址服务提供互联网连接
  • HCIP:MPLS LDP的原理和配置
  • Go开发简历优化指南
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月2日第96弹
  • 高压电绝缘子破损目标检测数据集简介与应用