一、简介

Tokenizer(分词器)是将自然语言文本映射为数字表示(tokens/IDs) 的工具,核心完成 3 件事:

  • 🔴 分词(Tokenization):将文本拆分为最小语义单元(token,如单词、子词、字符);
  • 🔴 编码(Encoding):将每个 token 映射为唯一的整数 ID;
  • 🔴 解码(Decoding):将整数 ID 还原为文本(逆向操作)。

展示分词可视化结果的网站https://tiktokenizer.vercel.app/

分词粒度:                                                                                                                                      不同模型采用不同的分词粒度,直接影响模型效果和效率:

分词粒度定义示例(文本:"Hello, world!")适用模型 重点特点
字符级(Character)按单个字符拆分["H", "e", "l", "l", "o", ",", " ", "w", "o", "r", "l", "d", "!"]小模型、低资源语言

粒度最细,词汇表小,但语义信息少

单词级(Word)按空格 / 标点拆分单词["Hello", ",", "world", "!"]基础 NLP 任务(如文本分类)语义清晰,但词汇表大(生僻词易 OOV)
子词级(Subword)拆分为常用子词(如 BPE)["Hello", ",", "world", "!"](GPT)/ ["He", "ll", "o", ",", "world", "!"](BERT)大模型(BERT/LLaMA/GPT)

平衡词汇表大小和OOV 率,工业级首选

术语解释

术语定义重点说明
Vocabulary(词汇表)token 与 ID 的映射字典(如 {"[PAD]":0, "hello":123})每个分词器有专属词汇表,模型训练 / 推理必须用同一套
OOV(Out of Vocabulary)未出现在词汇表中的 token子词分词可大幅降低 OOV 率,单词级分词 OOV 率高
Special Tokens(特殊 token)

模型定义的特殊标识,如:

-[PAD]:填充 token(统一序列长度)

- [CLS]:BERT 分类 token

- [SEP]:分隔 token

- [MASK]:BERT 掩码 token

- <bos>/<eos>:句子开始 / 结束 token

不同模型的特殊 token 不同,编码时必须正确添加
Max Length(最大长度)分词器允许的最大 token 数超过则截断,不足则填充,需匹配模型输入限制(如 BERT 最大 512)
Truncation(截断)超过最大长度时,截断文本(从左 / 右 / 中间)需指定截断策略(如 truncation="longest_first")
Padding(填充)不足最大长度时,用[PAD]填充需指定填充方向(如 padding="max_length")

三种主流的subword分词方法:BPE、WordPiece 和 Unigram Language Model

  • BPE:从字符级开始,迭代合并高频子词
  • WordPiece:从单词级开始,拆分低频词为子词
  • Unigram Language Model:基于概率选择最优子词集合

二、Hugging Face Tokenizers 库( 重点)

1. 核心优势
  • 高性能:Rust 底层实现,批量处理速度比纯 Python 快 10-100 倍;
  • 全覆盖:支持所有主流分词算法(BPE/WordPiece/Unigram);
  • 易扩展:可自定义词汇表、特殊 token;
  • 无缝衔接:与 transformers 库深度集成,支持所有预训练模型。
2. 核心使用流程实例

步骤 1:加载预训练分词器(最常用)  ,可从huggingface自动下载加载模型,也可事先下载至本地加载本地模型                                                                                            

从huggingface加载保存默认位置 

模型加载

# 从HuggingFace加载模型
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
tokenizer.save_pretrained("./bert-base-cased")
#从本地加载模型
tokenizer = AutoTokenizer.from_pretrained("./bert-base-cased")

步骤 2:编码文本(核心操作)

from transformers import AutoTokenizer

text = "I'm a happy man"

# 🔴 基础编码:返回token IDs
input_ids = tokenizer.encode(text,add_special_tokens=True)
print(input_ids)


# 🔴 详细编码:返回所有信息(推荐)
# tokenizer()包含分词 转换为ID 添加特殊token([CLS]、[SEP])填充/截断 生成attention_mask和   
#                                                                    token_type_ids

inputs = tokenizer(
    text, 
    max_length=21, 
    padding='max_length', 
    truncation=True, 
    return_offsets_mapping=True
)

print(inputs)

# {
#     'input_ids': [101, 1045, 1005, 1049, 1037, 3407, 1050, 102, 0, 0, ...],
#     'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...],
#     'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, ...],
#     'offset_mapping': [(0,0), (0,1), (1,3), (4,5), (7,12), (13,16), (0,0), (0,0), ...]
# }

关键输入:

  • input_ids - 文本的数字化表示
    • 将文本分词后转换为对应的 ID 序列
    • 每个数字代表词表中的一个 token
    • 例如:"I'm a happy man" → [101, 1045, 1005, 1049, 1037, 3407, 1050, 102]
      • 101 = [CLS](特殊开始符)
      • 1045 = I
      • 1005 = '
      • 102 = [SEP](特殊结束符)
  • token_type_ids - 句子分类标记
    • 用于区分不同的句子
    • 单句话:全为 0
    • 两句话(如问答):第一句为 0,第二句为 1
    • 例如:[0, 0, 0, 0, 0, 0, 0, 0](所有 token 都属于同一句)
  • attention_mask - 注意力掩码
    • 标记哪些 token 是真实内容,哪些是填充(padding)
    • 1 = 真实 token,0 = 填充 token
    • 例如:[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, ..., 0](前 8 个是真实,后面是填充)
    • 作用:告诉模型在计算注意力时忽略填充部分
  • offset_mapping - 位置映射
    • 记录每个 token 在原始文本中的起始和结束位置
    • 格式:[(start, end), ...]

步骤 3:解码(逆向操作)

# 索引转回文本(自动忽略特殊token)
text = tokenizer.decode(input_ids)
print(text) 

其他操作:

 句子分词tokenize:将文本拆分为模型可识别的最小单位(token)

# 基础分词(返回token列表)
tokens = tokenizer.tokenize("Hello, I love Transformer!")
print(tokens)  # 输出:['Hello', ',', 'I', 'love', 'Trans', '##former', '!']

# 批量分词
batch_tokens = tokenizer.tokenize(["Sentence 1", "Sentence 2"])

查看词典vocab

# 查看词典大小
print(f"词典大小:{tokenizer.vocab_size}")  # bert-base-cased 词典大小约30522

# 查看指定token的索引
print(tokenizer.vocab["Hello"])  # 输出对应数字索引
print(tokenizer.vocab["[CLS]"])  # 特殊token(BERT的句子起始符)

# 遍历词典(前5个)
for idx, (token, index) in enumerate(tokenizer.vocab.items()):
    if idx < 5:
        print(f"Token: {token}, Index: {index}")

索引转换

#编码:token → 数字索引(模型输入)
input_ids = tokenizer.convert_tokens_to_ids(tokens)
# 转换为token
tokens = tokenizer.convert_ids_to_tokens(input_ids)

填充(padding)截断 (truncation):                                                                              Transformer 模型要求输入长度固定,对短文本填充(padding)、长文本截断(truncation)

from transformers import AutoTokenizer
text = "I'm a happy man"

# 从本地加载模型
tokenizer = AutoTokenizer.from_pretrained("./bert-base-cased")

#tokenizer()包含分词 转换为 ID 添加特殊token([CLS]、[SEP])填充/截断 生成attention_mask和   
#token_type_ids

inputs = tokenizer(
    text, 
    max_length=21, 
    padding='max_length', 
    truncation=True, 
    return_offsets_mapping=True
)

print(inputs)

# {
#     'input_ids': [101, 1045, 1005, 1049, 1037, 3407, 1050, 102, 0, 0, ...],
#     'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...],
#     'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, ...],
#     'offset_mapping': [(0,0), (0,1), (1,3), (4,5), (7,12), (13,16), (0,0), (0,0), ...]
# }
完整实例
"""
功能:LLM 输入预处理完整流程(以LLaMA-2为例)
"""
from transformers import AutoTokenizer

# 1. 加载预训练分词器(LLaMA-2)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
# LLaMA无默认PAD token,需手动设置
tokenizer.pad_token = tokenizer.eos_token  # 用eos_token替代pad_token

# 2. 定义提示词模板(LLaMA-2对话模板)
def build_prompt(user_query):
    return f"<s>[INST] {user_query} [/INST] "

# 3. 批量处理用户输入
user_queries = [
    "介绍一下人工智能",
    "如何学习Python编程?",
    "大语言模型的核心原理是什么?"
]
prompts = [build_prompt(q) for q in user_queries]

# 4. 编码(适配LLaMA-2输入)
encoded = tokenizer(
    prompts,
    truncation=True,
    padding=True,
    max_length=128,
    return_tensors="pt",
    return_attention_mask=True
)

# 5. 输出核心信息
print("Input IDs形状:", encoded["input_ids"].shape)  # (3, 128)
print("Attention Mask形状:", encoded["attention_mask"].shape)  # (3, 128)

# 6. 解码验证
for i in range(len(prompts)):
    decoded = tokenizer.decode(encoded["input_ids"][i], skip_special_tokens=False)
    print(f"\n解码后提示词{i+1}:", decoded)
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐