☰
PaddleNLP 预训练数据全流程实战:从原始语料到 token id 的训练数据管线
2026/9/25 7:25:29 网站建设 项目流程
  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

PaddleNLP 的 llm/tools/preprocess 目录提供了一套完整的预训练数据处理工具链,覆盖从原始文本清洗、jsonl 转换、中文分词、token ID 化到训练 index 生成的四个核心阶段。本文以 ziya-llama-13b-v1 中文预训练为贯穿示例,逐环节讲解脚本参数、源码实现原理与实战命令,读完即可独立把 CLUECorpusSmall、OpenWebText2、WuDaoCorpus2.0 Base 等主流开源语料加工成可直接用于训练的.bin/.idx数据文件。

一、预训练数据流程总览

预训练数据管线被划分为四个阶段,每一步产出明确的中间产物,最终得到训练器直接消费的二进制数据集:

步骤阶段数据格式样例
0️⃣ 初始状态-原始数据:每个 doc 之间用空行间隔;中文默认每句换行作为句子结束,英文默认使用 nltk 判断句子结束飞桨是功能完备、开源开放的产业级深度学习平台。
飞桨拥有核心训练和推理框架、基础模型库。

PaddleNLP是自然语言处理领域的优秀工具。
1️⃣ 原始数据转换(trans_to_json.py)预处理jsonl 格式:每个 doc 对应一行 json 字符串{"text": "飞桨是功能完备、开源开放的产业级深度学习平台。飞桨拥有..."}
❇️(可选)数据中文分词(words_segmentation.py)语料分词:中文 WWM将 jsonl 恢复为分词后的原始格式数据飞桨 是 功能 完备、开源 开放的 产业级 深度学习 平台。
2️⃣ 数据 ID 化(create_pretraining_data.py)预处理.bin(token id)+.idx(句子、文章位置索引)-
3️⃣ 训练 index 文件生成训练启动.npy:根据 max_steps 生成 train/valid/test 的样本索引文件-
4️⃣ token 动态 mask(可选)Dataset 取数据无-

工具目录共包含 5 个文件:

├── create_pretraining_data.py ├── merge.py ├── trans_to_json.py ├── words_segmentation.py └── README.md

二、环境依赖

处理脚本依赖以下 Python 包:

  • tqdm:create_pretraining_data.py处理文件时展示进度条
  • numpy:用于 token id 的 dtype 判定与索引构建
  • pybind11:编译支撑 fast_dataindex 等扩展
  • fast_dataindex:数据索引相关能力
  • lac(可选):中文分词,提供lac/seg两种 LAC 模式
  • zstandard(可选):用于解压.zst格式的压缩语料(如 OpenWebText2)

一键安装命令:

pip install tqdm numpy pybind11 fast_dataindex lac zstandard

另外,部分功能需要g++ >= 4.8编译支持。若处理英文语料并开启--split_sentences,还需要 nltk 环境——源码中通过try: import nltk判断可用性,若缺失则直接报错退出(见 create_pretraining_data.py)。

三、步骤 1:原始数据转换(trans_to_json.py)

trans_to_json.py将原始纯文本转换为 jsonl 格式,每个 doc 对应一行 json 字符串。

3.1 参数说明

optional arguments: -h, --help 显示帮助 --input_path 必须设置。原始文件路径,可以是文件夹或单个文件; 文件夹中的目录默认最多搜索两层子目录。 --output_path 必须设置。输出 json 文件的名称。 --json_key json 的 content key,建议不修改,默认是 text --doc_spliter 文档分隔符。默认空行作为文章分隔符; 若使用空行分隔 doc,该项留空即可。 --min_doc_length 可选。过滤过短文章,默认值 10(字符数) --workers 可选。多进程转换文件数,适用于 input_path 中文件较多的情况, 每个文件分配给不同 worker 处理 --log_interval 可选。处理完文件个数的日志间隔,默认 1 --no-merge 可选。默认不开启;开启后每个文件转换的 jsonl 不拼接 到同一个文件,而是各自输出 --no-shuffle 可选。默认不开启;默认处理完会对所有 doc 进行 shuffle

3.2 源码实现要点

从源码看,核心转换逻辑在raw_text_to_json函数(trans_to_json.py):

  • 逐行读取原始文本,遇到line.strip() == doc_spliter(即空行)时,把累积的doc字符串判断长度后写入一行json.dumps({json_key: doc}, ensure_ascii=False);
  • ensure_ascii=False保证中文以原文形式(而非\u转义)写入,便于人眼检查;
  • 主流程使用multiprocessing.Pool并行处理文件(每个文件一个 worker),默认 1 个进程;
  • 合并(merge_file)直接用二进制流shutil.copyfileobj拼接,随后用系统shuf命令对整文件做 shuffle(shuffle_file)。

3.3 实战命令

以下载百度百科样例数据为例:

mkdir data && cd data wget https://bj.bcebos.com/paddlenlp/models/transformers/data_tools/baike.txt cd ..

执行转换(此处默认对所有 doc 进行 shuffle):

python trans_to_json.py --input_path ./data --output_path baike_sample

查看产出的 jsonl:

head -1 baike_sample.jsonl {"text": "中国效仿西方发展工业的过程,于中华民国国民政府成立后至中日战争开战前夕已顺畅发展,尽管其间受到内外因素的多重干扰。尔后直至中日战争和国共战争的结束,中国始有较为长期的和平发展时期。\n1980年代以来,邓小平政府宣布改革开放,开始实行社会主义市场经济并推行经济体制改革。……\n"}

四、步骤 ❇️(可选):中文语料预分词(words_segmentation.py)

words_segmentation.py是中文预训练做 WWM(Whole Word Masking)的可选步骤,作用是把 jsonl 格式的数据恢复成"分词 + 按句换行"的原始格式,供后续create_pretraining_data.py直接以--cn_splited=True消费。

4.1 使用原则

  • 数据量较少时,分词耗时短,不需要单独分词,直接在create_pretraining_data.py步骤中完成分词即可;
  • 单独分词的目的是提前分词、加快后续 ID 转化:当数据集很大或需要多次尝试转换时,可避免每次运行create_pretraining_data.py都重复执行分词程序;
  • 若此处输入的是 jsonl 文件,最好为多文件,并在trans_to_json.py阶段开启--no-merge选项;
  • 分词转换完成后,需要重新执行步骤 1️⃣(trans_to_json.py),最后在步骤 2️⃣ 中设置--cn_splited=True;
  • 反过来,步骤 2️⃣ 也可以在转化 ID 的同时一起完成分词,此时无需 ❇️ 预分词步骤。

4.2 参数与实现

--input_path 必须设置。输入路径,文件夹或单个文件 --output_path 输出目录,默认 ./tmp --data_format 输入数据格式,可选 jsonl 或 wudao(默认 jsonl) --cn_seg_func 中文分词函数,可选 lac / seg / jieba(默认 jieba) --workers 多进程个数,默认 1 --log_interval 处理文件的日志间隔,默认 1

三种分词函数在 words_segmentation.py 中均有实现:jieba直接调用jieba.cut;lac与seg都基于 LAC 库,分别使用LAC(mode="lac")(词法分析,返回词语与词性)和LAC(mode="seg")(纯分词)。

源码还包含一套简单的断句规则(text_to_text函数,words_segmentation.py):

  1. 用正则re.sub("[" + char + "]+[ ]*", char, text)把连续的特殊符号(\n、。、?、?、空格、;、;、!、!)压缩为单个,避免同一符号被当作多个句子分隔符;
  2. 再把断句符号(。、?、?、;、;、!、!)替换为"符号 + 换行",实现按句切分;
  3. 最后对每行调用分词函数,用空格连接词语,每句一行输出。

WuDao 数据则通过data_format=wudao分支读取,按js["content"]字段逐条产出。

五、步骤 2:数据 ID 化(create_pretraining_data.py)

这是整个管线最核心的脚本:读取 jsonl,断句、分词、tokenize,最终产出两个文件——XXX.bin(数据 ID 化后的 token ids)与XXX.idx(数据句子、文章位置索引)。

5.1 参数说明

--model_name_or_path 必须设置。使用的模型名或词表路径,如 idea-ccnl/ziya-llama-13b-v1; 使用自定义词表时,指定 model_name 为词表所在文件夹地址。 data input/output: --input_path 必须设置。输入 jsonl 文件或目录 --output_prefix 必须设置。输出文件名,假设为 XXX, 则输出 XXX.bin(token ids)与 XXX.idx(句子/文章位置索引) --data_format {JSON} 不需要设置。目前默认处理 jsonl 数据格式(choices 仅 JSON) --json_key json 文本的 key 值,与 trans_to_json.py 一致,默认 text --split_sentences 是否将文章划分成句子。一般 GPT 不需要,BERT/ERNIE 模型需要 --data_impl {mmap,lazy} 处理后的数据格式,可选 mmap 或 lazy; mmap 读入时建立内存映射,lazy 读入时直接从文件读取 chinese words: --chinese 处理中文且设置了 split_sentences 时需要设置 --cn_whole_word_segment 是否需要 WWM 策略。一般 BERT/ERNIE 需要,GPT 不需要 --cn_seg_func {lac,seg,jieba} 中文分词函数,默认 jieba(速度快);lac 模型更准确但计算量高 --cn_splited 语料是否已分词。设置后 cn_seg_func 不起作用; 例如分词后的文本串 "中国 效仿 西方 发展 工业 的过 程" --cn_split_dimer 配合 cn_splited 使用,默认空格表示分词间隔 common config: --append_eos doc 末尾追加 <eos> token。gpt 类模型专用,表示 doc 结束; 若 tokenizer 不含 eos_token,输出 warning 且不追加 --log_interval 打印日志间隔,表示处理文本行数/doc 数的间隔 --workers 文本 id 化的进程个数 --max_repeated_len 最大保留的重复字符个数(默认 100) --max_doc_num 处理到该 doc 数时停止(源码中默认 sys.maxsize)

5.2 源码实现要点

ID 化逻辑集中在Converter类(create_pretraining_data.py):

  • Tokenizer 初始化:每个 worker 进程通过AutoTokenizer.from_pretrained(model_name_or_path)加载分词器;开启 WWM 时还会调用extend_chinese_char()扩充中文单字词表;
  • 句子切分:中文用NewlineSplitter(按\n切分),英文用 nltk 的punkt模型;未开--split_sentences时用IdentitySplitter原样返回;
  • WWM 分词:get_whole_word_mask_tokens函数(create_pretraining_data.py)把 WordPiece 切出的中文单字与 jieba/LAC 分词结果对齐,对处于中文词语中间的字符加上##前缀(如["通过","利用"]→["通","##过","利","##用"]),确保 WWM 时整词一起被 mask。非中文字符直接沿用 WordPiece 结果;max_word_length默认 6,避免过长中文词被整词 mask;
  • 重复字符过滤:remove_repeated_chars用正则(.)\1{N,}把连续出现 N 次(默认 100)以上的重复字符压缩为单个;
  • dtype 自适应:vocab_size < 2^16 - 1时用np.uint16存储,否则用np.int32(create_pretraining_data.py),小词表模型可节省一半存储;
  • 并行流水线:multiprocessing.Pool(workers, initializer=convert.initializer)配合pool.imap(convert.encode, text, 256)实现按行分发的并行编码;
  • 数据写入:通过paddlenlp.data.indexed_dataset.make_builder构建 mmap/lazy 数据集,add_item写入句子、end_document结束文档,最后finalize生成 idx 索引;
  • .zst 支持:输入文件以.zst结尾时自动调用zstandard.ZstdDecompressor流式解压,可直接处理 OpenWebText2 一类压缩语料。

5.3 实战命令

针对 llama 模型(GPT 类,不切句、不加 WWM,追加 eos):

python -u create_pretraining_data.py \ --model_name_or_path "idea-ccnl/ziya-llama-13b-v1" \ --input_path "baike_sample.jsonl" \ --output_prefix "baike_sample" \ --data_format "JSON" \ --json_key "text" \ --data_impl "mmap" \ --append_eos \ --log_interval 5 \ --workers 40

针对 ernie 模型(BERT 类,切句、中文、WWM):

python -u create_pretraining_data.py \ --model_name_or_path "ernie-3.0-base-zh" \ --input_path "baike_sample.jsonl" \ --output_prefix "baike_sample" \ --data_format "JSON" \ --json_key "text" \ --split_sentences \ --data_impl "mmap" \ --chinese \ --cn_whole_word_segment \ --cn_seg_func "jieba" \ --log_interval 5 \ --workers 40

两个实用技巧:

  1. 使用已分好词的语料时,设置--cn_splited,同时指定--cn_split_dimer(如空格)。此时源码中segment_func退化为lambda text: text.split(cn_split_dimer),且会处理连续空词对应的分隔符位置;
  2. 使用自定义词表时,--model_name_or_path直接指定词表所在文件夹地址即可。

六、大语料并行加工与 merge.py 合并

若预处理文件过大、单次转换耗时过长,可把 jsonl 拆分为多个小文件,并行运行多个create_pretraining_data.py,各自产出多组.bin/.idx,再用merge.py合并为一份完整数据。

6.1 参数说明

--input 必须设置。待合并文件所在文件夹; 文件夹内各小文件需按 merge 的顺序排列, 如 1.bin / 1.idx,2.bin / 2.idx ... --output_prefix 必须设置。合并后输出文件名,假设为 XXX, 则输出 XXX.bin 与 XXX.idx --data_impl {mmap,lazy} 合并前后数据格式必须一致,可选 mmap 或 lazy

6.2 实现与命令

从 merge.py 源码可见合并流程:

  1. 扫描输入目录,以.bin/.idx扩展名配对确认每个 prefix 的两个文件齐全,去重后按文件名排序依次合并(保证顺序与生成时一致);
  2. 首个文件决定目标格式:MMapIndexedDataset走MMapIndexedDatasetBuilder(沿用首文件的_index.dtype),lazy 走IndexedDatasetBuilder;
  3. 逐个builder.merge_file_(prefix)追加数据,最后finalize写出 idx。

实际合并命令:

python merge.py \ --input /root/data \ --output-prefix /root/data/merged \ --data_impl mmap

七、步骤 3 与步骤 4:训练 index 生成与 token 动态 mask

  • 训练 index 文件生成:发生在训练启动阶段,根据训练步数max_steps生成.npy格式的 train / valid / test 每个样本的索引文件,训练器据此顺序消费样本。
  • token 动态 mask(可选):在 Dataset 取数据阶段由 Python 层实时对文本做 mask。相关实现位于 slm/model_zoo/ernie-1.0/data_tools/dataset_utils.py,核心入口为create_masked_lm_predictions函数(dataset_utils.py),其关键参数包括:
参数含义
do_whole_word_mask是否执行 WWM(把同一原始词的所有 wordpiece 一起 mask)
favor_longer_ngram是否偏好更长 n-gram 的 mask 片段(默认pvals = 1/n更偏好短 n-gram,置 True 后反转)
do_permutation是否启用排列(permutation)式 mask 策略
geometric_dist是否用几何分布采样 n-gram 长度(默认均匀分布)
masking_stylemask 风格,默认"bert"
to_chinese_char是否把##中形式的字符还原为原始中文字符

用户可根据需求在dataset_utils.py中灵活修改 mask 方式,这些策略(do_whole_word_mask、favor_longer_ngram、do_permutation、geometric_dist 等)与 Megatron-LM 的 lm_mask 策略一脉相承。

八、开源数据集制作教程汇总

针对常见开源语料,llm/tools/preprocess/docs目录提供了四个制作教程:

名称文本类型纯文本大小适配模型
CLUECorpusSmall中文14GBLlama
OpenWebText2英文70GBLlama
WuDaoCorpus2.0 Base中文200GBLlama
CLUECorpus2020中文200GBLlama

8.1 CLUECorpusSmall(中文 14GB)

数据量超过 14G,近 4000 个 txt 文件、50 亿字,包含新闻、社区互动、维基百科、评论四类子语料。解压后先执行转换:

python trans_to_json.py --input_path ./clue_corpus_small_14g --output_path clue_corpus_small_14g.jsonl

Llama 数据制作(--append_eos、--data_impl mmap、--workers 48,分词较耗时约一小时完成,产出clue_corpus_small_14g.bin/.idx,全文约 1570 万文档):

python -u create_pretraining_data.py \ --model_name "idea-ccnl/ziya-llama-13b-v1" \ --input_path "clue_corpus_small_14g.jsonl" \ --output_prefix "clue_corpus_small_14g" \ --data_format "JSON" \ --json_key "text" \ --data_impl "mmap" \ --append_eos \ --log_interval 10000 \ --workers 48

Ernie 数据制作(切句 + 中文 + WWM,分词函数可换lac获取更高准确率):

python -u create_pretraining_data.py \ --model_name "ernie-3.0-base-zh" \ --input_path "clue_corpus_small_14g.jsonl" \ --output_prefix "clue_corpus_small_14g" \ --data_format "JSON" \ --json_key "text" \ --split_sentences \ --data_impl "mmap" \ --chinese \ --cn_whole_word_segment \ --cn_seg_func "lac" \ --log_interval 10000 \ --workers 48

8.2 OpenWebText2(英文 70GB)

源自 Reddit 的英文网页文本,经去重清洗后含 800 多万个文档。下载解压后直接用create_pretraining_data.py制作(Llama 类无需分词与切句):

python -u create_pretraining_data.py \ --model_name meta-llama/Llama-2-7b \ --tokenizer_name LlamaTokenizer \ --data_format JSON \ --input_path /path/to/openwebtext/ \ --append_eos \ --output_prefix llama_openwebtext \ --workers 40 \ --log_interval 10000 \ --data_impl "mmap"

处理约一小时产出llama_openwebtext.bin/.idx,统一放入 data 目录供训练使用。

8.3 WuDaoCorpus2.0 Base(中文 200GB)

WuDaoCorpora 是悟道爬取的中文大规模语料,开源部分约 200GB。由于数据量极大,教程演示了"预分词 → 重转 jsonl → ID 化"的完整链路:

  1. 下载解压(压缩包约 64GB)后先做语料分词与断句:
python words_segmentation.py \ --input_path ./WuDaoCorpus2.0_base_200G \ --workers 40 \ --data_format wudao \ --cn_seg_func seg \ --output_path ./wudao_lac_cut

注意:预训练若需要实现 SOP(Sentence Order Prediction)任务,分词时会用简单规则进行文本断句;如果语料只有一句话,建议去除 SOP loss,训练时设置binary_head=False。

  1. 重新转换为 jsonl(此时语料已分词):
python ./trans_to_json.py \ --input_path ./wudao_lac_cut \ --output_path wudao_corpus_200g.jsonl \ --workers 40
  1. 对 llama(未分词路径,直接处理原始 json)或 ernie 进行 ID 化。Ernie 路径由于已提前分词,需加上--cn_splited:
python -u create_pretraining_data.py \ --model_name "ernie-3.0-base-zh" \ --input_path "wudao_corpus_200g.jsonl" \ --output_prefix "wudao_corpus_200g" \ --data_format "JSON" \ --json_key "text" \ --split_sentences \ --data_impl "mmap" \ --chinese \ --cn_whole_word_segment \ --cn_seg_func "jieba" \ --cn_splited \ --log_interval 10000 \ --workers 48

8.4 CLUECorpus2020(中文 200GB)

由 Common Crawl 中文部分清洗而来,可通过邮件向 CLUEbenchmark 申请下载。获取后同样走trans_to_json.py+create_pretraining_data.py的标准流程(详见 CLUECorpus2020.md)。

九、预训练启动:数据接入与下一步

数据制作完成后,把.bin/.idx拷贝到训练目录即可启动预训练:

mkdir data mv ./preprocess/baike_sample* ./data
  • llama 类模型预训练可参考 llm 目录 下的相关配置与启动脚本;
  • ernie 类模型预训练可参考 slm/model_zoo/ernie-1.0 的预训练说明(该目录同时维护着动态 mask 的实现 dataset_utils.py)。

十、小结

PaddleNLP 的预训练数据管线在设计上有几个值得借鉴的特点:原始文本转换与 ID 化两个阶段充分解耦,配合可选的预分词环节,让大数据集可以"分步并行、一次分词、多次复用";mmap/lazy两种数据格式兼顾大文件的内存映射提速与简单文件直读;多进程 worker 贯穿转换、分词、ID 化全流程,并支持多份.bin/.idx的按序合并。整体流程参考自 Megatron-LM 的数据处理思路,用户在掌握上述步骤后,既可以沿用现成命令直接处理开源语料,也可以按同样的数据结构接入自有数据,快速构建大规模预训练数据集。

  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

相关推荐

上一篇:Keyviz v2.0 完全掌握指南:从新手到高手的实用教程
下一篇:如何快速掌握Fastboot刷机:Android用户的完整图形化解决方案

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询