超详细中文预训练模型ERNIE使用指南

本文做者:杨蕊1002html

实习之后由于各类事就很久没写过文章了。最近在工做上处理的都是中文语料,也尝试了一些最近放出来的预训练模型(ERNIE,BERT-CHINESE,WWM-BERT-CHINESE),比对以后仍是以为百度的ERNIE效果会比较好,并且使用十分方便,因此今天就详细地记录一下。但愿你们也都能在本身的项目上取得进展~git

1A Glance at ERNIEgithub

关于ERNIE模型自己的话这篇不会作过多介绍,网上的介绍文档也不少了,相信从事NLP的同窗们确定都很是熟悉啦。web

 

2ERNIE源码浅尝bash

Okay,当咱们了解了ERNIE模型的大致框架及原理以后,接下来就能够深刻理解一下具体的实现啦。ERNIE是基于百度本身的深度学习框架飞桨(PaddlePaddle)搭建的,(百度推这个飞桨的力度仍是蛮大的,还开放了免费算力),你们平时炼丹用的更多的多是TensorFlow和Pytorch,这里关于运行ERNIE的飞桨环境安装能够参考快速安装指南(https://www.paddlepaddle.org.cn/#quick-start)。框架

2.1 关于输入dom

模型预训练的输入是基于百科类、资讯类、论坛对话类数据构造具备上下文关系的句子对数据,利用百度内部词法分析工具对句对数据进行字、词、实体等不一样粒度的切分,而后基于 tokenization.py中的 CharTokenizer 对切分后的数据进行 token 化处理,获得明文的 token 序列及切分边界,而后将明文数据根据词典 config/vocab.txt 映射为 id 数据,在训练过程当中,根据切分边界对连续的 token 进行随机 mask 操做。通过上述预处理以后的输入样例为:函数

 

1 1048 492 1333 1361 1051 326 2508 5 1803 1827 98 164 133 2777 2696 983 121 4 19 9 634 551 844 85 14 2476 1895 33 13 983 121 23 7 1093 24 46 660 12043 2 1263 6 328 33 121 126 398 276 315 5 63 44 35 25 12043 2;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55;-1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 -1 0 0 0 1 0 0 1 0 1 0 0 1 0 1 0 -1;0工具

 

一共有五个部分组成,每一个部分之间用分号;隔开:源码分析

  • token_ids:输入句子对的表示;
  • sentence_type_ids:0或者1表示token属于哪个句子;
  • position_ids:绝对位置编码
  • seg_labels: 表示分词边界信息,0表示词首、1表示非词首、-1为占位符
  • next_sentence_label:表示该句子对是否存在上下句的关系(0为无1为有)

reader.pretraining.py中的parse_line函数.

2.2 关于mask策略 batching.py

咱们知道,相较于BERT,ERNIE最大的改进就是中文 + 短语/实体掩码(这个短语掩码的操做后来也被BERT采用训练出了WWM-BERT),因此咱们首先来看看ERNIE的掩码机制是怎么样实现的。

2.3 关于infer过程代码改写

ERNIE代码很方便使用,可是有一个不足的地方就是目前官方尚未给出infer.py文件,也就是模型训练以后给出快速推理结果的文件。Github上简直万人血书求接口呀。

 

因此咱们的目的就是须要改写源码,完成这样一个接口:输入为咱们须要预测的文件predict.tsv,调用接口后输出为相应任务的结果pred_result。下面咱们以分类任务为例,改写一个infer接口。

Step 1. finetune下的classifier.py

在文件中完成predict函数

Step 2. run_classifier.py

修改predict_only=True时的逻辑

Step 3. finetune_args.py

在该文件中添加一个参数do_predict

OK, 篇幅有限后面还要介绍具体ERNIE实战,源码阅读部分就先这样,其实剩下的不少都跟BERT代码比较类似,感兴趣的同窗也能够参考以前的 BERT源码分析系列https://blog.csdn.net/Kaiyuan_sjtu/article/details/90265473

 

3ERNIE实战指南

上面扯的都是务虚的,接下来咱们务实地来看看ERNIE这个预训练模型的具体应用。和BERT相比,ERNIE的使用更加简单,在以前介绍过的BERT模型实战之多文本分类(https://blog.csdn.net/Kaiyuan_sjtu/article/details/88709580中,咱们须要手动改写一个适应本身任务的Processor,而对于ERNIE来讲,简单到只须要三步:

  • 把数据准备成要求的格式(源码中使用tsv格式,不过在bert中咱们也说过了,能够修改为各类格式的)
  • 写一下训练脚本sh
  • 跑脚本获得结果bash run_script.sh

准备工做

对于最近大火的预训练模型来讲,绝大多数咱们是不太可能本身从头开始训练的,最多使用的是官方开源的模型进行特定任务的Finetune。因此第一步就是下载模型代码

https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE

以及相应的参数https://baidu-nlp.bj.bcebos.com/ERNIE_stable-1.0.1.tar.gz

接下去就是准备咱们任务的数据,使其符合ERNIE模型输入要求。通常来讲字段之间都是label和text_a用制表符分割,对于句对任务还须要额外的text_b字段。在后面咱们会具体介绍每种任务的示例输入。

ok,前面咱们一直强调ERNIE是超友好上手超快的模型,下面咱们结合实际任务来看一看到底有多简单~

情感分类

情感分类是属于很是典型的NLP基础任务之一,由于以前BERT写过文本分类,因此这里咱们就稍微换一换口味~这里咱们只考虑最简单状况的情感分类任务,即给定一个输入句子,要求模型给出一个情感标签,能够是只有正负的二分类,也能够是包括中性情感的三分类。ok,咱们来看看数据,网上随便找了一个财经新闻数据集,数据来源于雪球网上万得资讯发布的正负面新闻标题,数据集中包含17149条新闻数据,包括日期、公司、代码、正/负面、标题、正文6个字段,其中正面新闻12514条,负面新闻4635条。大概长这样:

处理成ERNIE分类任务所须要的输入,大概长这样:

将处理完成的数据和前面下载好的预训练模型参数放置到合适的位置,就能够开始写咱们跑模型的脚本文件了:

嗯,这样一个任务就结束了…运行脚本后等待输出结果便可,是否是很简单~

固然若是你还想玩点花样的话,就能够多看看论文。好比复旦以前有一篇文章是在BERT的基础上,将ABSA情感分类的单句分类任务转变成了句子对的类似度匹配任务。简单来讲就是经过构建辅助句子,把输入这家餐馆的锅包肉超好吃变成了这家餐馆的锅包肉超好吃 + 菜品口感的情感是正的,论文代表这一trick是会比单句分类的效果更好。更具体的细节能够参考论文:
Utilizing BERT for Aspect-Based Sentiment Analysis via Constructing Auxiliary Sentence》:https://www.aclweb.org/anthology/N19-1035

 

命名实体识别

命名实体识别也是NLP的一个基础任务,以前在博客中也有过介绍:【论文笔记】命名实体识别论文https://blog.csdn.net/Kaiyuan_sjtu/article/details/89143573


关于NER的处理思路也是跟上面情感分类的大同小异,只不过NER是属于序列标注任务,在运行脚本的时候注意使用源码中的run_senquence_labeling.py

4、有趣的ISSUE

Github上比源码更有价值的是对应的issue,一个好的开源项目会吸引不少人的关注,issue区里会有不少有趣的思考,因此你们千万不要错过噢~下面就列几个我以为比较有意思的issue供你们参考。

  1. 关于batch_size

刚打开ERNIE脚本打算跑的同窗可能会发现,它的batch_size居然是8192,个人天哪(小岳岳脸),这不得炸!因而乎你很是机智地把batch_size改成了32,美滋滋地输入bash script/pretrain.py,而后自信地敲下Enter键。嗯???报错???

报的什么错你们感兴趣的本身去复现吧~

对,在pretrain的时候这里的batch_size指的是全部输入token的总数,因此才会那么大~

  1. 关于Mask机制的逻辑

正如我开篇说的,ERNIE的最大创新就是它的mask机制,这一点的代码实现也在issue区被热烈讨论

  1. 关于获取输入的中间向量表示

有时候咱们会须要获取句子 Embedding 和 token Embeddings,可参照下面的方案

  1. 预测被masked的词

将一个句子的某个词语mask后,而后使用模型去预测这个词语,获得候选词和词语的几率

  1. ERNIE模型部署

飞桨(PaddlePaddle)模型的部署能够在官方说明文档中找到:https://www.paddlepaddle.org.cn/documentation/docs/zh/1.4/advanced_usage/deploy/inference/index_cn.html

 

5Some Tips

最后一部分打算说一下关于使用预训练模型的一些小tips:

  • 学习率是第一种重要的参数,当你开始着手调参时优先从学习率开始。
  • 根据你的任务来选择预训练模型。每一个模型的训练大规模语料是不同的,这就说明了有些模型天生就是更加适用于某个领域。
  • 全部的预训练模型为了在尽量多的下游任务上取得较好的效果,所使用的训练语料的覆盖范围都是很是大的,但这也带来了一个问题----过于general。也就是说若是你的任务所属domain与训练语料的相差较大,好比关于医学材料学之类的领域,反而不容易取得好的效果。因此咱们能够在特定领域下尝试post-train预训练模型
  • 目前来讲,对于中文领域的NLP任务,能够优先选择ERNIE。听小道消息说,ERNIE 2.0快出来了,听说效果很猛。
  • 不要过度迷信预训练模型!!!

 

关于ERNIE的更多信息,可点击文末阅读原文(连接:https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE或查看如下连接:

https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE

 

 

Reference:

 

 

 

 

 

原文连接地址:https://developer.baidu.com/topic/show/290242

相关文章
相关标签/搜索