from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace
import os
# 初始化BPE分词器
tokenizer = Tokenizer(BPE())
tokenizer.pre_tokenizer = Whitespace()
# 配置训练器
trainer = BpeTrainer(
vocab_size=1000,
special_tokens=["<|endoftext|>", "<unk>", "<pad>"]
)
# 指定目录并收集所有txt文件路径
root_dir = r"F:python codesHeroes"
file_paths = []
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith('.txt'):
file_path = os.path.join(root, file)
file_paths.append(file_path)
print(f"找到文件: {file_path}")
if not file_paths:
print("未找到任何txt文件,请检查目录是否正确")
else:
# 训练分词器
tokenizer.train(file_paths, trainer)
print("分词器训练完成")
tokenizer.save("bpe_tokenizer.json")
print("分词器已保存为 bpe_tokenizer.json")
# 获取词表
vocab = tokenizer.get_vocab()
# 按照词频从高到低排序
sorted_vocab = sorted(vocab.items(), key=lambda x: x[1], reverse=True)
word_list = [word for word, _ in sorted_vocab]
# 将词表保存到文件中
with open("bpe_vocabulary.txt", "w", encoding="utf-8") as f:
for word in word_list:
f.write(word + "
")
print("BPE词表已保存到 bpe_vocabulary.txt")
要理解这段代码,我们需要逐行拆解其功能,从 “导入依赖” 到 “训练 & 保存分词器”,每个步骤都对应 BPE(字节对编码)分词器构建的核心流程。以下是一行行的详细解读:
1. 导入必要的库和模块
python
运行
from tokenizers import Tokenizer
作用:从 Hugging Face 开源的库中导入核心类
tokenizers。说明:
Tokenizer是所有分词器(包括 BPE、WordPiece 等)的基础容器,负责管理分词逻辑、词表、编码 / 解码等核心功能。
Tokenizer
python
运行
from tokenizers.models import BPE
作用:从模块导入
tokenizers.models类(Byte Pair Encoding,字节对编码)。说明:
BPE是一种常用的分词算法,核心思想是 “从基础字符开始,不断合并出现频率最高的字符对”,能平衡词汇量和语义完整性(适合处理多语言、未登录词)。
BPE
python
运行
from tokenizers.trainers import BpeTrainer
作用:从模块导入
tokenizers.trainers类。说明:
BpeTrainer是专门用于训练 BPE 分词器的工具,负责定义训练规则(如词表大小、特殊符号)、处理训练数据、生成词表等。
BpeTrainer
python
运行
from tokenizers.pre_tokenizers import Whitespace
作用:从模块导入
tokenizers.pre_tokenizers类。说明:
Whitespace(预分词器)是训练前的 “数据预处理步骤”,
pre_tokenizers的功能是 “按空格分割文本”(例如将
Whitespace拆为
"hello world"),为后续 BPE 合并做准备。
["hello", "world"]
python
运行
import os
作用:导入 Python 内置的模块。说明:
os模块用于与操作系统交互,这里主要用来遍历文件夹、获取文件路径(收集训练用的 txt 文件)。
os
2. 初始化 BPE 分词器
python
运行
# 初始化BPE分词器
tokenizer = Tokenizer(BPE())
作用:创建一个基于 BPE 算法的分词器实例。说明:表示 “用 BPE 模型初始化分词器”,此时分词器还没有词表,需要后续通过训练生成。
Tokenizer(BPE())
python
运行
tokenizer.pre_tokenizer = Whitespace()
作用:为初始化的分词器绑定 “预分词规则”。说明:指定分词器在处理文本时,先按空格分割文本(预分词),再对分割后的片段进行 BPE 合并。如果不指定预分词器,BPE 会直接从原始字符开始处理,可能导致效率低下。
3. 配置 BPE 训练器
python
运行
# 配置训练器
trainer = BpeTrainer(
vocab_size=1000,
special_tokens=["<|endoftext|>", "<unk>", "<pad>"]
)
作用:创建 BPE 训练器实例,并定义训练的核心参数。参数解读:
:指定训练完成后词表的总大小为 1000(包括普通词汇和特殊符号)。词表大小需根据数据量调整,数据量小时词表不宜过大(避免过拟合)。
vocab_size=1000:定义分词器需要识别的特殊符号,这些符号不参与 BPE 合并,需手动指定:
special_tokens=[...]
:文本结束符(表示一段文本的结尾,常见于 GPT 类模型);
<|endoftext|>:未知词符(遇到词表中没有的词时,用该符号替换);
<unk>:填充符(用于将不同长度的文本补成相同长度,方便批量训练)。
<pad>
4. 收集训练数据(遍历文件夹找 txt 文件)
python
运行
# 指定目录并收集所有txt文件路径
root_dir = r"F:python codesHeroes"
作用:定义训练数据所在的根文件夹路径。说明:前缀表示 “原始字符串”,避免路径中的
r被解析为转义字符(例如
不会把
r"F: est"解析为制表符)。需根据实际 txt 文件存放路径修改。
python
运行
file_paths = []
作用:创建一个空列表,用于存储所有找到的 txt 文件路径。
file_paths
python
运行
for root, dirs, files in os.walk(root_dir):
作用:调用遍历
os.walk()文件夹及其所有子文件夹。返回值解读:
root_dir
:当前正在遍历的文件夹路径;
root:当前文件夹下的所有子文件夹列表;
dirs:当前文件夹下的所有文件列表。
files
python
运行
for file in files:
作用:遍历当前文件夹()下的所有文件。
root
python
运行
if file.endswith('.txt'):
作用:筛选出后缀为的文件(只用 txt 文件作为训练数据,避免其他格式文件干扰)。
.txt
python
运行
file_path = os.path.join(root, file)
作用:将 “当前文件夹路径(root)” 和 “文件名(file)” 拼接成完整的文件路径。例子:若是
root,
F:python codesHeroes是
file,则
hero1.txt为
file_path。
F:python codesHeroeshero1.txt
python
运行
file_paths.append(file_path)
作用:将拼接好的 txt 文件路径添加到列表中,完成 “收集训练数据路径” 的操作。
file_paths
python
运行
print(f"找到文件: {file_path}")
作用:打印找到的 txt 文件路径,方便用户确认 “是否正确找到目标文件”(排查路径错误)。
5. 训练分词器(核心逻辑)
python
运行
if not file_paths:
作用:判断列表是否为空(即是否找到任何 txt 文件)。
file_paths
python
运行
print("未找到任何txt文件,请检查目录是否正确")
作用:若未找到 txt 文件,打印错误提示,避免后续代码报错(无数据时无法训练)。
python
运行
else:
作用:若找到 txt 文件,执行后续的 “训练 – 保存” 逻辑。
python
运行
# 训练分词器
tokenizer.train(file_paths, trainer)
作用:用收集到的 txt 文件训练 BPE 分词器,是整个代码的核心步骤。过程解读:
分词器读取中的所有 txt 文件内容;按
file_paths预分词规则分割文本;
Whitespace按规则合并高频字符对,直到词表大小达到
BpeTrainer;将生成的词表绑定到
vocab_size=1000中,此时分词器具备 “编码文本” 的能力。
tokenizer
python
运行
print("分词器训练完成")
作用:提示训练完成,方便用户感知流程进度。
python
运行
tokenizer.save("bpe_tokenizer.json")
作用:将训练好的分词器(包含词表、预分词规则、BPE 模型参数)保存为文件。说明:后续使用时,只需通过
bpe_tokenizer.json即可加载分词器,无需重新训练。
Tokenizer.from_file("bpe_tokenizer.json")
python
运行
print("分词器已保存为 bpe_tokenizer.json")
作用:提示分词器保存完成,告知用户文件名称和位置(默认保存在代码运行目录下)。
6. 提取并保存词表
python
运行
# 获取词表
vocab = tokenizer.get_vocab()
作用:从训练好的分词器中提取词表字典。说明:是一个
vocab的字典(例如
{词: 词ID}),词 ID 是分词器编码时用的数字标识。
{"the": 5, "a": 12}
python
运行
# 按照词频从高到低排序
sorted_vocab = sorted(vocab.items(), key=lambda x: x[1], reverse=True)
作用:对词表按 “词 ID” 倒序排序(间接体现词频高低)。逻辑解读:
:将字典转为
vocab.items()的元组列表;
(词, 词ID):按元组的第 2 个元素(词 ID)排序;
key=lambda x: x[1]:倒序排列(BPE 训练中,词频越高的词,词 ID 越小,倒序后高频词排在前面)。
reverse=True
python
运行
word_list = [word for word, _ in sorted_vocab]
作用:从排序后的词表中提取 “纯词列表”,去掉词 ID。说明:表示 “忽略该变量”(这里不需要词 ID,只需要词本身),
_最终是
word_list的格式。
["<|endoftext|>", "the", "a", ...]
python
运行
# 将词表保存到文件中
with open("bpe_vocabulary.txt", "w", encoding="utf-8") as f:
作用:创建文件,以 “写入模式(w)” 和 “UTF-8 编码” 打开(避免中文乱码)。说明:
bpe_vocabulary.txt语句会自动管理文件关闭,避免手动关闭文件的遗漏。
with
python
运行
for word in word_list:
f.write(word + "
")
作用:将中的每个词按 “一行一个词” 的格式写入
word_list。例子:文件内容会是:
bpe_vocabulary.txt
plaintext
<|endoftext|>
<unk>
<pad>
the
a
...
python
运行
print("BPE词表已保存到 bpe_vocabulary.txt")
作用:提示词表保存完成,方便用户后续查看词表内容(验证词表是否符合预期)。
整体流程总结
这段代码的核心目标是基于自定义 txt 数据训练一个 BPE 分词器,完整流程可概括为:
导入依赖 → 2. 初始化 BPE 分词器(绑定预分词规则) → 3. 配置训练器(指定词表大小、特殊符号) → 4. 遍历文件夹收集 txt 训练数据 → 5. 训练分词器 → 6. 保存分词器和词表。
训练后的分词器可用于 NLP 任务(如文本编码、模型预训练),词表文件则方便人工检查分词效果。



















暂无评论内容