BERT (Bidirectional Encoder Representations from Transformers)以Transformer 编码器为网络基本组件,使用掩码语言模型(Masked Language Model)和邻接句子预测(Next Sentence Prediction)两个任务在大规模无标注文本语料上进行预训练(pre-train),得到融合了双向内容的通用语义表示模型。以预训练产生的通用语义表示模型为基础,结合任务适配的简单输出层,微调(fine-tune)后即可应用到下游的NLP任务,效果通常也较直接在下游的任务上训练的模型更优。此前BERT即在GLUE评测任务上取得了SOTA的结果。
本项目是BERT在 Paddle 2.0上的开源实现,包含了预训练和GLUE评测任务上的微调代码。
本教程除了需要安装PaddleNLP库,还需以下依赖
h5py
create_pretraining_data.py
是创建预训练程序所需数据的脚本。其以文本文件(使用换行符换行和空白符分隔,data目录下提供了部分示例数据)为输入,经由BERT tokenizer进行tokenize后再做生成sentence pair正负样本、掩码token等处理,最后输出hdf5格式的数据文件。使用方式如下:
python create_pretraining_data.py \
--input_file=data/sample_text.txt \
--output_file=data/training_data.hdf5 \
--bert_model=bert-base-uncased \
--max_seq_length=128 \
--max_predictions_per_seq=20 \
--masked_lm_prob=0.15 \
--random_seed=12345 \
--dupe_factor=5
其中参数释义如下:
input_file
指定输入文件,可以使用目录,指定目录时将包括目录中的所有.txt
文件。output_file
指定输出文件。bert_model
指定使用特定BERT模型对应的tokenizer进行tokenize处理。max_seq_length
指定最大句子长度,超过该长度将被截断,不足该长度的将会进行padding。max_predictions_per_seq
表示每个句子中会被mask的token的最大数目。masked_lm_prob
表示每个token被mask的概率。random_seed
指定随机种子。dupe_factor
指定输入数据被重复处理的次数,每次处理将重新产生随机mask。
使用以上预训练数据生成程序可以用于处理领域垂类数据后进行二次预训练。若需要使用BERT论文中预训练使用的英文Wiki和BookCorpus数据,可以参考这里进行处理,得到的数据可以直接接入本项目中的预训练程序使用。
GLUE评测任务所含数据集已在paddlenlp中以API形式提供,无需预先准备,使用run_glue.py
执行微调时将会自动下载。
GPU训练
unset CUDA_VISIBLE_DEVICES
python -m paddle.distributed.launch --gpus "0" run_pretrain.py \
--model_type bert \
--model_name_or_path bert-base-uncased \
--max_predictions_per_seq 20 \
--batch_size 32 \
--learning_rate 1e-4 \
--weight_decay 1e-2 \
--adam_epsilon 1e-6 \
--warmup_steps 10000 \
--num_train_epochs 3 \
--input_dir data/ \
--output_dir pretrained_models/ \
--logging_steps 1 \
--save_steps 20000 \
--max_steps 1000000 \
--device gpu \
--use_amp False
其中参数释义如下:
model_type
指示了模型类型,使用BERT模型时设置为bert即可。model_name_or_path
指示了某种特定配置的模型,对应有其预训练模型和预训练时使用的 tokenizer。若模型相关内容保存在本地,这里也可以提供相应目录地址。max_predictions_per_seq
表示每个句子中会被mask的token的最大数目,与创建预训练数据时的设置一致。batch_size
表示每次迭代每张卡上的样本数目。learning_rate
表示基础学习率大小,将于learning rate scheduler产生的值相乘作为当前学习率。weight_decay
表示AdamW优化器中使用的weight_decay的系数。adam_epsilon
表示AdamW优化器中使用的epsilon值。warmup_steps
表示动态学习率热启的step数。num_train_epochs
表示训练轮数。input_dir
表示输入数据的目录,该目录下所有文件名中包含training的文件将被作为训练数据。output_dir
表示模型的保存目录。logging_steps
表示日志打印间隔。save_steps
表示模型保存及评估间隔。max_steps
表示最大训练步数,达到max_steps
后就提前结束。注意,我们必须设置max_steps
。device
表示训练使用的设备, 'gpu'表示使用GPU, 'xpu'表示使用百度昆仑卡, 'cpu'表示使用CPU。use_amp
指示是否启用自动混合精度训练。
unset CUDA_VISIBLE_DEVICES
python -m paddle.distributed.launch --gpus "0" run_pretrain_trainer.py \
--model_type bert \
--model_name_or_path bert-base-uncased \
--max_predictions_per_seq 20 \
--per_device_train_batch_size 32 \
--learning_rate 1e-4 \
--weight_decay 1e-2 \
--adam_epsilon 1e-6 \
--warmup_steps 10000 \
--num_train_epochs 3 \
--input_dir data/ \
--output_dir pretrained_models/ \
--logging_steps 1 \
--save_steps 20000 \
--max_steps 1000000 \
--device gpu \
--fp16 False \
--do_train
XPU训练
unset FLAGS_selected_xpus
python -m paddle.distributed.launch --xpus "0" run_pretrain.py \
--model_type bert \
--model_name_or_path bert-base-uncased \
--max_predictions_per_seq 20 \
--batch_size 32 \
--learning_rate 1e-4 \
--weight_decay 1e-2 \
--adam_epsilon 1e-6 \
--warmup_steps 10000 \
--num_train_epochs 3 \
--input_dir data/ \
--output_dir pretrained_models/ \
--logging_steps 1 \
--save_steps 20000 \
--max_steps 1000000 \
--device xpu \
--use_amp False
其中参数释义如下:
model_type
指示了模型类型,使用BERT模型时设置为bert即可。model_name_or_path
指示了某种特定配置的模型,对应有其预训练模型和预训练时使用的 tokenizer。若模型相关内容保存在本地,这里也可以提供相应目录地址。max_predictions_per_seq
表示每个句子中会被mask的token的最大数目,与创建预训练数据时的设置一致。batch_size
表示每次迭代每张卡上的样本数目。learning_rate
表示基础学习率大小,将于learning rate scheduler产生的值相乘作为当前学习率。weight_decay
表示AdamW优化器中使用的weight_decay的系数。adam_epsilon
表示AdamW优化器中使用的epsilon值。warmup_steps
表示动态学习率热启的step数。num_train_epochs
表示训练轮数。input_dir
表示输入数据的目录,该目录下所有文件名中包含training的文件将被作为训练数据。output_dir
表示模型的保存目录。logging_steps
表示日志打印间隔。save_steps
表示模型保存及评估间隔。max_steps
表示最大训练步数,达到max_steps
后就提前结束。注意,我们必须设置max_steps
。device
表示训练使用的设备, 'gpu'表示使用GPU, 'xpu'表示使用百度昆仑卡, 'cpu'表示使用CPU。use_amp
指示是否启用自动混合精度训练。
unset FLAGS_selected_xpus
python -m paddle.distributed.launch --xpus "0" run_pretrain_trainer.py \
--model_type bert \
--model_name_or_path bert-base-uncased \
--max_predictions_per_seq 20 \
--per_device_train_batch_size 32 \
--learning_rate 1e-4 \
--weight_decay 1e-2 \
--adam_epsilon 1e-6 \
--warmup_steps 10000 \
--num_train_epochs 3 \
--input_dir data/ \
--output_dir pretrained_models/ \
--logging_steps 1 \
--save_steps 20000 \
--max_steps 1000000 \
--device xpu \
--fp16 False \
--do_train
其中参数释义如下:
model_type
指示了模型类型,使用BERT模型时设置为bert即可。model_name_or_path
指示了某种特定配置的模型,对应有其预训练模型和预训练时使用的 tokenizer。若模型相关内容保存在本地,这里也可以提供相应目录地址。max_predictions_per_seq
表示每个句子中会被mask的token的最大数目,与创建预训练数据时的设置一致。per_device_train_batch_size
表示用于训练的每个 GPU 核心/CPU 的batch大小.(int
,可选,默认为 8)learning_rate
表示基础学习率大小,将于learning rate scheduler产生的值相乘作为当前学习率。weight_decay
表示AdamW优化器中使用的weight_decay的系数。adam_epsilon
表示AdamW优化器中使用的epsilon值。warmup_steps
表示动态学习率热启的step数。num_train_epochs
表示训练轮数。input_dir
表示输入数据的目录,该目录下所有文件名中包含training的文件将被作为训练数据。output_dir
表示模型的保存目录。logging_steps
表示日志打印间隔。save_steps
表示模型保存及评估间隔。max_steps
表示最大训练步数,达到max_steps
后就提前结束。注意,我们必须设置max_steps
。device
表示训练使用的设备, 'gpu'表示使用GPU, 'xpu'表示使用百度昆仑卡, 'cpu'表示使用CPU。fp16
是否使用 fp16 混合精度训练而不是 fp32 训练。(bool
, 可选, 默认为False
)do_train
是否进行训练任务。(bool
, 可选, 默认为False
)
NOTICE: 预训练时data目录存放的是经过 create_pretraining_data.py
处理后的数据,因此需要通过该数据处理脚本预先处理,否则预训练将会出现报错。
以GLUE中的SST-2任务为例,启动Fine-tuning的方式如下:
unset CUDA_VISIBLE_DEVICES
python -m paddle.distributed.launch --gpus "0" run_glue_trainer.py \
--model_name_or_path bert-base-uncased \
--task_name SST2 \
--max_seq_length 128 \
--per_device_train_batch_size 32 \
--per_device_eval_batch_size 32 \
--learning_rate 2e-5 \
--num_train_epochs 3 \
--logging_steps 1 \
--save_steps 500 \
--output_dir ./tmp/ \
--device gpu \
--fp16 False\
--do_train \
--do_eval
其中参数释义如下:
model_name_or_path
指示了某种特定配置的模型,对应有其预训练模型和预训练时使用的 tokenizer。若模型相关内容保存在本地,这里也可以提供相应目录地址。注:bert-base-uncased
等对应使用的预训练模型转自huggingface/transformers,具体可参考当前目录下converter中的内容。task_name
表示Fine-tuning的任务。max_seq_length
表示最大句子长度,超过该长度将被截断。per_device_train_batch_size
表示用于训练的每个 GPU 核心/CPU 的batch大小.(int
,可选,默认为 8)per_device_eval_batch_size
表示用于评估的每个 GPU 核心/CPU 的batch大小.(int
,可选,默认为 8)learning_rate
表示基础学习率大小,将于learning rate scheduler产生的值相乘作为当前学习率。num_train_epochs
表示训练轮数。logging_steps
表示日志打印间隔。save_steps
表示模型保存及评估间隔。output_dir
表示模型保存路径。device
表示训练使用的设备, 'gpu'表示使用GPU, 'xpu'表示使用百度昆仑卡, 'cpu'表示使用CPU, 'npu'表示使用华为昇腾卡。fp16
是否使用 fp16 混合精度训练而不是 fp32 训练。(bool
, 可选, 默认为False
)do_train
是否进行训练任务。(bool
, 可选, 默认为False
)do_eval
是否进行评估任务。同上。(bool
, 可选, 默认为False
)
基于bert-base-uncased
在GLUE各评测任务上Fine-tuning后,在验证集上有如下结果:
Task | Metric | Result |
---|---|---|
SST2 | Accuracy | 0.92660 |
QNLI | Accuracy | 0.91707 |
CoLA | Mattehew's corr | 0.59557 |
MRPC | F1/Accuracy | 0.91667/0.88235 |
STSB | Person/Spearman corr | 0.88847/0.88350 |
QQP | Accuracy/F1 | 0.90581/0.87347 |
MNLI | Matched acc/MisMatched acc | 0.84422/0.84825 |
RTE | Accuracy | 0.711191 |
在Fine-tuning完成后,我们可以使用如下方式导出希望用来预测的模型:
python -u ./export_model.py \
--model_type bert \
--model_path bert-base-uncased \
--output_path ./infer_model/model
其中参数释义如下:
model_type
指示了模型类型,使用BERT模型时设置为bert即可。model_path
表示训练模型的保存路径,与训练时的output_dir
一致。output_path
表示导出预测模型文件的前缀。保存时会添加后缀(pdiparams
,pdiparams.info
,pdmodel
);除此之外,还会在output_path
包含的目录下保存tokenizer相关内容。
完成模型导出后,可以开始部署。deploy/python/seq_cls_infer.py
文件提供了python部署预测示例。可执行以下命令运行部署示例:
python deploy/python/seq_cls_infer.py --model_dir infer_model/ --device gpu --backend paddle
运行后预测结果打印如下:
[2023-03-02 08:30:03,877] [ INFO] - We are using <class 'paddlenlp.transformers.bert.fast_tokenizer.BertFastTokenizer'> to load '../../infer_model/'.
[INFO] fastdeploy/runtime/runtime.cc(266)::CreatePaddleBackend Runtime initialized with Backend::PDINFER in Device::GPU.
Batch id: 0, example id: 0, sentence1: against shimmering cinematography that lends the setting the ethereal beauty of an asian landscape painting, label: positive, negative prob: 0.0003, positive prob: 0.9997.
Batch id: 1, example id: 0, sentence1: the situation in a well-balanced fashion, label: positive, negative prob: 0.0002, positive prob: 0.9998.
Batch id: 2, example id: 0, sentence1: at achieving the modest , crowd-pleasing goals it sets for itself, label: positive, negative prob: 0.0017, positive prob: 0.9983.
Batch id: 3, example id: 0, sentence1: so pat it makes your teeth hurt, label: negative, negative prob: 0.9986, positive prob: 0.0014.
Batch id: 4, example id: 0, sentence1: this new jangle of noise , mayhem and stupidity must be a serious contender for the title ., label: negative, negative prob: 0.9806, positive prob: 0.0194.
更多详细用法可参考 Python 部署。
上述的介绍是基于动态图的BERT的预训练任务和微调任务以及预测任务的实践过程,同时在我们也提供了基于PaddlePaddle Fleet API的静态图的BERT相关实践,在组网代码层面保持动静统一,在计算速度以及多机联合训练方面有着更优的性能,具体的细节可以参考 BERT静态图 。