BERT Tokenizer文本处理详细解析
本文主要是学习[动手写 bert 系列] 02 tokenizer encode_plus, token_type_ids(mlm,nsp)专栏第二个视频的知识归纳总结。
1. BERT Tokenizer 基础知识
1.1 Tokenizer 初始化
from transformers import BertTokenizer
model_name = 'bert-base-uncased'
tokenizer = BertTokenizer.from_pretrained(model_name)
-
BertTokenizer是专门为 BERT 模型设计的tokenizer -
bert-base-uncased是一个预训练模型,特点:-
"base":基础规模(12层,768隐藏层维度)
-
"uncased":不分大小写,所有文本都会转为小写
-
词汇表大小:30522个token
-
最大序列长度:512个token
-
1.2 Tokenizer 的特殊token
这个上一节视频也有介绍,这节视频介绍得更细致一些。
tokenizer.special_tokens_map
# 输出:
{'unk_token': '[UNK]',
'sep_token': '[SEP]',
'pad_token': '[PAD]',
'cls_token': '[CLS]',
'mask_token': '[MASK]'}
# 将特殊token转换为对应的ID
tokenizer.convert_tokens_to_ids(special_tokens)
# 输出:[100, 102, 0, 101, 103]
-
[CLS](分类token):
-
位置:总是出现在序列开头
-
作用:用于分类任务的聚合表示
-
在BERT预训练中,CLS位置用于下一句预测(NSP)任务
-
-
[SEP](分隔token):
-
作用:分隔两个句子
-
在单个句子中也存在,标记句子结束
-
对于句子对任务,[SEP]分隔两个句子
-
-
[PAD](填充token):
-
作用:将不同长度的序列填充到相同长度
-
ID为0,便于在注意力机制中屏蔽
-
-
[UNK](未知token):
-
作用:表示词汇表中不存在的词
-
当遇到未登录词(OOV)时使用
-
-
[MASK](掩码token):
-
作用:用于掩码语言建模(MLM)任务
-
在预训练中,随机掩盖部分输入token
-
-
特殊tokenID对应关系:[UNK] → 100 [SEP] → 102 [PAD] → 0 [CLS] → 101 [MASK] → 103
1.3 编码和解码过程
# 编码特殊token
tokenizer.encode(special_tokens)
# 输出:[101, 100, 102, 0, 101, 103, 102]
# 解码回文本
tokenizer.decode([101, 100, 102, 0, 101, 103, 102])
# 输出:'[CLS] [UNK] [SEP] [PAD] [CLS] [MASK] [SEP]'
-
tokenizer.encode()自动添加了 [CLS] 和 [SEP] -
实际编码结果是:
[CLS] + 特殊token列表 + [SEP] -
注意有两个 [CLS] 和两个 [SEP],这是因为输入列表中包含这些token,tokenizer又自动添加了它们
2. 20 Newsgroups 数据集
作为了解即可,不是学习的重点内容。
2.1 数据集加载
from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
数据集特点:
-
来源:20个不同的新闻组(讨论组)
-
数据量:训练集11314个文档
-
类型:文本分类数据集
-
类别数:20类
2.2 数据结构
# 数据类型
type(newsgroups_train.data) # list
# 数据量
len(newsgroups_train.data) # 11314
len(newsgroups_train.target) # 11314(与数据一一对应)
# 查看类别分布
from collections import Counter
Counter(newsgroups_train.target)
类别分布分析:
-
大部分类别有约600个样本
-
最少的类别有377个样本(索引19)
-
最多的类别有600个样本(索引10)
-
整体相对平衡,但有一定差异
2.3 类别名称
newsgroups_train.target_names

20个类别分为4个大组:
-
计算机相关(comp.):comp.graphics:计算机图形学-windows.misc:Windows操作系统comp.sys.ibm.pc.hardware:IBM PC硬件comp.sys.mac.hardware:Mac硬件comp.windows.x:X Window系统
-
休闲娱乐(rec.):rec.autos:汽车rec.motorcycles:摩托车rec.sport.baseball:棒球
rec.sport.hockey:曲棍球 -
科学技术(sci.):sci.crypt:密码学sci.electronics:电子学sci.med:医学 sci.space:太空
-
讨论话题(talk.,soc.,alt.):talk.politics.guns:政治-枪支talk.politics.mideast:政治-中东talk.politics.misc:政治-杂项talk.religion.misc:宗教-杂项soc.religion.christian:社会-基督教alt.atheism:无神论misc.forsale:二手交易
3. Tokenizer 高级功能
本节的重点学习内容!
3.1 核心概念
input_ids:token在词汇表中的索引,将文本转换为模型可理解的数字序列。
attention_mask:二进制掩码,指示哪些位置是真实token,哪些是padding。1表示真实token,0表示padding token。防止padding token影响注意力计算
token_type_ids(或segment_ids):用于区分句子对中的两个句子。第一个句子标记为0,第二个句子标记为1。在单句任务中,所有token_type_ids都是0。(之前没有提到的重点内容)
tokenizer 的核心方法对比:
| 方法 | 输入类型 | 输出 | 特点 |
|---|---|---|---|
encode_plus() |
单个文本/句子对 | 完整编码字典 | 功能最全,可控制所有参数 |
__call__() |
单文本、列表或批处理 | 完整编码字典 | 推荐用法,支持批处理 |
encode() |
单个文本 | token ID列表 | 只返回input_ids |
batch_encode_plus() |
文本列表 | 批处理的编码字典 | 已弃用,用__call__替代 |
encode_plus 是一个功能全面的文本编码方法,但在新版Transformers中,建议直接使用 tokenizer() 方法,它提供了相同的功能且接口更统一。无论是处理单句、句子对还是批量数据,都能灵活应对各种NLP任务的输入需求。
3.2 单句编码
test_news = newsgroups_train.data[:3]
len(test_news[2]) # 1981个字符
# 单句编码
result = tokenizer(test_news[0], truncation=True, max_length=32)
参数详解:
-
truncation=True:如果序列超过最大长度,则截断 -
max_length=32:设置最大序列长度 -
自动添加的token:
[CLS]和[SEP]
输出结果包含三个关键字段:
-
input_ids:token ID序列 -
token_type_ids:全为0(单句任务) -
attention_mask:全为1(没有padding)
3.3 句子对编码
# 句子对编码
result_pair = tokenizer.encode_plus(
text=test_news[0], # 第一个句子
text_pair=test_news[1], # 第二个句子
max_length=32,
truncation=True
)
encode_plus 输出详解:
-
input_ids结构:
-
[CLS] + 句子1 + [SEP] + 句子2 + [SEP] -
示例:
[101, 2013, ..., 102, 2013, ..., 102]
-
-
token_type_ids:
-
句子1的token:全部为0
-
句子2的token:全部为1
-
清晰区分两个句子
-
-
attention_mask:
-
所有真实token为1
-
3.4 截断策略
-
'longest_first'(默认):
-
从较长的句子开始移除token
-
直到满足最大长度要求
-
对于句子对,优先截断较长的那个句子
-
-
'only_first':
-
只截断第一个句子
-
第二个句子保持不变
-
-
'only_second':
-
只截断第二个句子
-
-
'do_not_truncate':
-
不截断,如果超过最大长度会报错
-
3.5 解码示例
# 解码示例
decoded_text = tokenizer.decode(result_pair['input_ids'])
# 输出:'[CLS] from : lerxst @ wam. umd. edu [SEP] from : guykuo @ carson. u. washington. edu [SEP]'
-
可以看到完整的结构:
[CLS] + 句子1 + [SEP] + 句子2 + [SEP] -
电子邮件地址被分割:
guykuo @ carson . u . washington . edu -
BERT tokenizer使用WordPiece分词,将复杂词分解为子词
4. 实际应用注意事项
4.1 文本预处理
-
大小写处理:
uncased模型会自动转为小写cased模型保留原始大小写
-
特殊字符:
- BERT tokenizer能处理各种标点符号
- 网址、电子邮件等会被适当分割
-
中文处理:
- 对中文按字切分
- 每个中文字符作为独立的token
4.2 BERT预训练任务相关
MLM(掩码语言建模)
-
随机掩盖输入token(15%概率)
-
被掩盖的token中:
-
80%替换为[MASK]
-
10%替换为随机token
-
10%保持不变
-
-
模型预测被掩盖的原始token
NSP(下一句预测)
-
输入:两个句子A和B
-
任务:判断B是否是A的下一句
-
50%概率是真实下一句,50%是随机句子
-
使用[CLS]位置的输出进行分类
5. 总结
BERT tokenizer 可以理解为 BERT 模型处理文本时的“翻译官”——它负责把我们的文字翻译成模型能看懂的数字。既要处理好过长文本的截断,又要给短文本补位填充;既能处理单个句子,也能处理两个句子组合的任务;而且还完美契合了 BERT 训练时的掩码预测这些任务需求。在实际用起来的时候,掌握好 tokenizer 的各种小技巧,无论是整理数据、准备输入,还是优化效果、调试问题,都能帮你省不少心。用好这个“翻译官”,你的模型才能更好地理解你想让它理解的东西。
学习不是赛跑,是和自己一起的成长旅行。你走得每一步,都算数。 🌱一起加油吧!
更多推荐


所有评论(0)