本示例致力于打造基于PaddleNLP预训练模型的最佳实践。
我们将预训练数据过程划分为以下部分
- 原始数据转换,原始文本转换为jsonl的json字符串格式。
- 数据ID化,断句、分词、tokenize转化为token id格式。
- 训练index文件生成,生成train、valid、test的每个样本索引。
- token动态mask(可选),python 层实时mask文本。
本目录下主要包含一下文件:
../data_tools
├── create_pretraining_data.py
├── dataset_utils.py
├── ernie_dataset.py
├── helpers.cpp
├── Makefile
├── README.md
└── trans_to_json.py
其中,trans_to_json.py是原始数据转化的脚本,将数据转化为json串格式。
create_pretraining_data.py将jsonl文本,断句、分词后,tokenizer转化为token id。
dataset_utils.py中包含了index生成、动态mask的实现。
ernie_dataset.py通过调用dataset_utils.py的一些函数,产生ernie的输入dataset。
- tqdm
- numpy
- pybind11
- lac (可选)
- zstandard (可选)
安装命令pip install tqdm numpy pybind11 lac zstandard。另,部分功能需要g++>=4.8编译支持
| 步骤 | 阶段 | 数据格式 | 样例 |
|---|---|---|---|
| - | - | 原始数据: 每个doc之间用空行间隔开 - 中文,默认每句换行符,作为句子结束。 - 英文,默认使用nltk判断句子结束 |
百度,是一家中国互联网公司。 百度为用户提供搜索服务。 PaddleNLP是自然语言处理领域的优秀工具。 |
原始数据转换trans_to_json.py |
预处理 | jsonl格式:每个doc对应一行json字符串 | {"text": "百度是一家中国互联网公司。百度为..."}{"text": "PaddleNLP是自然语言..."} |
数据ID化create_pretrain_data.py |
预处理 | npy格式:数据id化后的token id npz格式:数据句子、文章位置索引 |
- |
| 训练index文件生成 | 训练启动 | npy格式: 根据训练步数max_steps生成 train、valid、test的每个样本索引文件 |
- |
| token动态mask(可选) | Dataset取数据 | 无 | - |
下面以ERNIE预训练为例,简要介绍一下预训练的全流程。
首先下载样例数据:
mkdir data && cd data
wget https://paddlenlp.bj.bcebos.com/models/transformers/data_tools/baike.txt
cd ..
使用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 documment.
可选。过滤掉长度多短的文章,默认值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。
python trans_to_json.py --input_path ./data --output_path baike_sample
#查看数据
head -1 baike_sample.jsonl
{"text": "百度手机助手:最具人气的应用商店\n百度手机助手是Android手机的权威资源平台,分发市场份额连续十个季度排名市场第一,拥有最全最好的应用、游戏、壁纸资源,帮助用户在海量资源中精准搜索、高速下载、轻松管理,万千汇聚,一触即得。\n"}本部分,我们使用 create_pretraining_data.py 脚本将前面得到的 baike_sample.jsonl 进行tokenize id化处理。
optional arguments:
-h, --help show this help message and exit
--model_name MODEL_NAME
What model to use.
必须设置,如:ernie-1.0, 可以参考已有的模型名称 https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/model_zoo/transformers.rst
--tokenizer_name {ErnieTokenizer,BertTokenizer,GPTTokenizer,GPTChineseTokenizer}
What type of tokenizer to use.
模型对应的tokenizer, 目前暂时只支持 Ernie,Bert,GPT
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_ids.npy, XXX_idx.npz 两个文件。
npy文件,数据id化后的token ids; npz文件,数据句子、文章位置索引。
--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模型需要
chinese words:
--chinese Is corpus need words segmentation step for chinese words.
中文情形必须设置。处理的文本类型是否是中文。
--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.
默认lac,jieba速度较快
--cn_splited Is chinese corpus is splited in to words.
分词后的文本,可选。设置此选项则,cn_seg_func不起作用。
例如分词后文本串 "百度 手机助手 是 Android 手机 的 权威 资源平台"
--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结束。
--log_interval LOG_INTERVAL
Interval between progress updates
打印日志间隔,interval表示处理 文本行数/doc数的 间隔。
--workers WORKERS Number of worker processes to launch
处理文本id化的进程个数。
同过下面脚本转化,我们可以得到处理好的预训练数据,token ids:baike_sample_ids.npy, 文章索引信息baike_sample_idx.npz.
python -u create_pretraining_data.py \
--model_name ernie-1.0 \
--tokenizer_name ErnieTokenizer \
--input_path baike_sample.jsonl \
--split_sentences\
--chinese \
--cn_whole_word_segment \
--output_prefix baike_sample \
--workers 1 \
--log_interval 5
得到了处理好的训练数据,就可以开始Ernie模型的预训练了。ernie预训练的代码在examples/language_model/ernie-1.0。
简单将预处理好的数据,拷贝到data目录,即可开始Ernie模型预训练。
cd ../ernie-1.0
mkdir data
mv ../data_tools/baike_sample* ./data
sh run_static.sh
# 建议修改 run_static.sh 中的配置,将max_steps设置小一些。
代码说明:
- ernie预训练使用的 dataset 代码文件在
./data_tools/ernie_dataset.py - 数据集index生成,动态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使用这些lm_mask策略。
- 请先检查pybind11包是否安装,g++、make工具是否正常。
- 编译失败可能是本文件夹下的Makefile命令出现了一些问题。可以将Makefile中的python3、python3-config设置成完全的路径,如/usr/bin/python3.7。
注: 大部分数据流程,参考自Megatron,特此表达感谢。