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

分词算法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.lqws.cn/news/83935.html

相关文章:

  • 【深度学习新浪潮】多模态模型如何处理任意分辨率输入?
  • 项目采购管理习题剖析
  • 振动力学:有阻尼单自由度系统
  • 《操作系统真相还原》——中断
  • Python训练营打卡 Day43
  • 2023年12月6级第一套第一篇
  • mybatisplus的总结
  • Linux配置DockerHub镜像源配置
  • 代码随想录算法训练营第六天| 242.有效的字母异位词 、 349. 两个数组的交集 、 202. 快乐数 、1. 两数之和
  • 【看到哪里写到哪里】C的指针-3(函数指针)
  • TC3xx学习笔记-启动过程详解(一)
  • Arch安装botw-save-state
  • deep forest安装及使用教程
  • 一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——4. 配置服务器终端环境 zsh , oh my zsh, vim
  • 基于爬取的典籍数据重新设计前端界面
  • 前端八股之CSS
  • 推荐一款使用html开发桌面应用的工具——mixone
  • 力扣HOT100之多维动态规划:62. 不同路径
  • 力扣HOT100之多维动态规划:64. 最小路径和
  • 量子物理:深入学习量子物理的基本概念与应用
  • Python_day43
  • Linux运维笔记:服务器感染 netools 病毒案例
  • mysql专题上
  • Vue 项目创建教程 (开发前的准备工作保姆级辅助文档)
  • 专注成就技术传奇:一路向前的力量
  • 数学建模期末速成 最短路径
  • Ubuntu22.04 安装 ROS2 Humble
  • Spark-TTS: AI语音合成的“变声大师“
  • ubuntu 添加应用到启动菜单
  • P5684 [CSP-J2019 江西] 非回文串 题解