huggingface实操_百度NLP预训练模型ERNIE2.0最强实操课程来袭!【附教程】

2019年3月,百度正式发布NLP模型ERNIE,其在中文任务中全面超越BERT一度引发业界广泛关注和探讨。经过短短几个月时间,百度ERNIE再升级,发布持续学习的语义理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0预训练模型。继1.0后,ERNIE英文任务方面取得全新突破,在共计16个中英文任务上超越了BERT和XLNet, 取得了SOTA效果。

本篇内容可以说是史上最强实操课程,由浅入深完整带大家试跑ERNIE,大家可前往AI Studio fork代码 (https://aistudio.baidu.com/aistudio/projectdetail/117030),运行即可获赠12小时GPU算力,每天都有哦~

一、基础部分

1.1 准备代码、数据、模型

step1:下载ERNIE代码。温馨提示:如果下载慢,暂停重试

!git clone --depth 1 https://github.com/PaddlePaddle/ERNIE.git

step2:下载并解压finetune数据

!wget --no-check-certificate https://ernie.bj.bcebos.com/task_data_zh.tgz

!tar xf task_data_zh.tgz

step3:下载预训模型

!wget --no-check-certificate https://ernie.bj.bcebos.com/ERNIE_1.0_max-len-512.tar.gz

!mkdir -p ERNIE1.0

!tar zxf ERNIE_1.0_max-len-512.tar.gz -C ERNIE1.0

备用方案,如果下载慢的话,可以用我们预先下载好的代码和数据

%cd ~

!cp -r work/ERNIE1.0 ERNIE1.0

!cp -r work/task_data task_data

!cp -r work/lesson/ERNIE ERNIE

完成ERNIE代码部分的准备之后,让我们一起以一个序列标注任务来举例。

什么是序列标注任务?

下面这张图可以概括性的让大家理解序列标注任务:

序列标注的任务可以用来做什么?

可以:信息抽取、数据结构化,帮助搜索引擎搜索的更精准

可以:…

序列标注任务: 一起来看看这个任务的数据长什么样子吧?

序列标注任务输入数据包含2部分:

1)标签映射文件:存储标签到ID的映射。

2)训练测试数据:2列,文本、标签(文本中每个字之间使用隐藏字符\2分割,标签同理。)

# 标签映射文件

!cat task_data/msra_ner/label_map.json

{

"B-PER": 0,

"I-PER": 1,

"B-ORG": 2,

"I-ORG": 3,

"B-LOC": 4,

"I-LOC": 5,

"O": 6

}

# 测试数据

!head task_data/msra_ner/dev.tsv

B: Begin

I: Inside

O: Outside

ERNIE应用于序列化标注

1.2 利用ERNIE做Finetune

step1:设置环境变量

%cd ERNIE

!ln -s ../task_data

!ln -s ../ERNIE1.0

%env TASK_DATA_PATH=task_data

%env MODEL_PATH=ERNIE1.0

!echo "task_data_path: ${TASK_DATA_PATH}"

!echo "model_path: ${MODEL_PATH}"

step2:运行finetune脚本

!sh script/zh_task/ernie_base/run_msra_ner.sh

1.3将Finetune结果打印

在finetune过程中,会自动保存对test集的预测结果,我们可以查看预测结果是否符合预期。

由于Finetune需要一些时间,所以不等Finetune完了,直接查看我们之前已经Finetune收敛后的模型与test集的预测结果

%cd ~

show_ner_prediction('work/lesson/test_result.5.final')

二、进阶部分

2.1 GPU显存过小,如何使用ERNIE?

脚本进阶:模型太大,无法完全放进显存的情况下,如何只使用前3层参数热启Finetune?

如果能只加载几层模型就好了!

方法:只需要修改一行配置文件ernie_config.json,就能自动的使用前3层参数热启Finetune。

提示:ernie_config.json在ERNIE1.0发布的预训练模型中

TODO 结合“终端”标签,运行一下吧

提示:您可以需要用到sed与pwd命令

step1:设置环境变量

%cd ~%cd ERNIE

!ln -s ../task_data

!ln -s ../ERNIE1.0

%env TASK_DATA_PATH=task_data

%env MODEL_PATH=ERNIE1.0

!echo "task_data_path: ${TASK_DATA_PATH}"

!echo "model_path: ${MODEL_PATH}"

!pwd

!sh script/zh_task/ernie_base/run_msra_ner.sh

2.2如何将ERNIE适配我的业务数据?

数据进阶:如何修改输入格式?

假设msra ner任务的输入数据格式变了,每条样本不是以行式保存,而是以列式保存。列式保存是指,每条样本由多行组成,每行包含一个字符和对应的label,不同样本间以空行分割,具体样例如下:

text_a label

海 O

钓 O

比 O

赛 O

地 O

点 O

在 O

厦 B-LOC

门 I-LOC

与 O

金 B-LOC

门 I-LOC

之 O

间 O

的 O

海 O

域 O

。 O

当输入数据为列式时,我们如何修改ERNIE的数据处理代码,以适应新的数据格式。

首先,我们先大致了解一下ERNIE的数据处理流程:

ERNIE对于finetune任务的所有数据处理代码都在reader/task_reader.py中,里面已经预先写好了适合多种不同类型任务的Reader类,ERNIE通过Reader读取并处理数据给后续模型使用。

Reader类对数据处理流程做了以下几步抽象:

step 1.  从文件中逐条读取样本,通过_read_tsv等方法,读取不同格式的文件,并将读取的每条样本存入一个list

step 2. 逐一将读取的样本转化为Record。Record中包含了一条样本经过数据处理后,模型所需要的所有features。处理成Record的流程一般又分以下几步:

1. 将文本tokenize,超过最大长度时截断;

2. 加入'[CLS]'、'[SEP]'等标记符后,将文本ID化;

3. 生成每个token对应的position和token_type信息。

step 3. 将多个Record组成batch,同一个batch内feature长度不一致时,padding至batch内最大的feature长度。

了解了ERNIE的数据处理流程以后,我们发现当输入数据格式变了,我们只需要修改第1步的代码,保持其他代码不变,就能适应新的数据格式。具体来说,只需要在reader/task_reader.py的 SequenceLabelReader 类中,加入下面的 _read_tsv 函数(重写基类 BaseReader 的 _read_tsv)。

def _read_tsv(self, input_file, quotechar=None):

with open(input_file, 'r', encoding='utf8') as f:

reader = csv_reader(f)

headers = next(reader)

text_indices = [

index for index, h in enumerate(headers) if h != 'label'

]

Example = namedtuple('Example', headers)

examples = []

buf_t, buf_l = [], []

for line in reader:

if len(line) != 2:

assert len(buf_t) == len(buf_l)

example = Example(u'^B'.join(buf_t), u'^B'.join(buf_l))

examples.append(example)

buf_t, buf_l = [], []

continue

if line[0].strip() == '':

continue

buf_t.append(line[0])

buf_l.append(line[1])

if len(buf_t) > 0:

assert len(buf_t) == len(buf_l)

example = Example(u'^B'.join(buf_t), u'^B'.join(buf_l))

examples.append(example)

buf_t, buf_l = [], []

return examples

我们将已经修改好的数据和代码,预先放在work/lesson/2目录中,可以替换掉ERNIE项目中对应的文件,然后尝试运行

%cd ~

!cp -r work/lesson/2/msra_ner_columnwise task_data/msra_ner_columnwise

!cp -r work/lesson/2/task_reader.py ERNIE/reader/task_reader.py

!cp -r work/lesson/2/run_msra_ner.sh ERNIE/script/zh_task/ernie_base/run_msra_ner_columnwise.sh

%cd ERNIE

!ln -s ../task_data

!ln -s ../ERNIE1.0

%env TASK_DATA_PATH=task_data

%env MODEL_PATH=ERNIE1.0 !sh script/zh_task/ernie_base/run_msra_ner_columnwise.sh

2.3在哪里改模型结构?

模型进阶:如何将序列标注任务的损失函数替换为CRF?

目前序列标注任务的finetune代码中,以 softmax ce 作为损失函数,该损失函数较为简单,没有考虑到序列中词与词之间的联系,如何替换一个更优秀的损失函数呢?

我们只需要修改其中的create_model函数,将 softmax ce 损失函数部分,替换为 linear_chain_crf 即可,具体代码如下:

def create_model(args, pyreader_name, ernie_config, is_prediction=False):

pyreader = fluid.layers.py_reader(

capacity=50,

shapes=[[-1, args.max_seq_len, 1], [-1, args.max_seq_len, 1],

[-1, args.max_seq_len, 1], [-1, args.max_seq_len, 1],

[-1, args.max_seq_len, 1], [-1, args.max_seq_len, 1], [-1, 1]],

dtypes=[

'int64', 'int64', 'int64', 'int64', 'float32', 'int64', 'int64'

],

lod_levels=[0, 0, 0, 0, 0, 0, 0],

name=pyreader_name,

use_double_buffer=True)

(src_ids, sent_ids, pos_ids, task_ids, input_mask, labels,

seq_lens) = fluid.layers.read_file(pyreader)

ernie = ErnieModel(

src_ids=src_ids,

position_ids=pos_ids,

sentence_ids=sent_ids,

task_ids=task_ids,

input_mask=input_mask,

config=ernie_config,

use_fp16=args.use_fp16)

enc_out = ernie.get_sequence_output()

enc_out = fluid.layers.dropout(

x=enc_out, dropout_prob=0.1, dropout_implementation="upscale_in_train")

logits = fluid.layers.fc(

input=enc_out,

size=args.num_labels,

num_flatten_dims=2,

param_attr=fluid.ParamAttr(

name="cls_seq_label_out_w",

initializer=fluid.initializer.TruncatedNormal(scale=0.02)),

bias_attr=fluid.ParamAttr(

name="cls_seq_label_out_b",

initializer=fluid.initializer.Constant(0.)))

infers = fluid.layers.argmax(logits, axis=2)

ret_infers = fluid.layers.reshape(x=infers, shape=[-1, 1])

lod_labels = fluid.layers.sequence_unpad(labels, seq_lens)

lod_infers = fluid.layers.sequence_unpad(infers, seq_lens)

lod_logits = fluid.layers.sequence_unpad(logits, seq_lens)

(_, _, _, num_infer, num_label, num_correct) = fluid.layers.chunk_eval(

input=lod_infers,

label=lod_labels,

chunk_scheme=args.chunk_scheme,

num_chunk_types=((args.num_labels-1)//(len(args.chunk_scheme)-1)))

probs = fluid.layers.softmax(logits)

crf_loss = fluid.layers.linear_chain_crf(

input=lod_logits,

label=lod_labels,

param_attr=fluid.ParamAttr(

name='crf_w',

initializer=fluid.initializer.TruncatedNormal(scale=0.02)))

loss = fluid.layers.mean(x=crf_loss)

graph_vars = {

"inputs": src_ids,

"loss": loss,

"probs": probs,

"seqlen": seq_lens,

"num_infer": num_infer,

"num_label": num_label,

"num_correct": num_correct,

}

for k, v in graph_vars.items():

v.persistable = True

return pyreader, graph_vars

我们将已经修改好的数据和代码,预先放在work/lesson/3 目录中,可以替换掉ERNIE项目中对应的文件,然后尝试运行

%cd ~

!cp -r work/lesson/3/sequence_label.py ERNIE/finetune/sequence_label.py

%cd ERNIE

!ln -s ../task_data

!ln -s ../ERNIE1.0

%env TASK_DATA_PATH=task_data

%env MODEL_PATH=ERNIE1.0

!sh script/zh_task/ernie_base/run_msra_ner_columnwise.sh

修改后重新运行finetune脚本:

sh script/zh_task/ernie_base/run_msra_ner.sh等待运行完后,取最后一次评估结果,对比如下:

划重点!

查看ERNIE模型使用的完整内容和教程,请点击下方链接,建议Star收藏到个人主页,方便后续查看。

GitHub:https://github.com/PaddlePaddle/ERNIE

版本迭代、最新进展都会在GitHub第一时间发布,欢迎持续关注!

也邀请大家加入ERNIE官方技术交流**QQ群:760439550**,可在群内交流技术问题,会有ERNIE的研发同学为大家及时答疑解惑。

中文预训练模型ERNIE2.0模型下载及安装

2019年7月,百度ERNIE再升级,发布持续学习的语义理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0预训练模型, 它利用百度海量数据和飞桨(PaddlePaddle)多机多卡高效训练优 ...

NLP预训练模型-百度ERNIE2.0的效果到底有多好【附用户点评】

ERNIE是百度自研的持续学习语义理解框架,该框架支持增量引入词汇(lexical).语法 (syntactic) .语义(semantic)等3个层次的自定义预训练任务,能够全面捕捉训练语料中的词法 ...

最强中文NLP预训练模型艾尼ERNIE官方揭秘【附视频】

“最近刚好在用ERNIE写毕业论文” “感觉还挺厉害的” “为什么叫ERNIE啊,这名字有什么深意吗?” “我想让艾尼帮我写作业” 看了上面火热的讨论,你一定很好奇“艾尼”.“ERNIE”到底是个啥? ...

【转载】最强NLP预训练模型!谷歌BERT横扫11项NLP任务记录

本文介绍了一种新的语言表征模型 BERT--来自 Transformer 的双向编码器表征.与最近的语言表征模型不同,BERT 旨在基于所有层的左.右语境来预训练深度双向表征.BERT 是首个在大批句 ...

最强 NLP 预训练模型库 PyTorch-Transformers 正式开源:支持 6 个预训练框架,27 个预训练模型

先上开源地址: https://github.com/huggingface/pytorch-transformers#quick-tour 官网: https://huggingface.co/py ...

自然语言处理(三) 预训练模型:XLNet 和他的先辈们

预训练模型 在CV中,预训练模型如ImagNet取得很大的成功,而在NLP中之前一直没有一个可以承担此角色的模型,目前,预训练模型如雨后春笋,是当今NLP领域最热的研究领域之一. 预训练模型属于迁移学 ...

我的Keras使用总结(4)——Application中五款预训练模型学习及其应用

本节主要学习Keras的应用模块 Application提供的带有预训练权重的模型,这些模型可以用来进行预测,特征提取和 finetune,上一篇文章我们使用了VGG16进行特征提取和微调,下面尝试一 ...

BERT预训练模型的演进过程!(附代码)

1. 什么是BERT BERT的全称是Bidirectional Encoder Representation from Transformers,是Google2018年提出的预训练模型,即双向Tr ...

XLNet预训练模型,看这篇就够了!(代码实现)

1. 什么是XLNet XLNet 是一个类似 BERT 的模型,而不是完全不同的模型.总之,XLNet是一种通用的自回归预训练方法.它是CMU和Google Brain团队在2019年6月份发布的模 ...

随机推荐

PDO防sql注入原理分析

使用pdo的预处理方式可以避免sql注入. 在php手册中'PDO--预处理语句与存储过程'下的说明: 很多更成熟的数据库都支持预处理语句的概念.什么是预处理语句?可以把它看作是想要运行的 SQL 的 ...

SQL Server 分区表

分区表可以提高查询效率 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随 ...

【Android】Android内存机制,了解Android堆和栈

1.dalvik的Heap和Stack 这里说的只是dalvik java部分的内存,实际上除了dalvik部分,还有native.     下面针对上面列出的数据类型进行说明,只有了解了我们申请的数 ...

Codeforces Round #147 (Div. 2)

A. Free Cash 判断值相同的最长长度. B. Young Table 按从上到下,从左到右排序,每个位置最多交换一次. C. Primes on Interval \(p_i\)表示位置\( ...

zedboard--Opencv移植和zedboard测试(十一)

继上次生成了ARM架构的链接库之后,我们要把他们拷贝到装载有文件系统的SD卡中即可,在拷贝时,最好是/usr/lib下 实践一:将那些lib拷贝到U盘里面,因为之前跑过demo,里面就是一个简易的li ...

总结JAVA----IO流中的File类

对于IO流中File类的总结 File类的基本概念 File类只能用于完成对于文件属性(是否存在.可读性.长度)的一些操作,不能用于文件的访问. File类的对象 File类的对象存储的是文件的绝对路 ...

Perl解除引用:从引用还原到数据对象

使用引用可以指向数据对象,这似乎很简单. @name1=qw(longshuai wugui); @name2=qw(xiaofang tuner); $ref_name=\@name1; push ...

ViewPager Fragment 懒加载 可见 总结 MD

Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

Struts2 Intercepter 笔记

以前一直对Struts2的自定义拦截器(intercepter)不是很清楚,今天仔细研究了下,终于搞懂了,现在记录对拦截器的总结如下: 1:自定义拦截器的作用一般就是用来实现系统权限控制比较多: 2: ...

IDEA教程之导入maven项目

通过从网上的开源项目下载源码,一般都是maven管理的项目,此类项目可以通过导入快捷运行项目,如图为下载的一个项目: 2 打开IDEA,点击第二个选项“Import Porject”,然后选择源码根目 ...

你可能感兴趣的:(huggingface实操)