关于 huggingface-tokenizers
huggingface-tokenizers 是面向 NLP 开发者的快速分词库,适用于数据与模型处理流程。它支持训练自定义分词器、批量编码,以及将 Token 位置映射回原文。
主要功能
- 01训练自定义分词器
- 02加载预训练分词器
- 03批量编码与填充
- 04配置规范化和处理流程
- 05追踪 Token 原文偏移
适用场景
- 01处理大型文本语料
- 02为自定义数据集训练分词器
- 03将 NLP 预测映射到原文位置
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ kalarislabs/ research-agent-skills --skill huggingface-tokenizers安装后在 Claude Code 中输入/huggingface-tokenizers确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/tokenization-algorithms.mdtraining.mdintegration.mdalgorithms.mdpipeline.md详细介绍
HuggingFace Tokenizers - NLP 快速分词
兼具 Rust 性能与 Python 易用性的快速、可用于生产环境的分词器。
何时使用 HuggingFace Tokenizers
在以下情况下使用 HuggingFace Tokenizers:
- 需要极快的分词速度(每 GB 文本少于 20 秒)
- 从头训练自定义分词器
- 希望跟踪对齐关系(token → 原文位置)
- 构建生产级 NLP 流水线
- 需要高效地对大型语料库进行分词
性能:
- 速度:在 CPU 上对 1GB 文本进行分词耗时少于 20 秒
- 实现:基于 Rust 核心,并提供 Python/Node.js 绑定
- 效率:比纯 Python 实现快 10-100 倍
可改用以下替代方案:
- SentencePiece:与语言无关,T5/ALBERT 使用
- tiktoken:OpenAI 为 GPT 模型开发的 BPE 分词器
- transformers AutoTokenizer:仅用于加载预训练分词器(内部使用此库)
快速入门
安装
# Install tokenizers
pip install tokenizers
# With transformers integration
pip install tokenizers transformers
加载预训练分词器
from tokenizers import Tokenizer
# Load from HuggingFace Hub
tokenizer = Tokenizer.from_pretrained("bert-base-uncased")
# Encode text
output = tokenizer.encode("Hello, how are you?")
print(output.tokens) # ['hello', ',', 'how', 'are', 'you', '?']
print(output.ids) # [7592, 1010, 2129, 2024, 2017, 1029]
# Decode back
text = tokenizer.decode(output.ids)
print(text) # "hello, how are you?"
训练自定义 BPE 分词器
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace
# Initialize tokenizer with BPE model
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
tokenizer.pre_tokenizer = Whitespace()
# Configure trainer
trainer = BpeTrainer(
vocab_size=30000,
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"],
min_frequency=2
)
# Train on files
files = ["train.txt", "validation.txt"]
tokenizer.train(files, trainer)
# Save
tokenizer.save("my-tokenizer.json")
训练时间:100MB 语料库约需 1-2 分钟,1GB 约需 10-20 分钟
使用填充进行批量编码
# Enable padding
tokenizer.enable_padding(pad_id=3, pad_token="[PAD]")
# Encode batch
texts = ["Hello world", "This is a longer sentence"]
encodings = tokenizer.encode_batch(texts)
for encoding in encodings:
print(encoding.ids)
# [101, 7592, 2088, 102, 3, 3, 3]
# [101, 2023, 2003, 1037, 2936, 6251, 102]
分词算法
详情、代码示例和参数表:references/tokenization-algorithms.md。适用此步骤时请阅读。
分词流水线
完整流水线:规范化 → 预分词 → 模型 → 后处理
规范化
清理并统一文本格式:
from tokenizers.normalizers import NFD, StripAccents, Lowercase, Sequence
tokenizer.normalizer = Sequence([
NFD(), # Unicode normalization (decompose)
Lowercase(), # Convert to lowercase
StripAccents() # Remove accents
])
# Input: "Héllo WORLD"
# After normalization: "hello world"
常见规范化器:
NFD、NFC、NFKD、NFKC- Unicode 规范化形式Lowercase()- 转换为小写StripAccents()- 去除重音符号(é → e)Strip()- 去除空白字符Replace(pattern, content)- 正则表达式替换
预分词
将文本拆分为类似单词的单元:
from tokenizers.pre_tokenizers import Whitespace, Punctuation, Sequence, ByteLevel
# Split on whitespace and punctuation
tokenizer.pre_tokenizer = Sequence([
Whitespace(),
Punctuation()
])
# Input: "Hello, world!"
# After pre-tokenization: ["Hello", ",", "world", "!"]
常见预分词器:
Whitespace()- 按空格、制表符和换行符拆分ByteLevel()- GPT-2 风格的字节级拆分Punctuation()- 分离标点符号Digits(individual_digits=True)- 将数字逐个拆分Metaspace()- 将空格替换为 ▁(SentencePiece 风格)
后处理
为模型输入添加特殊 token:
from tokenizers.processors import TemplateProcessing
# BERT-style: [CLS] sentence [SEP]
tokenizer.post_processor = TemplateProcessing(
single="[CLS] $A [SEP]",
pair="[CLS] $A [SEP] $B [SEP]",
special_tokens=[
("[CLS]", 1),
("[SEP]", 2),
],
)
常见模式:
# GPT-2: sentence <|endoftext|>
TemplateProcessing(
single="$A <|endoftext|>",
special_tokens=[("<|endoftext|>", 50256)]
)
# RoBERTa: <s> sentence </s>
TemplateProcessing(
single="<s> $A </s>",
pair="<s> $A </s> </s> $B </s>",
special_tokens=[("<s>", 0), ("</s>", 2)]
)
对齐跟踪
跟踪 token 在原文中的位置:
output = tokenizer.encode("Hello, world!")
# Get token offsets
for token, offset in zip(output.tokens, output.offsets):
start, end = offset
print(f"{token:10} → [{start:2}, {end:2}): {text[start:end]!r}")
# Output:
# hello → [ 0, 5): 'Hello'
# , → [ 5, 6): ','
# world → [ 7, 12): 'world'
# ! → [12, 13): '!'
使用场景:
- 命名实体识别(将预测结果映射回文本)
- 问答(提取答案片段)
- token 分类(将标签与原始位置对齐)
与 transformers 集成
使用 AutoTokenizer 加载
from transformers import AutoTokenizer
# AutoTokenizer automatically uses fast tokenizers
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Check if using fast tokenizer
print(tokenizer.is_fast) # True
# Access underlying tokenizers.Tokenizer
fast_tokenizer = tokenizer.backend_tokenizer
print(type(fast_tokenizer)) # <class 'tokenizers.Tokenizer'>
将自定义分词器转换为 transformers 格式
from tokenizers import Tokenizer
from transformers import PreTrainedTokenizerFast
# Train custom tokenizer
tokenizer = Tokenizer(BPE())
# ... train tokenizer ...
tokenizer.save("my-tokenizer.json")
# Wrap for transformers
transformers_tokenizer = PreTrainedTokenizerFast(
tokenizer_file="my-tokenizer.json",
unk_token="[UNK]",
pad_token="[PAD]",
cls_token="[CLS]",
sep_token="[SEP]",
mask_token="[MASK]"
)
# Use like any transformers tokenizer
outputs = transformers_tokenizer(
"Hello world",
padding=True,
truncation=True,
max_length=512,
return_tensors="pt"
)
常见模式
从迭代器训练(大型数据集)
from datasets import load_dataset
# Load dataset
dataset = load_dataset("wikitext", "wikitext-103-raw-v1", split="train")
# Create batch iterator
def batch_iterator(batch_size=1000):
for i in range(0, len(dataset), batch_size):
yield dataset[i:i + batch_size]["text"]
# Train tokenizer
tokenizer.train_from_iterator(
batch_iterator(),
trainer=trainer,
length=len(dataset) # For progress bar
)
性能:处理 1GB 数据约需 10-20 分钟
启用截断和填充
# Enable truncation
tokenizer.enable_truncation(max_length=512)
# Enable padding
tokenizer.enable_padding(
pad_id=tokenizer.token_to_id("[PAD]"),
pad_token="[PAD]",
length=512 # Fixed length, or None for batch max
)
# Encode with both
output = tokenizer.encode("This is a long sentence that will be truncated...")
print(len(output.ids)) # 512
多进程
from tokenizers import Tokenizer
from multiprocessing import Pool
# Load tokenizer
tokenizer = Tokenizer.from_file("tokenizer.json")
def encode_batch(texts):
return tokenizer.encode_batch(texts)
# Process large corpus in parallel
with Pool(8) as pool:
# Split corpus into chunks
chunk_size = 1000
chunks = [corpus[i:i+chunk_size] for i in range(0, len(corpus), chunk_size)]
# Encode in parallel
results = pool.map(encode_batch, chunks)
加速比:使用 8 个核心时可达 5-8 倍
性能基准测试
训练速度
| 语料库大小 | BPE(30k 词汇表) | WordPiece(30k) | Unigram(8k) |
|---|---|---|---|
| 10 MB | 15 秒 | 18 秒 | 25 秒 |
| 100 MB | 1.5 分钟 | 2 分钟 | 4 分钟 |
| 1 GB | 15 分钟 | 20 分钟 | 40 分钟 |
硬件:16 核 CPU,在英文 Wikipedia 上测试
分词速度
| 实现方式 | 1 GB 语料库 | 吞吐量 |
|---|---|---|
| 纯 Python | 约 20 分钟 | 约 50 MB/分钟 |
| HF Tokenizers | 约 15 秒 | 约 4 GB/分钟 |
| 加速比 | 80 倍 | 80 倍 |
测试:英文文本,平均句长为 20 个单词
内存用量
| 任务 | 内存 |
|---|---|
| 加载分词器 | 约 10 MB |
| 训练 BPE(30k 词汇表) | 约 200 MB |
| 编码 100 万个句子 | 约 500 MB |
支持的模型
可通过 from_pretrained() 使用的预训练分词器:
BERT 系列:
bert-base-uncased、bert-large-caseddistilbert-base-uncasedroberta-base、roberta-large
GPT 系列:
gpt2、gpt2-medium、gpt2-largedistilgpt2
T5 系列:
t5-small、t5-base、t5-largegoogle/flan-t5-xxl
其他:
facebook/bart-base、facebook/mbart-large-cc25albert-base-v2、albert-xlarge-v2xlm-roberta-base、xlm-roberta-large
浏览全部模型:https://huggingface.co/models?library=tokenizers
参考资料
- 训练指南 - 训练自定义分词器、配置训练器、处理大型数据集
- 算法深入解析 - 详细介绍 BPE、WordPiece、Unigram
- 流水线组件 - 规范化器、预分词器、后处理器、解码器
- Transformers 集成 - AutoTokenizer、PreTrainedTokenizerFast、特殊词元
资源
- 文档:https://huggingface.co/docs/tokenizers
- GitHub:https://github.com/huggingface/tokenizers ⭐ 9,000+
- 版本:0.20.0+
- 课程:https://huggingface.co/learn/nlp-course/chapter6/1
- 论文:BPE(Sennrich 等,2016)、WordPiece(Schuster 和 Nakajima,2012)
Agent 操作流程
- 检查环境。 检查 GPU 类型、内存和驱动/CUDA 版本(
nvidia-smi)、框架版本,以及数据集的位置和大小。 - 明确输入。 根据数据或用户确认格式、标识符和参数。任何会改变结果的值都应询问确认,不要猜测。
- 先运行小规模版本。 执行冒烟测试:使用小型模型或数据子集,运行少量步骤,并确认损失下降且检查点成功保存。
- 根据上述说明和参考资料执行完整任务。
- 验证结果。 在留出数据上跟踪指标,与基线进行比较,并记录随机种子、配置和硬件信息。
- 报告。 说明运行内容(版本、命令、参数)、检查项目以及仍不确定之处。
| 如果出现这种情况 | 请执行以下操作 |
|---|---|
| CUDA 显存不足 | 减小批次大小,启用梯度累积/检查点或混合精度,或者对模型进行分片。 |
| 损失为 NaN 或发散 | 降低学习率,检查数据中是否有无效值,并启用梯度裁剪。 |
| 当前安装版本中缺少这些说明里提到的函数、标志或端点 | 查阅已安装版本自身的文档(help()、--help、官方文档),调整用法并告知用户。切勿编造 API。 |
| 必需的输入、标识符或参数不明确 | 询问用户,或在运行前明确说明所采用的假设。 |
诚信规则
- 切勿捏造结果、参数、标识符、引文或统计数据。如果无法运行或验证某项内容,请如实说明。
- 没有日志时,切勿声称取得了训练结果;启动大型任务前应估算计算成本。
- 此处与特定版本相关的细节可能已过时:请根据已安装版本的官方文档进行确认。
- 对于需要付费、占用共享 GPU 或云配额、涉及个人或患者数据,或无法撤销的操作,必须先征求同意。
相关技能
transformers:用于加载 Hub 模型、运行流水线推理、文本生成,以及在 NLP、视觉、音频等任务上使用 Trainer 微调的 Hugging Face Transformers……sentencepiece:与语言无关的分词器,将文本视为原始 Unicode。
评论
支持 Markdown