PaddleHub是依托于PaddlePaddle框架的预训练模型应用工具,号称十行代码完成ERNIE工业级文本分类,如此可见其开发的简易程度。开发者可以便捷地使用高质量的预训练模型结合Fine-tune API快速完成模型迁移到部署的全流程工作。PaddleHub提供的预训练模型涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、视频分类、图像生成、图像分割、文本审核、关键点检测等主流模型。其GitHub地址为https://github.com/PaddlePaddle/PaddleHub。
PaddleHub目前支持CPU和GPU计算,所以如果只使用CPU,直接pip安装paddlepaddle,代码如下:
pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
使用GPU请按照以下操作。
安装PaddleHub之前,需要我们先安装PaddlePaddle(推荐最新版本),需要注意的是,我们需要需要安装CUDA,安装包下载地址https://developer.nvidia.com/cuda-downloads:
Linux平台
Windows平台
然后再安装gpu版本的PaddlePaddle,安装脚本为:
python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
安装PaddleHub
pip install paddlehub
模型名 | PaddleHub Module |
---|---|
ERNIE, Chinese | hub.Module(name='ernie') |
ERNIE 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') |
本次新闻标题分类为中文选用ERNIE
安装ERNIE预训练模型
hub install ernie
载入数据,这里使用里官方提供的数据模块。
import paddlehub as hub
dataset = hub.dataset.THUCNEWS()
如果是我们自己的数据则需要重新写dataset这块,官网说明自定义数据集方式具体方式为:
import io
import os
from paddlehub.dataset.base_nlp_dataset import BaseNLPDataset
from paddlehub.dataset import InputExample
class THUCNEWS(BaseNLPDataset):
def __init__(self):
dataset_dir = os.path.join("thucnews") # 这里需要给出train.txt,dev.txt,test.txt的所在路径
super(THUCNEWS, self).__init__(
base_path=dataset_dir ,
train_file="train.txt",
dev_file="dev.txt",
test_file="test.txt",
label_file=None,
label_list=[str(i) for i in range(14)],
)
# 对数据进行处理,关键点是InputExample,这里也可以重写,可以参照PaddleHub源码修改
def _read_file(self, input_file, phase=None):
"""Reads a tab separated value file."""
with io.open(input_file, "r", encoding="UTF-8") as file:
examples = []
for (i, line) in enumerate(file):
data = line.strip().split("_!_")
try:
example = InputExample(
guid=i, label=data[0], text_a=data[3], text_b=None)
examples.append(example)
except:
pass
return examples
dataset = THUCNEWS()
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) # 最长处理文字,长度不够的空白补齐,多余部分,截除。
其包含的参数含义为:
PaddleHub中为我们提供了很多Fine-Tune优化策略,官方文档地址为https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Strategy
在这里我们选取AdamWeightDecayStrategy优化策略,具体代码为:
strategy = hub.AdamWeightDecayStrategy(
learning_rate=1e-4,
lr_scheduler="linear_decay",
warmup_proportion=0.0,
weight_decay=0.01,
optimizer_name="adam")
其中:
config = hub.RunConfig(
log_interval=10, # 日志打印间隔步数
eval_interval=100, # 评估周期,查看训练效果,可以设置较大,可以加快训练
use_pyreader=False,
use_data_parallel=False,
save_ckpt_interval=None,
use_cuda=True,
checkpoint_dir='THUNEWS_finetune', #
num_epoch=1, # 训练多少轮
batch_size=100, # 每次训练数据大小,根据自己内存可以调节
enable_memory_optim=False,
strategy=strategy)
其中:
这一块比较难理解,主要是这里用的是静态图的原因。
inputs, outputs, program = module.context(trainable=True, max_seq_len=128)
pooled_output = outputs["pooled_output"]
# feed_list的配置需要与ClassifyReader的Tensor输出顺序保持一致。
# 请注意,此处的tensor name顺序不可以改变,因为ClassifyReader就是按照这一顺序返回ERNIE所需的输入tensor。
# 具体可以查看reader下的nlpreader.py源代码
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)
cls_task.finetune_and_eval() # 开始训练和评估模型
hub.TextClassifierTask类似一根线,将与训练模型以及自己的数据,优化策略连接在一起进行训练,前面所作的工作都是在建立模块,后面建立的任务是将前面的模块组装起来使其可以运转。
最后是如何预测,当训练完成后,只要存储的文件夹在,上面代码可以短时间跑一边(重新进行训练时需要将原来的文件夹删除,也可以将config中的checkpoint_dir重命名),便于下面的预测。
import numpy as np
labels = []
datas = []
with io.open('thucnews/test.txt', "r", encoding="UTF-8") as file:
for (i, line) in enumerate(file):
data = line.strip().split("_!_")
labels.append(data[0])
datas.append([data[3]])
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\tpredict=%s\tlabel=%s" % (datas[index][0], result, labels[index]))
index += 1
至此其训练迁移学习过程,以及最后的预测完成。
这篇博文,主要是在做课程比赛中督促自己学习,学习还是需要有人一起,就像打比赛一样,每次正确率提高那么一点就很兴奋,也正是这一点的提升,才使得自己更加有学下去的动力。找资料的过程中也渐渐明白开源的重要性,以及文本算法模型的一些基本思想,难以想象之前我还对这些一窍不通。以后是属于开源的时代。