PaddleNLP学习笔记

PaddleHub学习笔记之NPL

  • PaddleHub简介
  • PaddleHub的安装
    • CUDA安装
    • PaddlePaddle安装
    • PaddleHub安装
  • THUNEW分类实战
    • NLP预训练模型
    • 加载数据集
    • 构建reader
    • 选择优化迁移策略
    • 运行时的配置设置
    • 构建网络并创建分类迁移任务进行Fine-tune
    • 预测
  • 学习体会

PaddleHub简介

PaddleHub是依托于PaddlePaddle框架的预训练模型应用工具,号称十行代码完成ERNIE工业级文本分类,如此可见其开发的简易程度。开发者可以便捷地使用高质量的预训练模型结合Fine-tune API快速完成模型迁移到部署的全流程工作。PaddleHub提供的预训练模型涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、视频分类、图像生成、图像分割、文本审核、关键点检测等主流模型。其GitHub地址为https://github.com/PaddlePaddle/PaddleHub。

PaddleHub的安装

PaddleHub目前支持CPU和GPU计算,所以如果只使用CPU,直接pip安装paddlepaddle,代码如下:

pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

使用GPU请按照以下操作。

CUDA安装

安装PaddleHub之前,需要我们先安装PaddlePaddle(推荐最新版本),需要注意的是,我们需要需要安装CUDA,安装包下载地址https://developer.nvidia.com/cuda-downloads:
Linux平台
PaddleNLP学习笔记_第1张图片
Windows平台
PaddleNLP学习笔记_第2张图片

PaddlePaddle安装

然后再安装gpu版本的PaddlePaddle,安装脚本为:

python -m pip install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple

PaddleHub安装

安装PaddleHub

pip install paddlehub

THUNEW分类实战

NLP预训练模型

模型名 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

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) # 最长处理文字,长度不够的空白补齐,多余部分,截除。

其包含的参数含义为:

  • dataset: 传入定义的PaddleHub Dataset;
  • vocab_path: 传入ERNIE/BERT模型对应的词表文件路径;
  • max_seq_len: ERNIE模型的最大序列长度,若序列长度不足,会通过padding方式补到max_seq_len,
    若序列长度大于该值,则会以截断方式让序列长度为max_seq_len;
  • sp_model_path: 传入 ERNIE 的subword切分模型路径;
  • word_dict_path: 传入 ERNIE 的词语切分模型路径;

选择优化迁移策略

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")

其中:

  • learning_rate: 全局学习率,默认为1e-4
  • lr_scheduler: 学习率调度方法,默认为"linear_decay"
  • warmup_proportion: warmup所占比重
  • weight_decay: 学习率衰减率,当过拟合严重时需要提高此项,当loss很大时,可以降低或者设置为0
  • 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)

其中:

  • log_interval: 打印训练日志的周期,默认为10。
  • eval_interval: 进行评估的周期,默认为100。
  • use_pyreader: 是否使用pyreader,默认False。
  • use_data_parallel: 是否使用并行计算,默认False。打开该功能依赖nccl库。
  • save_ckpt_interval: 保存checkpoint的周期,默认为None。
  • use_cuda: 是否使用GPU训练和评估,默认为False。
  • checkpoint_dir: checkpoint的保存目录,默认为None,此时会在工作目录下根据时间戳生成一个临时目录。
  • num_epoch: 运行的epoch次数,默认为10。
  • batch_size: batch大小,默认为None。
  • enable_memory_optim: 是否进行内存优化,默认为False。
  • strategy: finetune的策略。默认为None,此时会使用DefaultFinetuneStrategy策略。

构建网络并创建分类迁移任务进行Fine-tune

这一块比较难理解,主要是这里用的是静态图的原因。

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

至此其训练迁移学习过程,以及最后的预测完成。

学习体会

这篇博文,主要是在做课程比赛中督促自己学习,学习还是需要有人一起,就像打比赛一样,每次正确率提高那么一点就很兴奋,也正是这一点的提升,才使得自己更加有学下去的动力。找资料的过程中也渐渐明白开源的重要性,以及文本算法模型的一些基本思想,难以想象之前我还对这些一窍不通。以后是属于开源的时代。

你可能感兴趣的:(笔记,PaddleHub,深度学习)