Files
paddlepaddle--paddlenlp/llm/tools/preprocess/README.md
T
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

256 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PaddleNLP 预训练数据流程
本示例致力于打造基于 PaddleNLP 预训练模型的最佳实践。
我们将预训练数据过程划分为以下部分
- 原始数据转换,原始文本转换为 jsonl 的 json 字符串格式。
- 数据 ID 化,断句、分词、tokenize 转化为 token id 格式。
- 训练 index 文件生成,生成 train、valid、test 的每个样本索引。
- token 动态 mask(可选)python 层实时 mask 文本。
本目录下主要包含一下文件:
```
├── create_pretraining_data.py
├── merge.py
├── trans_to_json.py
├── words_segmentation.py
└── README.md
```
### 环境依赖
- tqdm
- numpy
- pybind11
- fast_dataindex
- lac (可选)
- zstandard (可选)
安装命令`pip install tqdm numpy pybind11 fast_dataindex lac zstandard`。另,部分功能需要`g++>=4.8`编译支持
## 训练全流程数据 Pipeline
飞桨是自主研发、功能完备、开源开放的产业级深度学习平台,集深度学习核心训练和推理框架、基础模型库、端到端开发套件和丰富的工具组件于一体
| 步骤 | 阶段                      | 数据格式 | 样例 |
|-----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 0️⃣初始状态 | - | 原始数据: <br/> **每个 doc 之间用空行间隔开** <br/> - 中文,默认每句换行符,作为句子结束。<br/> - 英文,默认使用 nltk 判断句子结束 | ```飞桨是功能完备、开源开放的产业级深度学习平台。``` <br/> ```飞桨拥有核心训练和推理框架、基础模型库。``` <br/><br/> ```PaddleNLP是自然语言处理领域的优秀工具。``` |
| 1️⃣原始数据转换<br/>`trans_to_json.py` | 预处理 <br>输入:0️⃣初始状态 <br>输出:jsonl | jsonl 格式:每个 doc 对应一行 json 字符串 | ```{"text": "飞桨是功能完备、开源开放的产业级深度学习平台。飞桨拥有..."}```<br/>```{"text": "PaddleNLP是自然语言..."}``` |
| ❇️(**可选**)数据中文分词<br/>`words_segmentation.py` | 语料分词:中文 WWM <br>输入:jsonl <br> 输出:0️⃣初始状态 | 将 jsonl 格式的数据,恢复成分词后的原始格式数据 <br> | ```飞桨 是 功能 完备、开源 开放的 产业级 深度学习 平台。``` <br/> ```飞桨 拥有 核心 训练和推理 框架、基础 模型库。``` <br/><br/> ```PaddleNLP 是 自然语言处理领域 的 优秀工具。``` |
| 2️⃣数据 ID 化<br/>`create_pretrain_data.py` | 预处理 | bin 格式:数据 id 化后的 token id <br/>idx 格式:数据句子、文章位置索引 | - |
| 3️⃣训练 index 文件生成 | 训练启动 | npy 格式:<br/> 根据训练步数 max_steps 生成<br/>train、valid、test 的每个样本索引文件 | - |
| 4️⃣token 动态 mask(可选) | Dataset 取数据 | 无 | - |
注意:
- **❇️(**可选**)数据中文分词** 是中文预训练做 WWM 的可选步骤
- 当你的数据比较少时,分词耗时较少,不需要分词步骤。直接在`create_pretrain_data.py`步骤中分词即可。
- 目的是为了提前分词,加快后续数据 ID 转化步骤。
- 如果这里输入的是 jsonl 格式文件,最好为多文件,`trans_to_json.py` 时候开启`no-merge`选项。
- 当你的数据集比较大,或者需要尝试多次转换数据的时候,提前分词可以避免`create_pretrain_data.py`时每次都运行一次分词程序。
- 转换后,需要重新进行步骤 1️⃣`原始数据转换 trans_to_json.py`,最后2️⃣`数据 ID 化`步骤设置`--cn_splited=True`参数。
- 2️⃣`数据 ID 化`也可以在转化 ID 的同时,一起实现分词。不需要❇️`数据中文分词`步骤。
## 数据教程汇总
针对目前开源的数据集,PaddleNLP 提供了详细的数据教程,点击对应数据集的链接,即可开始进行数据制作:
| 名称 | 文本类型 | 纯文本大小 | 适配模型 |
|--------------------------------------------------|----------|------------|----------|
| [CLUECorpusSmall](./docs/CLUECorpusSmall.md) | 中文 | 14GB | Llama |
| [OpenWebText2](./docs/OpenWebText2.md) | 英文 | 70GB | Llama |
| [WuDaoCorpus2.0 Base](./docs/WuDaoCorpusBase.md) | 中文 | 200GB | Llama |
| [CLUECorpus2020](./docs/CLUECorpus2020.md) | 中文 | 200GB | Llama |
## 预训练详细准备
下面以 ziya-llama-13b-v1预训练为例,简要介绍一下预训练的全流程。
### 原始数据
首先下载样例数据:
```
mkdir data && cd data
wget https://bj.bcebos.com/paddlenlp/models/transformers/data_tools/baike.txt
cd ..
```
### 原始数据转换 jsonl 格式
使用`trans_to_json.py`转化为 json 串格式,下面是脚本的使用说明
```
optional arguments:
-h, --help show this help message and exit
--input_path INPUT_PATH
Path to you raw files. Folder or file path.
必须设置,可以是文件夹或者单个文件。文件夹中的目录默认最多搜索两层子目录。
--output_path OUTPUT_PATH
Path to save the output json files.
必须设置,输出文件的名字。
--json_key JSON_KEY The content key of json file.
建议不修改,默认的key是text
--doc_spliter DOC_SPLITER
Spliter between documents. We will strip the line, if you use blank line to split doc, leave it blank.
根据实际情况修改,默认空行作为文章换行符。
--min_doc_length MIN_DOC_LENGTH
Minimal char of a document.
可选。过滤掉长度多短的文章,默认值10
--workers WORKERS Number of worker processes to launch
可选。多进程转化文件,适用于 input_path 中包含的文件数据较多的情况。每个文件,分配给不同worker处理
--log_interval LOG_INTERVAL
Interval between progress updates.
可选。此处的interval是值处理完文件个数的间隔。
--no-merge Don't merge the file.
可选。默认不开启这个选项,默认每个文件转换的jsonl文本,会拼接成到同一个文件。
--no-shuffle Don't shuffle the file.
可选。默认不开启这个选项,默认对处理完进行shuffle。
```
根据说明,我们使用下面简单命令,可以得到`baike_sample.jsonl`文件。此处,我们对文章所有 doc 进行了 shuffle。
```shell
python trans_to_json.py --input_path ./data --output_path baike_sample
```
```shell
#查看数据
head -1 baike_sample.jsonl
{"text": "中国效仿西方发展工业的过程,于中华民国国民政府成立后至中日战争开战前夕已顺畅发展,尽管其间受到内外因素的多重干扰。尔后直至中日战争和国共战争的结束,
中国始有较为长期的和平发展时期。\n1980年代以来,邓小平政府宣布改革开放,开始实行社会主义市场经济并推行经济体制改革。中国大陆近年至2010年,GDP超过72000亿美元,
已经成为美国之后的世界第二经济大国,普遍认为中国是世界上发展速度最快的经济体,但是人均国民生产总值仍位于世界中等水平(第89位),并逐渐受到资源限制和贫富差距加
大的制约。中华人民共和国省份中,广东为GDP最高的第一强省,浙江为人均收入最高的第一富省。中国大陆、香港、澳门、台湾之间的经济联系在全球化的过程中日益紧密。\n"}
```
### 数据 ID 化
本部分,我们使用 `create_pretraining_data.py` 脚本将前面得到的 `baike_sample.jsonl` 进行 tokenize id 化处理。
```
optional arguments:
-h, --help show this help message and exit
--model_name_or_path MODEL_NAME_OR_PATH
What model to use.
必须设置,如:idea-ccnl/ziya-llama-13b-v1, 可以参考已有的模型名称 https://github.com/PaddlePaddle/PaddleNLP/blob/develop/llm
data input/output:
--input_path INPUT_PATH
Path to input JSON files.
必须设置,输入文件jsonl的目录
--output_prefix OUTPUT_PREFIX
Output prefix to store output file.
必须设置,输出文件的名称。
假设名称为XXX,则会输出 XXX.bin, XXX.idx 两个文件。
bin文件,数据id化后的token ids; idx文件,数据句子、文章位置索引。
--data_format {JSON} Only support json format for now. One document per line.
不需要设置。目前默认处理jsonl数据格式
--json_key JSON_KEY For JSON format. Space separate listed of keys to extract from json
文本串json的key值。同前面trans_to_json.py的json_key,默认text为key
--split_sentences Split documents into sentences.
是否需要将文章划分成句子。一般而言,GPT不需要,BERT/ERNIE模型需要
--data_impl {mmap,lazy}
Convert the json into mmap/lazy format.
处理后的数据格式,可选“mmap”或“lazy”,其中“mmap”格式在读入数据时会建立内存映射,“lazy”格式在读入数据时直接从文件读取。
chinese words:
--chinese Is corpus need words segmentation step for chinese words.
若设置了split_sentences,并处理中文则需要设置。
--cn_whole_word_segment
Is corpus need words segmentation step for chinese words WWM.
可选。是否需要WWM策略。一般而言,BERT/ERNIE模型需要,GPT不需要。
--cn_seg_func {lac,seg,jieba}
Words segment function for chinese words.
默认jieba,jieba速度较快,lac模型更准确,计算量高。
--cn_splited Is chinese corpus is split into words.
分词后的文本,可选。设置此选项则,cn_seg_func不起作用。
例如分词后文本串 "中国 效仿 西方 发展 工业 的过 程"
--cn_split_dimer CN_SPLIT_DIMER
Split dimer between chinese words.
配合cn_splited使用,默认空格表示分词间隔。
common config:
--append_eos Append an <eos> token to the end of a document.
gpt类模型专用,gpt设置此选项,表示doc结束。针对tokenizer中不包含eos_token情况,输出提示warning并且不添加<eos>。
--log_interval LOG_INTERVAL
Interval between progress updates
打印日志间隔,interval表示处理 文本行数/doc数的 间隔。
--workers WORKERS Number of worker processes to launch
处理文本id化的进程个数。
--max_repeated_len Max length of repeated chars to keep
最大保留重复的字符个数。
```
通过下面脚本转化,我们可以得到处理好的预训练数据,token ids:`baike_sample.bin`, 文章索引信息`baike_sample.idx`.
* 针对 llama 模型
```shell
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 模型
```shell
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 为 True,同时指定--cn_split_dimer 如空格。
2. 使用自定义词表的话,请指定 model_name 为词表所在的文件夹地址。
若需要预处理的文件过大,该脚本所耗费的时间可能会很长。此时可以考虑将 jsonl 文件拆分为多个小文件,并行使用 create_pretraining_data.py 进行处理,得到多个.bin & .idx 文件。
之后使用如下 merge 脚本合并多个小的.bin & .idx 文件。
```
python merge.py \
--input /root/data \
--output-prefix /root/data/merged \
--data_impl mmap
```
使用说明:
```
arguments:
--input INPUT_PATH
Path to the folder where the files to be merged.
待合并的文件所在文件夹,文件夹内各个小文件需按merge的顺序排列,如1.bin / 1.idx2.bin / 2.idx...
--output_prefix OUTPUT_PREFIX
Output prefix to store output file.
合并后输出文件的名称,假设名称为XXX,则会输出 XXX.bin, XXX.idx 两个文件。
--data_impl {mmap,lazy}
Convert the json into mmap/lazy format.
merge前后的数据格式,可选“mmap”或“lazy,各个待merge的文件需格式一致。”。
```
### 预训练开始
得到了处理好的训练数据,就可以开始模型的预训练了。简单将预处理好的数据,拷贝到 data 目录,即可开始预训练。
```shell
mkdir data
mv ./preprocess/baike_sample* ./data
```
* llama 预训练请参考[预训练](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/llm)。
* ernie 预训练请参考[预训练](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/slm/model_zoo/ernie-1.0/pretraining_introduction.md)。
代码说明:
- 动态 mask 相关代码实现在`./data_tools/dataset_utils.py`
用户可以根据自己的需求,灵活修改 mask 方式。具体可以参考`dataset_utils.py`中`create_masked_lm_predictions`函数。
可以自定义的选项有 do_whole_word_mask, favor_longer_ngram, do_permutation, geometric_dist 等,
可以参考[Megatron](https://github.com/NVIDIA/Megatron-LM)使用这些 lm_mask 策略。
## 参考内容
注: 大部分数据流程,参考自[Megatron](https://github.com/NVIDIA/Megatron-LM),特此表达感谢。