使用Paddle框架加载NLP的各类预训练模型方法总结
深度学习
最后更新 2020-04-28 15:34 阅读 9869
最后更新 2020-04-28 15:34
阅读 9869
深度学习
一、Introduction
最近宅在家,有空只能搞搞NLP的比赛。不得不赞扬一下优秀的国产深度学习框架–Paddle(飞浆),代码精炼,使用简单,具有极高的集成度,非常适合初学者上手。 由于代码中用到了各种预训练模型做迁移学习,所以在此记录一下Paddle Hub加载各类预训练模型的方法。
二、Method
使用Paddle进行训练大概分为以下几个步骤:
- 加载预训练模型
- 加载数据集
- 生成reader
- 选择Fine-Tune优化策略
- 选择运行配置
- 组建Fine-Tune任务
- 开始Fine-Tune
1、加载预训练模型 首先需要在命令行更新paddlehub到最新版本:
pip install --upgrade paddlehub -i https://pypi.tuna.tsinghua.edu.cn/simple
然后通过下面的语法进行预训练模型的加载(若本地未找到会自动联网下载且不限速)
import paddlehub as hub module = hub.Module(name="ernie")
一些常用的NLP预训练模型如下表所示:
模型名 | PaddleHub Module |
---|---|
ERNIE, Chinese | hub.Module(name=‘ernie’) |
ERNIE 2.0 Tiny, Chinese | hub.Module(name=‘ernie_tiny’) |
ERNIE 2.0 Base, English | hub.Module(name=‘ernie_v2_eng_base’) |
ERNIE 2.0 Large, English | hub.Module(name=‘ernie_v2_eng_large’) |
RoBERTa-Large, Chinese | hub.Module(name=‘roberta_wwm_ext_chinese_L-24_H-1024_A-16’) |
RoBERTa-Base, Chinese | hub.Module(name=‘roberta_wwm_ext_chinese_L-12_H-768_A-12’) |
BERT-Base, Uncased | hub.Module(name=‘bert_uncased_L-12_H-768_A-12’) |
BERT-Large, Uncased | hub.Module(name=‘bert_uncased_L-24_H-1024_A-16’) |
BERT-Base, Cased | hub.Module(name=‘bert_cased_L-12_H-768_A-12’) |
BERT-Large, Cased | hub.Module(name=‘bert_cased_L-24_H-1024_A-16’) |
BERT-Base, Multilingual Cased | hub.Module(nane=‘bert_multi_cased_L-12_H-768_A-12’) |
BERT-Base, Chinese | hub.Module(name=‘bert_chinese_L-12_H-768_A-12’) |
2、生成Reader
接着生成一个reader,以文本分类任务为例,reader负责将dataset的数据进行预处理,首先对文本进行分词,然后以特定格式组织并输入给模型进行训练。
ClassifyReader的参数有三个:
dataset: 传入PaddleHub Dataset;
vocab_path: 传入ERNIE/BERT模型对应的词表文件路径;
max_seq_len: ERNIE模型的最大序列长度,若序列长度不足,会通过padding方式补到max_seq_len, 若序列长度大于该值,则会以截断方式让序列长度为max_seq_len;
reader = hub.reader.ClassifyReader( dataset=dataset, vocab_path=module.get_vocab_path(), sp_model_path=module.get_spm_path(), word_dict_path=module.get_word_dict_path(), max_seq_len=128)
3、选择Fine-Tune优化策略
对于ERNIE/BERT这类Transformer模型来说最合适的迁移优化策略就是AdamWeightDecayStrategy了。 AdamWeightDecayStrategy的参数有三个:
learning_rate: 最大学习率
lr_scheduler: 有linear_decay和noam_decay两种衰减策略可选 warmup_proprotion: 训练预热的比例,若设置为0.1, 则会在前10%的训练step中学习率逐步提升到learning_rate
weight_decay: 权重衰减,类似模型正则项策略,避免模型overfitting optimizer_name: 优化器名称,推荐使用Adam
strategy = hub.AdamWeightDecayStrategy( weight_decay=0.01, warmup_proportion=0.1, learning_rate=5e-5)
PaddleHub还额外提供了多个优化策略,如AdamWeightDecayStrategy、ULMFiTStrategy、DefaultFinetuneStrategy等,详细参数说明请移步官方文档。
4、 运行配置 在进行Finetune前,我们可以设置一些运行时的配置。
use_cuda:设置为False表示使用CPU进行训练。如果您本机支持GPU,且安装的是GPU版本的PaddlePaddle,我们建议您将这个选项设置为True
epoch:要求Finetune的任务只遍历1次训练集 batch_size:每次训练的时候,给模型输入的每批数据大小为32,模型训练时能够并行处理批数据,因此batch_size越大,训练的效率越高,但是同时带来了内存的负荷,过大的batch_size可能导致内存不足而无法训练,因此选择一个合适的batch_size是很重要的一步
log_interval:每隔10 步打印一次训练日志 eval_interval:每隔50 步在验证集上进行一次性能评估 checkpoint_dir:将训练的参数和数据保存到model文件夹下
strategy:使用DefaultFinetuneStrategy策略进行
finetune config = hub.RunConfig( use_cuda=True, num_epoch=5, checkpoint_dir="model", batch_size=100, eval_interval=50, strategy=strategy)
5、组建Fine-Tune任务
有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个Task。
获取module的上下文环境,包括输入和输出的变量,以及Paddle Program;
从输出变量中找到用于情感分类的文本特征pooled_output;
在pooled_output后面接入一个全连接层,生成Task;
inputs, outputs, program = module.context( trainable=True, max_seq_len=128) # Use "pooled_output" for classification tasks on an entire sentence. pooled_output = outputs["pooled_output"] feed_list = [ inputs["input_ids"].name, inputs["position_ids"].name, inputs["segment_ids"].name, inputs["input_mask"].name, ] cls_task = hub.TextClassifierTask( data_reader=reader, feature=pooled_output, feed_list=feed_list, num_classes=dataset.num_labels, config=config)
6、开始Fine-Tune
我们通过finetune_and_eval接口来进行模型训练。这个接口在finetune的过程中会周期性的进行模型效果的评估,以便我们了解整个训练过程的性能变化。
run_states = cls_task.finetune_and_eval()
7、模型预测
import numpy as np # 写入预测的文本数据 data = [ ["抗击新型肺炎第一线中国加油鹤岗・绥滨县"],["正能量青年演员朱一龙先生一起武汉祈福武汉加油中国加油"]] index = 0 run_states = cls_task.predict(data=data) results = [run_state.run_results for run_state in run_states] for batch_result in results: # 获取预测的标签索引 batch_result = np.argmax(batch_result, axis=2)[0] for result in batch_result: print("%s\预测值=%s" % (data[index][0], result)) index += 1
三、Conclusion
本次文章简单介绍了以文本分类任务为例的paddle框架做预训练模型加载和微调的过程。这种新一代的国产框架确实有很多亮点,值得我们去学习与探索。