More than code

More Than Code
The efficiency of your iteration of reading, practicing and thinking decides your understanding of the world.
  1. 首页
  2. nlp
  3. 正文

Tokenizer notes

2025年1月30日 114点热度 0人点赞 0条评论

知乎这里有一篇不错的文章讲这块:https://zhuanlan.zhihu.com/p/460678461

基本介绍

deepseek给了一个基本的介绍:

好的!以下是对语言模型 Tokenizer 的详细解释,涵盖你的问题:


1. Tokenizer 的作用与使用方式

Tokenizer(分词器) 是语言模型的核心组件之一,负责将原始文本拆分成模型能处理的单元(Token),同时将 Token 转换为对应的数字 ID(或向量)。它的使用分两个方向:

  • 预处理(Preprocessing):
    将输入文本(如句子、段落)拆分成 Token,并转换为模型输入格式(如 input_ids)。
  • 生成(Generation):
    将模型输出的数字 ID 转换回可读文本。

具体步骤:
1. 文本清洗:去除特殊符号、统一大小写等。
2. 分词:按规则或算法拆分文本。
3. 编码:将 Token 映射到词汇表(Vocabulary)中的 ID。
4. 添加特殊标记:如 [CLS]、[SEP](用于 BERT),<s>、</s>(序列起止符)等。


2. 分词级别:Word/Character/Subword

(1) Word-Level(词级分词)

  • 原理:按空格或标点分割成独立单词(如英文直接按空格分,中文需要分词工具)。
  • 优点:直观,保留语义。
  • 缺点:
    • 词汇表庞大(需覆盖所有可能的词),导致内存和计算成本高。
    • 无法处理未登录词(OOV, Out-of-Vocabulary)。
  • 例子:早期模型如 Word2Vec 使用词级分词。

(2) Character-Level(字符级分词)

  • 原理:将文本拆分为单个字符(如字母、标点、汉字)。
  • 优点:
    • 词汇表极小(如英文仅需 26 字母 + 符号)。
    • 天然支持所有词汇,无 OOV 问题。
  • 缺点:
    • 序列长度过长(如一个句子可能有数百个字符)。
    • 难以捕捉语义和词间关系。
  • 例子:早期 RNN 模型尝试过字符级分词。

(3) Subword-Level(子词级分词)

  • 原理:将词拆分为更小的语义单元(如 "unhappiness" → "un" + "happiness" 或 "un" + "happy" + "ness")。
  • 优点:
    • 平衡词汇表大小与语义表达。
    • 可处理未登录词(通过子词组合)。
  • 缺点:需要复杂的分词算法。
  • 例子:现代主流模型(如 BERT、GPT)均使用子词分词。

3. 常见子词分词算法

(1) BPE(Byte-Pair Encoding,字节对编码)

  • 核心思想:通过合并高频的相邻符号对(如字母或字符)逐步构建词汇表。
  • 步骤:
    1. 初始词汇表:所有基础字符(如 ASCII)。
    2. 统计所有相邻符号对的频率。
    3. 合并频率最高的符号对,加入词汇表。
    4. 重复步骤 2-3,直到达到目标词汇表大小。
  • 特点:
    • 基于频率,优先合并高频组合。
    • 常用于 GPT 系列模型。
  • 例子:"low" → ["l", "ow"](如果 "ow" 是高频对)。

(2) WordPiece

  • 核心思想:类似 BPE,但合并策略基于概率(而非频率)。
  • 步骤:
    1. 初始词汇表:所有基础字符。
    2. 计算合并每对符号后的语言模型概率增益(通过似然函数)。
    3. 合并增益最大的符号对。
    4. 重复直到达到目标词汇表大小。
  • 特点:
    • 优先合并对模型似然提升最大的符号对。
    • 常用于 BERT 和 Transformer 系列模型。
  • 例子:"unhappy" → ["un", "##happy"](## 表示子词前缀)。

(3) ULM(Unigram Language Model)

  • 核心思想:通过语言模型概率评估所有可能的分词方式,选择最优解。
  • 步骤:
    1. 初始化一个大词汇表(如所有可能的子词)。
    2. 逐步删除对总概率影响最小的子词,缩小词汇表。
    3. 最终保留高频且重要的子词。
  • 特点:
    • 支持动态选择最佳分词方式。
    • 更灵活,但计算成本较高。
  • 例子:常用于 ALBERT 和部分多语言模型。

(4) SentencePiece

  • 核心思想:将文本视为 Unicode 字符序列,直接训练子词模型,无需预分词。
  • 特点:
    • 支持 BPE 或 ULM 作为底层算法。
    • 直接处理原始文本(包括空格和特殊符号)。
    • 常用于 T5 和 XLNet。

4. 对比与总结

算法 核心策略 优点 典型模型
BPE 合并高频符号对 简单高效 GPT-2, GPT-3
WordPiece 基于概率合并 优化语言模型似然 BERT
ULM 语言模型概率评估 动态选择最佳分词 ALBERT, XLM-R
SentencePiece 直接处理原始文本 支持多语言和空格保留 T5, XLNet

5. 如何选择 Tokenizer?

  • 任务需求:
    • 需要处理多语言?→ 优先 SentencePiece。
    • 需要高效性?→ BPE 或 WordPiece。
  • 数据特点:
    • 专业领域术语多?→ 增大词汇表或自定义子词。
  • 模型兼容性:
    • 使用预训练模型时,必须匹配其原生的 Tokenizer(如 BERT 用 WordPiece)。

希望这些信息对你有帮助!如果有进一步问题,欢迎随时提问 😊

WordPiece

好的!我们来深入探讨 WordPiece 中基于概率的合并策略,以及与 BPE 的核心区别。


WordPiece 的核心思想

WordPiece 的分词过程与 BPE 类似,但关键区别在于 合并子词的决策依据:
- BPE:合并频率最高的相邻符号对(如 ("e", "r") → "er")。
- WordPiece:合并能最大化语言模型(LM)似然概率的符号对,即对模型的训练目标(如预测下一个词)最有帮助的合并。

这种差异使得 WordPiece 更关注子词对模型性能的提升,而非单纯频率。


WordPiece 的合并步骤

以下是 WordPiece 构建词汇表的详细流程:

1. 初始化词汇表

  • 初始词汇表包含所有基础字符(如英文的字母、中文的汉字)和常见符号。
  • 例如:["a", "b", ..., "z", "##a", "##b", ..., "##z", ...](## 表示子词前缀)。

2. 训练语言模型(LM)

  • 定义一个简单的 单层语言模型,任务是预测句子中下一个词的概率。
  • 假设当前词汇表为 V,模型通过最大化训练数据的对数似然概率来学习:
  • $$\text{log-likelihood} = \sum_{s \in \text{数据}} \sum_{t \in s} \log P(t | \text{上下文})$$
    这里的 t 是当前词(或子词)。

3. 计算合并增益

  • 遍历所有可能的相邻符号对(例如 ("un", "happy")),计算 合并后的语言模型概率增益。
  • 对每一对符号 (A, B),计算合并为 AB 后的似然增益:
  • $$\Delta_{\text{score}} = \frac{\text{count}(A, B)}{\text{count}(A) + \text{count}(B)}$$
    其中:

    • count(A, B) 是 A 和 B 在训练数据中连续出现的次数。
    • count(A) 和 count(B) 是 A 和 B 单独出现的次数。
  • 关键点:合并增益高的符号对,意味着它们在上下文中共同出现时对模型预测更有帮助。

4. 合并最佳符号对

  • 选择增益最高的符号对(如 ("un", "happy") → "unhappy"),将其加入词汇表。
  • 更新训练数据中的所有实例,将原来的 A B 替换为 AB。

5. 重复直到达到目标词汇表大小

  • 重复步骤 3-4,直到词汇表大小达到预设值(如 30k)。

具体例子:合并过程

假设初始词汇表为 ["un", "happy", "##ness"],训练数据中有以下句子:

"un happy" → 出现 10 次  
"happy ##ness" → 出现 8 次
  • 计算合并增益:
    • 对符号对 ("un", "happy"):
    • count(un, happy) = 10
    • count(un) = 10, count(happy) = 10 + 8 = 18
    • 增益:Δ_score = 10 / (10 + 18) ≈ 0.357
    • 对符号对 ("happy", "##ness"):
    • count(happy, ##ness) = 8
    • count(happy) = 18, count(##ness) = 8
    • 增益:Δ_score = 8 / (18 + 8) ≈ 0.307
  • 决策:合并 ("un", "happy"),得到新子词 "unhappy",并更新数据:
    • 原句子 "un happy" → 变为 "unhappy"。

与 BPE 的关键区别

特性 WordPiece BPE
合并依据 最大化语言模型似然(概率增益) 合并最高频符号对
目标导向 优化模型预测能力 压缩词汇表,减少 OOV
计算方式 依赖语言模型的概率计算 直接统计频率
典型应用 BERT、DistilBERT GPT 系列、RoBERTa

为什么 WordPiece 有效?

  1. 语义相关性:
    合并能提升语言模型概率的符号对,意味着这些子词组合在语义上更相关(例如 "un" + "happy" → "unhappy")。
  2. 处理未登录词:
    通过动态合并子词,可以灵活生成未在词汇表中显式存在的词(如 "ChatGPT" → ["Chat", "G", "PT"])。
  3. 控制词汇表大小:
    选择对模型最有用的子词,避免冗余。

WordPiece 的局限性

  • 计算成本高:需要反复训练语言模型计算增益。
  • 依赖初始分词:需预先定义基础子词(如字符或简单子词)。
  • 符号标记处理:需特殊符号(如 ##)区分子词位置,增加复杂性。

实际应用中的 WordPiece

以 BERT 为例:
- 词汇表:包含 30k 个子词,如 "the"、"##ing"、"##ness"。
- 分词结果:

```python
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
print(tokenizer.tokenize("unhappiness"))
# 输出:['un', '##hap', '##piness']
```


总结来说,WordPiece 通过概率驱动的合并策略,在保留语义的同时高效构建词汇表,成为现代预训练模型(如 BERT)的核心组件。如果需要进一步探讨具体实现细节,可以继续提问! 🚀

这里我又问了一轮:

好的!我们来深入探讨 WordPiece 中基于概率合并子词的核心机制,以及它与 BPE 的区别。这里的关键在于理解 “合并策略如何基于概率”,而不仅仅是频率。


1. WordPiece 的核心思想

WordPiece 的目标是找到一个最优的子词集合,使得这些子词组合后能最大化训练数据的似然概率(即让模型对训练数据的“拟合程度”最高)。
核心问题:如何确定哪些子词组合应该被合并?
答案:合并能最大程度提升语言模型概率的符号对。


2. WordPiece 的训练步骤

步骤 1:初始化词汇表

  • 初始词汇表 = 所有基础字符(如英文字母、汉字、标点符号等)。

步骤 2:构建候选符号对

  • 将所有相邻的子词对(例如 ("a", "b")、("un", "##h"))作为候选。

步骤 3:计算合并增益(Merge Gain)

  • 核心公式:
    对于每个候选符号对 (A, B),计算将它们合并为 AB 后的概率增益:

    Gain = P(AB) / (P(A) * P(B))
    

    其中:

    • P(A) 和 P(B) 是符号 A 和 B 在训练数据中的独立概率。
    • P(AB) 是符号对 AB 在训练数据中的联合概率。
  • 直观理解:
    如果 Gain > 1,说明合并后的 AB 比单独出现的 A 和 B 更可能共同出现,合并是有益的。

步骤 4:选择并合并增益最大的符号对

  • 选择增益最大的符号对,将其合并为一个新的子词(如 A + B → AB),并更新词汇表。

步骤 5:重复步骤 2-4

  • 不断合并符号对,直到词汇表达到预设大小(例如 30,000)。

3. 概率增益的详细计算

举例说明

假设训练数据中有以下文本:

"the cat is unhappy"
"the unhappy cat"

假设当前词汇表包含 ["un", "##h", "##appy", ...],现在要计算是否合并 ("un", "##h") 为 "un##h"。

  1. 统计概率:
    • P(un) = un 在数据中出现的次数 / 总符号数
    • P(##h) = ##h 在数据中出现的次数 / 总符号数
    • P(un##h) = un##h 在合并后可能出现的次数 / 总符号数
  2. 计算增益:
    • 如果合并后的 un##h 出现概率显著高于 un 和 ##h 独立出现的概率乘积,则增益较大。

关键点:

  • WordPiece 通过最大化训练数据的似然(即让模型更“认可”当前的分词方式),选择合并的子词对。
  • 与 BPE 的区别:BPE 直接合并最高频的符号对,而 WordPiece 合并对模型似然提升最大的符号对。

4. 编码阶段的分词逻辑

训练完成后,WordPiece 在分词时采用 贪婪最长匹配优先 策略:
1. 从词汇表中找到最长的可能子词(从左到右扫描)。
2. 如果找不到匹配的子词,则回退到较小的子词或基础字符。
3. 未登录词会被拆分为子词组合(例如 "unhappiness" → "un" + "##happiness")。


5. 与 BPE 的对比

特性 BPE WordPiece
合并准则 合并最高频的符号对 合并对模型似然增益最大的符号对
目标函数 频率驱动 概率驱动(最大化数据似然)
处理未登录词 可能拆分不合理(依赖频率) 更合理地拆分(基于概率增益)
典型应用 GPT 系列 BERT、DistilBERT

6. 实际例子

假设词汇表中已有 ["un", "##h", "##appy"],现在输入单词 "unhappy":
1. 初始拆分:["un", "##h", "##appy"]
2. 检查是否可合并:
- 合并 "un" + "##h" → "un##h"(如果增益足够大)。
3. 最终分词:可能为 ["un##h", "##appy"] 或保持原状。


7. 数学形式化

假设训练数据由句子集合组成,WordPiece 的目标是找到词汇表 V,使得分词后的句子的对数似然最大化:

maximize Σ_{sentence} Σ_{token} log P(token)

每次合并符号对时,选择使得上述目标增长最大的合并操作。


8. 为什么选择概率而非频率?

  • 语义连贯性:高频符号对可能只是巧合(如 "th" 在英文中高频,但未必有意义),而概率增益高的符号对更可能构成有意义的语义单元。
  • 灵活性:能适应不同数据分布(如专业术语中的低频但重要的子词组合)。

通过这种基于概率的合并策略,WordPiece 在保留高频子词的同时,能更有效地捕捉有意义的语义单元,这也是 BERT 等模型选择它的重要原因。如果有进一步问题,欢迎继续提问!

WordPiece的Motivation

逐步解释:

WordPiece 的目标是找到一个子词集合,使得用这些子词组合分词后的训练数据概率最大化。这句话的核心在于理解“似然概率最大化”如何指导子词合并:


1. 什么是“似然概率”?

  • 定义:在统计学中,似然概率(Likelihood)表示在给定模型参数(这里是子词集合)下,观察到当前训练数据的可能性。
  • 语言模型中的意义:假设有一个简单的概率模型,每个子词的出现是独立事件,那么一个句子的概率就是其所有子词概率的乘积。例如:
    • 句子 "unhappy" 被分词为 ["un", "##happy"],则句子概率 = P("un") * P("##happy")。

2. 如何通过合并子词最大化似然?

WordPiece 的每一步合并都选择能最大程度提升整体数据概率的子词对。具体过程:

步骤 1:初始状态

  • 初始词汇表 = 所有单个字符(如 a, b, c, ...)。
  • 此时每个字符的概率由其出现频率决定。

步骤 2:计算合并候选对的增益

假设当前词汇表中有子词 A 和 B,合并它们为新子词 AB。
- 合并前:句子中 A 和 B 独立出现的概率为 P(A) * P(B)。
- 合并后:AB 作为一个整体出现的概率为 P(AB)。
- 增益:如果 P(AB) > P(A) * P(B),说明合并后的概率更高,合并是有益的。

步骤 3:选择增益最大的合并

合并增益最大的符号对,更新词汇表,并重新计算所有概率。

重复迭代

直到词汇表达到预设大小。


3. 具体例子说明

假设训练数据中频繁出现 "un" 和 "##happy" 的组合,但单独出现的概率较低:
- 合并前:
P("un") = 0.01, P("##happy") = 0.005 → 组合概率 0.01 * 0.005 = 0.00005。
- 合并后:
P("un##happy") = 0.008(因为合并后作为一个整体更常出现)。
- 增益:0.008 / 0.00005 = 160(增益远大于 1)。

此时合并 "un" 和 "##happy" 会显著提升整体数据的似然概率。


4. 为什么最大化似然有效?

  • 捕捉语义关联:
    如果 A 和 B 经常共同出现(如 "un" 和 "##happy"),合并后概率提升,说明它们组成了一个有意义的语义单元(如否定前缀)。
  • 减少冗余:
    独立出现的低频子词合并后,能降低模型对噪声的敏感度(例如拆分出无意义的片段)。

5. 与 BPE 的对比

  • BPE:合并高频符号对(如 ("e", "s") → "es"),但高频组合可能只是巧合(如 "th" 在英文中高频,但未必是完整语义单元)。
  • WordPiece:合并概率增益大的符号对,确保合并后的子词具有更强的语义关联性(如 "un"+"##happy" 比单独出现更有意义)。

6. 数学形式化

目标函数是最大化训练数据的对数似然:
\text{Maximize } \sum_{\text{sentence}} \sum_{\text{token}} \log P(\text{token})
每次合并选择使该值增长最大的符号对。


7. 实际意义

通过最大化似然,WordPiece 生成的子词能更准确地反映数据中的语义模式,从而:
1. 提升模型效果:输入表示更贴近真实语义。
2. 减少未登录词:通过组合子词表达新词(如 "ChatGPT" → "Chat" + "G" + "PT")。
3. 平衡效率与效果:词汇表大小可控,同时保留语义信息。


8. 常见误区澄清

  • 不是训练语言模型:WordPiece 训练的是分词器,而非后续的BERT/GPT等模型。它的目标是优化分词方式,使分词后的数据更“适合”语言模型处理。
  • 增益公式的简化:实际实现中,WordPiece 可能使用更复杂的概率估计(如考虑上下文),但核心思想仍是选择对似然提升最大的合并。

通过这种机制,WordPiece 能够生成既紧凑又富有语义的子词集合,成为BERT等模型成功的关键因素之一。

ULM

好的!我们来深入探讨 ULM(Unigram Language Model) 分词算法,它与其他子词分词方法(如 BPE、WordPiece)有本质区别,核心思想是基于概率模型反向构建词汇表。以下是详细解析:


1. ULM 的核心思想

ULM 是一种 基于概率的生成模型,其目标是:
找到所有可能的分词方式中,对训练数据概率最大的分词结果。
与 BPE/WordPiece(逐步合并符号对)不同,ULM 先假设一个较大的词汇表,然后逐步删除对整体概率贡献最小的子词,最终保留最优子词集合。


2. ULM 的训练步骤

步骤 1:初始化词汇表

  • 初始词汇表需要足够大,通常通过启发式方法生成:
    • 包含所有单字符。
    • 添加高频词、所有可能的 N-gram(如 2-gram、3-gram)组合。
    • 例如:从文本中提取所有出现次数超过阈值的子串。

步骤 2:估计子词概率

假设词汇表为 ( V ),每个子词 ( s \in V ) 有一个概率 ( p(s) ),满足 ( \sum_{s \in V} p(s) = 1 )。
通过 EM 算法(期望最大化) 迭代优化子词概率:
1. E 步(Expectation):
对每个句子,计算所有可能分词方式的概率,并统计每个子词的出现期望值。
2. M 步(Maximization):
根据期望值更新子词概率 ( p(s) )。

步骤 3:剪枝词汇表(Vocabulary Pruning)

逐步删除对总概率贡献最小的子词:
1. 计算移除每个子词 ( s ) 后的 总概率损失 ( L(s) )。
- 损失 ( L(s) ) 越小,说明该子词越不重要。
2. 删除损失最小的子词,更新词汇表。
3. 重复直到词汇表达到目标大小。

步骤 4:最终分词

训练完成后,对输入文本选择 概率最大的分词方式(通过动态规划,如 Viterbi 算法)。


3. 关键细节解析

(1) 如何计算分词概率?

对于一个句子 ( S ),假设其分词方式为 ( \text{Segmentation} = {s_1, s_2, ..., s_n} ),则分词概率为:
P(\text{Segmentation}) = \prod_{i=1}^n p(s_i)
ULM 的目标是找到所有可能的分词中概率最大的方式。

(2) 为什么需要剪枝?

初始词汇表非常大(可能包含冗余子词),剪枝可以:
- 去除低频或冗余子词(如 "ing" 和 "##ing" 可能保留一个)。
- 平衡词汇表大小与语义表达能力。

(3) 如何处理未登录词?

ULM 天然支持通过子词组合表达未登录词。例如:
- 新词 "ChatGPT" 可能被拆分为 ["Chat", "G", "PT"](假设这些子词在词汇表中)。


4. ULM 的特点

优点:

  1. 灵活的分词方式:
    支持动态选择最优分词(基于概率),而非固定合并规则。

    • 例如:"unhappily" 可以拆分为 ["un", "happ", "ily"] 或 ["un", "happy", "ly"],选择概率更高的方式。
  2. 多语言友好:
    与 SentencePiece 结合时,可直接处理多语言文本(无需空格分隔)。
  3. 抗噪声能力:
    低频子词会被自动剪枝,减少噪声影响。

缺点:

  1. 计算成本高:
    训练时需要计算所有可能分词的概率,复杂度为 ( O(n^2) )。
  2. 依赖初始化:
    初始词汇表的质量影响最终结果。

5. ULM vs BPE vs WordPiece

特性 BPE WordPiece ULM
核心策略 合并高频符号对 合并概率增益大的符号对 基于概率剪枝词汇表
训练方向 自底向上(合并) 自底向上(合并) 自顶向下(剪枝)
分词方式 贪婪匹配 贪婪匹配 动态规划(最优解)
多语言支持 需预分词 需预分词 直接处理原始文本(结合 SentencePiece)
典型应用 GPT BERT ALBERT、T5

6. 实际案例

案例 1:处理多义性分词

输入句子:"applepie"
- 可能的分词方式:
- ["apple", "pie"](概率高,语义合理)
- ["app", "lep", "ie"](概率低,无意义)
ULM 会选择概率更高的合理分词。

案例 2:未登录词处理

输入单词:"transformer"(假设未在训练数据中出现)
- ULM 可能拆分:["trans", "form", "er"](如果子词 "trans"、"form"、"er" 的概率较高)。


7. 实现工具:SentencePiece

  • 功能:
    SentencePiece 是一个开源库,支持以 ULM 或 BPE 作为底层算法,直接处理原始文本(无需预分词)。
  • 特点:
    • 将空格视为普通字符(适合中文、日文等无空格语言)。
    • 支持 Unicode 统一处理多语言。
  • 使用示例:
    import sentencepiece as spm
    spm.SentencePieceTrainer.train(
      input='data.txt',
      model_prefix='ulm_model',
      vocab_size=8000,
      model_type='unigram'  # 指定 ULM 算法
    )
    

8. 如何选择 ULM?

  • 适用场景:
    • 数据中包含大量未登录词或专业术语。
    • 需要处理多语言混合文本。
    • 对分词灵活性要求高(如诗歌、社交媒体文本)。
  • 不适用场景:
    • 资源受限(训练时间或计算能力不足)。
    • 数据分布简单(如纯英文新闻,BPE/WordPiece 已足够)。

9. 数学补充:损失函数

ULM 的优化目标是最大化训练数据的对数似然:
\mathcal{L} = \sum_{x \in \text{data}} \log P(x)
其中 ( P(x) ) 是句子 ( x ) 所有可能分词方式的概率之和。
由于直接计算所有分词方式不可行,实际通过动态规划近似求解。


通过这种概率驱动的剪枝策略,ULM 能够生成既紧凑又语义丰富的词汇表,尤其在处理复杂文本时表现出色。如果想进一步了解具体实现细节或应用案例,欢迎继续提问! 😊

中文tokenizer

以下是中文模型常用的 Tokenizer 类型及其特点的详细说明:


1. 中文分词的挑战

中文没有天然空格分隔词语,且存在大量组合词(如“人工智能” = “人工” + “智能”)。传统方法依赖分词工具(如结巴分词),但现代语言模型更倾向于使用 子词分词(Subword Tokenization),以解决未登录词(OOV)问题,并捕捉词语的组成结构。


2. 中文模型的常见 Tokenizer 类型

(1) 基于字符的分词(Character-Level)

  • 原理:将每个汉字视为一个独立的 Token。
    • 例如:“我喜欢猫” → ["我", "喜", "欢", "猫"]。
  • 优点:
    • 词汇表极小(约 2 万汉字覆盖 99% 文本)。
    • 天然支持所有组合词,无未登录词问题。
  • 缺点:
    • 序列长度较长(如一篇千字文需处理 1000+ Token)。
    • 丢失词语级语义(如“喜欢”拆成“喜”和“欢”可能破坏语义)。
  • 应用场景:早期模型如 TextCNN、部分 RNN 模型。

(2) 基于子词的分词(Subword-Level)

现代中文模型的主流选择,结合字符和词语的优点,常用以下算法:

a. WordPiece(如 BERT 中文版)
  • 原理:
    • 预分词:将文本按字符切分(如“我喜欢猫” → ["我", "喜", "欢", "猫"])。
    • 合并高频字符对:例如合并“喜”和“欢” → ["我", "喜欢", "猫"]。
  • 实现:
    • 中文 BERT 使用 BertWordPieceTokenizer,词汇表包含汉字和常见子词。
    • 例子:词汇表中可能包含 "喜欢"、"人工"、"##智能"(## 表示子词前缀)。
  • 优点:
    • 平衡序列长度与语义。
    • 支持未登录词拆分(如“人工智能” → ["人工", "##智能"])。
  • 缺点:
    • 需要预分词(中文需先按字符切分)。
b. SentencePiece(如 ALBERT、T5 中文版)
  • 原理:
    • 直接处理原始文本,无需预分词。
    • 使用 BPE 或 ULM 算法构建子词词汇表。
  • 特点:
    • 将空格视为普通字符(适合中文无需空格的特点)。
    • 支持多语言混合文本。
  • 例子:
    # SentencePiece 处理中文的示例
    import sentencepiece as spm
    sp = spm.SentencePieceProcessor()
    sp.load("chinese_sp.model")
    text = "人工智能是未来趋势"
    tokens = sp.encode_as_pieces(text)  # 输出:["▁", "人工", "智能", "是", "未来", "趋势"]
    
  • 优点:
    • 无需预分词,直接处理原始文本。
    • 更适合无空格语言(如中文、日文)。
c. BPE(如 GPT 中文版)
  • 原理:合并高频相邻字符对,例如:
    • “人工智能” → ["人", "工", "智", "能"] → 合并高频对后可能变为 ["人工", "智能"]。
  • 应用:部分中文 GPT 模型使用 BPE,但需注意中文的字符频率分布与英文不同。

3. 典型中文模型的 Tokenizer 实现

模型 Tokenizer 类型 特点 示例词汇表条目
BERT-中文 WordPiece 预分词为字符,合并高频子词 "我", "喜欢", "##智能"
ALBERT-中文 SentencePiece(Unigram) 直接处理原始文本,概率剪枝词汇表 "▁人工", "智能", "趋势"
GPT-3 中文 BPE 合并高频字符对,适合生成任务 "人工", "智能", "未来"
HuggingFace 多语言模型 SentencePiece 统一处理多语言,支持中文无空格 "▁Artificial", "▁人工"

4. 中文 Tokenizer 的关键设计选择

(1) 是否保留空格?

  • 中文无需空格:SentencePiece 直接处理原始文本,将空格视为特殊符号(如 "▁")。
  • 中英文混合场景:需统一处理,例如 "ChatGPT很棒" → ["Chat", "G", "PT", "▁很棒"]。

(2) 词汇表大小

  • 中文词汇表通常比英文大:
    • 英文典型词汇表:30k–50k。
    • 中文典型词汇表:20k–60k(包含常用汉字、子词、专有名词)。

(3) 特殊符号处理

  • 中文需处理全角/半角符号(如 “” vs "")、标点(如 ,、。)等。

5. 实际案例

案例 1:BERT-中文

  • Tokenizer: BertWordPieceTokenizer
  • 分词过程:
    1. 按字符切分:"人工智能" → ["人", "工", "智", "能"]。
    2. 合并高频子词对:["人工", "智能"](如果 "人工" 和 "智能" 在词汇表中)。
  • 词汇表条目:包含单字(如 "人")、词语(如 "人工")和子词(如 "##智能")。

案例 2:T5-中文(使用 SentencePiece)

  • Tokenizer: SentencePiece (Unigram)
  • 分词过程:
    1. 直接处理原始文本:"人工智能是未来趋势"。
    2. 动态选择概率最大的分词方式:["▁人工", "智能", "▁是", "▁未来", "▁趋势"]。

6. 如何选择中文 Tokenizer?

  • 任务类型:
    • 理解任务(如分类、NER):优先 WordPiece 或 SentencePiece。
    • 生成任务(如文本生成):BPE 或 SentencePiece 更灵活。
  • 数据特点:
    • 专业领域(如医学、法律):需自定义词汇表,添加领域子词。
  • 模型兼容性:
    • 使用预训练模型时,必须匹配其原始 Tokenizer(如 BERT 中文版用 WordPiece)。

7. 工具与库推荐

  • Hugging Face Tokenizers:支持 BertWordPieceTokenizer,适合中文 BERT。
  • SentencePiece:适合多语言、无空格文本,支持 ULM/BPE。
  • Jieba 分词:传统中文分词工具,可与子词分词结合使用(预分词后输入)。

总结

中文模型主要使用 子词分词器,主流选择包括:
1. WordPiece(如 BERT-中文):平衡字符与词语,需预分词。
2. SentencePiece(如 ALBERT、T5):直接处理原始文本,适合多语言。
3. BPE(如部分 GPT 模型):合并高频字符对,适合生成任务。

选择时需考虑任务需求、数据特点及模型兼容性。

SentencePiece


SentencePiece 是一种通用的子词分词(Subword Tokenization)工具,专为处理无空格语言(如中文、日文)和多语言混合文本设计。它的核心目标是 直接处理原始文本,无需依赖预分词(如按空格分割),从而简化流程并提升灵活性。以下是 SentencePiece 的详细解析:


1. SentencePiece 的核心功能

  • 无需预分词:直接处理原始字符串(包括中文、日文等无空格语言)。
  • 统一处理多语言:可同时处理多种语言的混合文本(如中英混杂的句子)。
  • 支持多种算法:底层可选择 BPE(Byte-Pair Encoding)或 ULM(Unigram Language Model)。
  • 保留空格:将空格视为普通字符(用特殊符号 ▁ 表示),避免信息丢失。
  • 生成紧凑词汇表:通过算法生成子词集合,平衡语义表达与计算效率。

2. 为什么需要 SentencePiece?

传统分词工具的局限性:

  • 依赖预分词:
    中文等语言需先用工具(如结巴分词)切分词语,再应用子词算法,流程复杂。
  • 无法处理无空格语言:
    英文 BPE/WordPiece 依赖空格分割单词,但中文、日文等语言没有空格。
  • 多语言混合困难:
    中英混杂的文本(如 "ChatGPT很棒")需要统一的分词策略。

SentencePiece 的优势:

  • 端到端处理:直接输入原始文本,自动学习子词分割规则。
  • 统一编码:无论语言是否有空格,均以相同方式处理。
  • 灵活适配:适合训练多语言模型(如 mT5、XLMRoberta)。

3. SentencePiece 的工作原理

步骤 1:文本标准化

  • 将输入文本转换为 Unicode 格式。
  • 处理空格:在句首和句尾添加特殊符号 ▁(U+2581),并将中间的空格替换为 ▁。
    • 例如:"Hello 世界" → "▁Hello▁世界"。

步骤 2:训练子词模型

选择底层算法(BPE 或 ULM),统计文本中的字符/子词频率,生成词汇表。

a. 使用 BPE 算法
  • 合并高频字符对,逐步构建词汇表(与英文 BPE 类似,但直接处理原始字节)。
b. 使用 ULM 算法
  • 基于概率剪枝初始词汇表,保留对数据似然贡献最大的子词。

步骤 3:编码与解码

  • 编码:将文本转换为子词序列(如 ["▁", "Hello", "▁", "世", "界"])。
  • 解码:将子词序列还原为原始文本(自动去除 ▁ 并恢复空格)。

4. SentencePiece 的关键特性

(1) 空格处理

  • 空格符号 ▁:
    • 句首和词间的空格用 ▁ 表示,例如 "I love NLP" → "▁I▁love▁NLP"。
    • 解码时会自动将 ▁ 转换为空格。
  • 意义:
    • 保留文本中的空格信息(如专有名词中的空格:"New York" → "▁New▁York")。
    • 统一处理所有语言,避免因空格缺失导致的分词错误。

(2) 支持多语言

  • 无语言限制:
    SentencePiece 不依赖特定语言的预分词规则,可处理任意 Unicode 字符。
  • 混合语言示例:
    输入: "ChatGPTは優秀なAIです。"
    分词: ["▁", "Chat", "G", "PT", "は", "優秀", "な", "AI", "です", "。"]
    

(3) 子词算法的选择

  • BPE 模式:
    • 适合生成任务(如 GPT 系列),合并高频字符对。
    • 词汇表大小可控,但可能生成不语义连贯的子词。
  • ULM 模式:
    • 基于概率剪枝,保留语义更丰富的子词。
    • 适合理解任务(如 BERT、T5),但训练成本较高。

5. 实际应用场景

场景 1:中文分词

  • 输入:"人工智能是未来趋势"
  • 分词结果(ULM 算法):
    ["▁人工", "智能", "▁是", "▁未来", "▁趋势"]
    
  • 优势:
    无需先按字符或词语切分,直接学习子词组合(如 "人工" + "智能")。

场景 2:多语言混合文本

  • 输入:"ChatGPT很棒!"
  • 分词结果(BPE 算法):
    ["▁", "Chat", "G", "PT", "▁很棒", "!"]
    
  • 优势:
    统一处理英文单词和中文字符,保留语义信息。

6. 如何使用 SentencePiece?

步骤 1:安装库

pip install sentencepiece

步骤 2:训练模型

import sentencepiece as spm

# 训练配置
spm.SentencePieceTrainer.train(
    input="corpus.txt",     # 输入文本文件
    model_prefix="sp_model", # 输出模型名前缀
    vocab_size=20000,       # 目标词汇表大小
    model_type="bpe",       # 选择算法(bpe/unigram)
    user_defined_symbols=["[ENT]"], # 自定义保留符号(如实体标记)
    pad_id=0,               # 特殊符号的ID(需与模型对齐)
)

步骤 3:加载与使用模型

import sentencepiece as sp

# 加载模型
sp_model = sp.SentencePieceProcessor()
sp_model.load("sp_model.model")

# 编码文本
text = "人工智能是未来趋势"
tokens = sp_model.encode_as_pieces(text)
print(tokens)  # 输出:['▁人工', '智能', '▁是', '▁未来', '▁趋势']

# 解码
decoded = sp_model.decode_pieces(tokens)
print(decoded)  # 输出:人工智能是未来趋势

7. SentencePiece 的优缺点

优点:

  1. 无需预分词:直接处理原始文本,简化流程。
  2. 多语言友好:适合中文、日文、代码等无空格文本。
  3. 灵活控制词汇表:通过调整 vocab_size 和算法平衡效率与效果。

缺点:

  1. 训练成本高:ULM 模式需要大量计算资源。
  2. 长文本处理:若未合并长词,可能导致序列过长。

8. 与其他工具对比

工具 预分词需求 多语言支持 典型应用
SentencePiece 不需要 优秀 T5、ALBERT、XLNet
WordPiece 需要(如空格) 一般 BERT、DistilBERT
BPE 需要(如空格) 一般 GPT-2、RoBERTa

9. 常见问题

Q1:如何处理中文专有名词(如“支付宝”)?

  • 方案:在训练时增大 vocab_size,或通过 user_defined_symbols 强制保留特定词。

Q2:SentencePiece 是否适合小语种?

  • 是:即使数据量较少,也可通过调整 vocab_size 和算法(如 ULM)生成有效子词。

Q3:如何与 Hugging Face 库结合使用?

  • 示例:
    from transformers import AutoTokenizer
    
    # 加载 SentencePiece 模型
    tokenizer = AutoTokenizer.from_pretrained("t5-base")
    
    # 编码
    text = "人工智能是未来趋势"
    inputs = tokenizer(text, return_tensors="pt")
    

总结

SentencePiece 是一种 面向无空格语言和多语言场景的通用分词工具,通过直接处理原始文本和灵活选择子词算法(BPE/ULM),解决了传统分词工具的局限性。它在现代多语言模型(如 mT5、ALBERT)中广泛应用,是处理复杂文本任务的理想选择。

标签: 暂无
最后更新:2025年1月30日

sheep

think again

点赞
< 上一篇
下一篇 >

文章评论

取消回复

COPYRIGHT © 2021 heavensheep.xyz. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS