news 2026/9/11 19:25:41

Transformers 中的 CPM 中文预训练语言模型:GPT-2 架构与 Jieba-RS + SentencePiece 分词器解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Transformers 中的 CPM 中文预训练语言模型:GPT-2 架构与 Jieba-RS + SentencePiece 分词器解析

Transformers 中的 CPM 中文预训练语言模型:GPT-2 架构与 Jieba-RS + SentencePiece 分词器解析

【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers

CPM(Chinese Pre-trained Language Model)是清华大学团队发布的面向中文的生成式预训练语言模型,本文基于本仓库的 CPM 模型文档(对应 英文版),结合源码实现,系统讲解 CPM 的模型背景、与 GPT-2 的关系,以及CpmTokenizer/CpmTokenizerFast两套分词器的设计原理、构造参数与实际用法。读完本文,你将掌握 CPM 分词器的完整工作流程,并能在中文生成任务中正确加载与使用它。

CPM 模型概述:面向中文的生成式预训练语言模型

CPM 模型由 Zhengyan Zhang、Xu Han、Hao Zhou、Pei Ke、Yuxian Gu、Deming Ye、Yujia Qin 等学者在论文 CPM: A Large-scale Generative Chinese Pre-trained Language Model 中提出(技术报告,2020-12-01 发布于 HF Papers,2021-04-10 贡献给 Hugging Face Transformers)。该模型由社区贡献者 canwenxu 提供,原始实现位于 TsinghuaAI/CPM-Generate。

论文摘要的核心事实如下:

  • 背景:GPT-3 凭借 1750 亿参数和 570GB 训练数据展现出强大的 few-shot(甚至 zero-shot)学习能力,但其训练语料以英文为主,且参数并未公开,难以直接应用于中文 NLP 任务。
  • CPM 的定位:CPM 在大规模中文训练数据上进行生成式预训练,拥有26 亿参数100GB 中文训练数据,在当时是最大的中文预训练语言模型。
  • 能力:可支撑对话、作文生成、完形填空、语言理解等多种下游中文 NLP 任务;实验表明其在 few-shot(甚至 zero-shot)设定下表现良好。

需要说明的是,上述数字(26 亿参数、100GB 数据)来自论文摘要原文,属于论文披露的客观信息;是否"最大"仅指论文发表时的状况,不宜延伸为当前结论。

架构要点:与 GPT-2 相同的解码器架构

文档中的 Tip 明确说明:

CPM 的架构与 GPT-2 相同,区别仅在于分词(tokenization)方法。API 参考信息请参见 GPT-2 文档。

这意味着 CPM 采用 GPT-2 式的自回归解码器(causal LM)结构,使用方式上与 GPT-2 一脉相承。值得注意的是,当前仓库中 CPM 模块只实现了分词器,并未实现独立的CpmModel模型类——这一点可以从测试文件 test_tokenization_cpm.py 中的注释 "There is noCpmModel" 得到印证。因此在实际使用时,分词由CpmTokenizer/CpmTokenizerFast负责,而模型权重加载与生成推理则遵循 GPT-2 的用法(将 CPM 视为 GPT-2 架构的中文版本)。

仓库中 CPM 模块的文件结构如下:

  • src/transformers/models/cpm/tokenization_cpm.py:慢速分词器CpmTokenizer
  • src/transformers/models/cpm/tokenization_cpm_fast.py:快速分词器CpmTokenizerFast
  • src/transformers/models/cpm/init.py:模块惰性加载入口(_LazyModule

CpmTokenizer:慢速分词器源码解析

CpmTokenizer继承自PreTrainedTokenizer(tokenization_cpm.py),其核心设计是基于Jieba-RS(结巴分词的 Rust 实现,Python 包rjiebaSentencePiece的两段式分词:先由 Jieba-RS 完成中文词语切分,再由 SentencePiece 的 BPE/Unigram 子词模型切出子词。类注释中明确写道:"Runs pre-tokenization with Jieba-RS segmentation tool. It is used in CPM models."

依赖与词表文件

  • 词表文件:VOCAB_FILES_NAMES = {"vocab_file": "spiece.model"},即一个 SentencePiece 模型文件(.spm)。
  • 硬依赖:rjieba。两个分词器在初始化时都会尝试import rjieba,若未安装则抛出带提示的ModuleNotFoundError:"You need to install rjieba to use CpmTokenizer or CpmTokenizerFast."(见 tokenization_cpm.py)。安装方式为pip install rjieba sentencepiece

构造参数一览

CpmTokenizer的构造参数(tokenization_cpm.py)如下:

参数默认值说明
vocab_file必填SentencePiece 词表文件(.spm),用于实例化词表
do_lower_caseFalse分词前是否将输入转为小写
remove_spaceTrue分词前是否去除首尾空格并合并多余空白
keep_accentsFalse是否保留重音符号(为False时按 NFKD 规范化去除组合字符)
bos_token"<s>"预训练时使用的序列起始 token;注意构建带特殊 token 的序列时,序列开头实际用的是cls_token
eos_token"</s>"序列结束 token;构建序列时序列末尾实际是sep_token
unk_token"<unk>"词表外 token
sep_token"<sep>"分隔 token,用于拼接多个序列
pad_token"<pad>"填充 token,用于 batch 内长度对齐
cls_token"<cls>"分类 token,位于序列首位
mask_token"<mask>"掩码 token;构造时会被包装为AddedToken(mask_token, lstrip=True, rstrip=False),即像普通词一样保留其前的空格
additional_special_tokens["<eop>", "<eod>"]额外特殊 token(从命名看应分别表示段落结束与文档结束,代码中未展开解释)
sp_model_kwargsNone透传给sentencepiece.SentencePieceProcessor的额外关键字参数

注意:源码 docstring 中do_lower_case标注的默认值是True,但函数签名与super().__init__传递的实际默认值是False,实际行为以代码签名为准。

另外,该分词器将_pad_token_type_id设置为3(tokenization_cpm.py),这是 padding 位置的 token type id,与下面将提到的 segment id(0/1/2)区分开。

文本预处理流水线:preprocess_text

每次分词前,文本会依次经过preprocess_text(tokenization_cpm.py)处理:

  1. remove_space=True,先strip()再按空白切分后重新拼接,压缩多余空格;
  2. ``替换为"''替换为"(中文语境中的引号统一);
  3. keep_accents=False,按 Unicode NFKD 规范化并删除组合字符(combining marks);
  4. do_lower_case=True,转为小写。

分词主流程:_tokenize 与数字逗号回切

_tokenize(tokenization_cpm.py)的实现为:

  1. 调用preprocess_text得到规范化文本;
  2. 通过self.sp_model.encode(text, out_type=str)得到 SentencePiece 子词序列;
  3. 数字千分位逗号回切:对每个子词,若len(piece) > 1且以逗号结尾、且逗号前一位是数字(例如1,000被切成一个子词时),则把逗号之前的部分(去掉句首空格标记)用EncodeAsPieces重新切分,再在末尾补回逗号。这样保证数字串与逗号能按语义正确拆分。

分词结果中,SPIECE_UNDERLINE)是 SentencePiece 的空格标记。反向拼接时,convert_tokens_to_string会把还原为空格并strip()(tokenization_cpm.py)。

特殊 token 序列格式与 token type ids

build_inputs_with_special_tokens(tokenization_cpm.py)定义了输入序列的组装格式:

  • 单序列:X <sep> <cls>
  • 双序列(如文本分类、问答):A <sep> B <sep> <cls>

对应的get_special_tokens_maskcreate_token_type_ids_from_sequences生成的 segment id 为:第一段为0,第二段为1,末尾<cls>段为2;padding 位置则为_pad_token_type_id = 3

解码:还原空格与换行

CpmTokenizer定义了一个字符映射表self.translator = str.maketrans(" \n", "\u2582\u2583"),即空格 →(U+2582)、换行 →(U+2583)。在_decode中(tokenization_cpm.py)会先调用父类解码,再删除普通空格、把还原为空格、还原为换行。这种"先占位再还原"的机制确保了中英文混合文本中空格信息在 token 化过程中不丢失。

词表保存

save_vocabulary(tokenization_cpm.py)支持将当前词表以spiece.model保存到指定目录(若原词表文件不存在,则通过serialized_model_proto()序列化写出)。

CpmTokenizerFast:基于 Tokenizer 的快速分词器

CpmTokenizerFast继承自PreTrainedTokenizerFast(tokenization_cpm_fast.py),同样基于 Jieba-RS 与 SentencePiece,核心差异在于:

  • 词表文件:除spiece.model外还支持tokenizer.jsonVOCAB_FILES_NAMES = {"vocab_file": "spiece.model", "tokenizer_file": "tokenizer.json"}),可直接从预构建的 Tokenizer 文件恢复,速度更快。
  • 批量编码前置处理_batch_encode_plus(tokenization_cpm_fast.py)会对每个输入先执行self.jieba.cut(text, False)完成 Jieba-RS 中文分词,再用translator将结果中的空格与换行替换为/占位符,拼接为带空格分隔的字符串后交给底层 Tokenizer 编码。这正是慢速分词器"空格/换行占位"思路在快速路径中的落地。
  • 特殊 token 与 segment idbuild_inputs_with_special_tokenscreate_token_type_ids_from_sequences与慢速版完全一致,_pad_token_type_id同样为3
  • 解码_decode与慢速版相同,删除普通空格、还原→空格、→换行。
  • 保存限制save_vocabulary要求can_save_slow_tokenizer为真,否则抛错提示无法回存慢速分词器所需信息。

实践:安装、加载与分词验证

环境准备

使用 CPM 分词器前需要安装两个依赖:

pip install rjieba sentencepiece

rjieba(Jieba-RS)是必需项,缺失时会直接报错并给出安装提示;sentencepiece用于加载spiece.model

加载与分词示例

from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("TsinghuaAI/CPM-Generate") text = "Hugging Face大法好,谁用谁知道。" tokens = tokenizer.tokenize(text) print(tokens) # ['▁Hu', 'gg', 'ing', '▁', '▂', '▁F', 'ace', '▁大法', '▁好', '▁', ',', '▁谁', '▁用', '▁谁', '▁知', '道', '▁', '。'] ids = tokenizer.encode(text) print(tokenizer.decode(ids))

上述示例中的期望输出直接取自仓库测试 test_tokenization_cpm.py,可观察到:

  • 中文词("大法""好""谁""用""知道")被 Jieba-RS 正确切分,再由 SentencePiece 拆出子词;
  • "Hugging" 与 "Face" 之间的空格在 token 序列中体现为独立的token,解码后还原为空格,实现了中英混排文本的信息无损往返;
  • 全角逗号","被归一化为半角,(对应preprocess_text与测试中的normalized_text)。

测试还验证了 token → id 的转换(例如▁Hu → 13789)以及decode能还原出"Hugging Face大法好,谁用谁知道。<unk>"的规范化文本。

AutoTokenizer 自动映射

在自动加载体系 tokenization_auto.py 中,"cpm"架构被映射到CpmTokenizer(在 tokenizers 可用时),因此上述AutoTokenizer.from_pretrained写法对 CPM 系列 checkpoint 是开箱即用的。

小结

CPM 是本仓库中一个"模型架构复用 GPT-2、分词完全定制"的典型案例:它以 26 亿参数和 100GB 中文语料进行生成式预训练,而仓库内为其提供的核心资产是CpmTokenizerCpmTokenizerFast两套基于 Jieba-RS + SentencePiece 的中文分词器。理解preprocess_text的规范化流程、_tokenize的数字逗号回切逻辑、▂/▃空格换行占位机制,以及单序列X <sep> <cls>、双序列A <sep> B <sep> <cls>的特殊 token 格式,是正确使用和微调 CPM 系列模型的关键。相关实现与验证均可直接在 tokenization_cpm.py、tokenization_cpm_fast.py 与 test_tokenization_cpm.py 中查阅。

【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 19:25:12

TensorFlow分布式FFT实现与性能优化指南

1. 项目概述&#xff1a;分布式FFT在TensorFlow中的实现价值在大规模信号处理领域&#xff0c;快速傅里叶变换&#xff08;FFT&#xff09;作为基础算法面临着数据量激增带来的计算瓶颈。传统单机FFT实现&#xff08;如NumPy的fft模块&#xff09;处理GB级数据时往往需要分钟级…

作者头像 李华
网站建设 2026/9/11 19:18:16

别忽视苹果的音频智能功能,它揭示了未来发展方向

约翰特纳斯作为苹果CEO首次主题演讲的前五分钟&#xff0c;既不是产品发布&#xff0c;也不是回顾苹果的历史。相反&#xff0c;这是对iPhone作为"智能个人中枢"的重新定义。苹果制造的所有设备中&#xff0c;iPhone不需要向任何人做过多解释或介绍。但这种将其重新定…

作者头像 李华
网站建设 2026/9/11 19:15:10

AI线稿生成技术:从原理到Stable Diffusion实践

1. 手绘线稿生成的核心逻辑与价值在数字绘画和概念设计领域&#xff0c;线稿生成是创作过程中最关键的起手式。不同于直接上色或渲染&#xff0c;分阶段生成的线稿&#xff08;如线稿一、线稿二、线稿三&#xff09;实际上模拟了传统手绘"从粗到细"的创作流程。这种分…

作者头像 李华
网站建设 2026/9/11 19:09:54

51单片机双机通信实战:UART串口通信与Proteus仿真工程详解

简介&#xff1a;基于51单片机的双机通信项目&#xff0c;演示甲机按键控制两机LED按全灭、LED1亮、LED2亮、全亮顺序循环点亮&#xff0c;乙机按键则向甲机依次发送0-9数字并由甲机数码管实时显示&#xff0c;覆盖了串口通信、按键扫描和数码管驱动等常见单片机应用场景。压缩…

作者头像 李华