暴走的Mine

  • 2

    获得赞
  • 2

    发布的文章
  • 0

    答辩的项目

使用Paddle框架加载NLP的各类预训练模型方法总结

深度学习

最后更新 2020-04-28 15:34 阅读 9194

最后更新 2020-04-28 15:34

阅读 9194

深度学习

一、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框架做预训练模型加载和微调的过程。这种新一代的国产框架确实有很多亮点,值得我们去学习与探索。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,转载请附上原文出处链接和本声明。
本文链接地址:https://www.flyai.com/article/411
讨论
500字
表情
发送
删除确认
是否删除该条评论?
取消 删除