0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

BERT在中文数据集上的fine tune全攻略

电子工程师 来源:未知 作者:胡薇 2018-11-27 08:53 次阅读

从11月初开始,Google Research就陆续开源了BERT的各个版本。Google此次开源的BERT是通过TensorFlow高级API—— tf.estimator进行封装(wrapper)的。因此对于不同数据集的适配,只需要修改代码中的processor部分,就能进行代码的训练、交叉验证和测试。

奇点机智技术团队将结合利用BERT在AI-Challenger机器阅读理解赛道的实践表现以及多年的NLP经验积累,为大家奉上BERT在中文数据集上的fine tune全攻略。

在自己的数据集上运行 BERT

BERT的代码同论文里描述的一致,主要分为两个部分。一个是训练语言模型(language model)的预训练(pretrain)部分。另一个是训练具体任务(task)的fine-tune部分。在开源的代码中,预训练的入口是在run_pretraining.py而fine-tune的入口针对不同的任务分别在run_classifier.py和run_squad.py。其中run_classifier.py适用的任务为分类任务。如CoLA、MRPC、MultiNLI这些数据集。而run_squad.py适用的是阅读理解(MRC)任务,如squad2.0和squad1.1。

预训练是BERT很重要的一个部分,与此同时,预训练需要巨大的运算资源。按照论文里描述的参数,其Base的设定在消费级的显卡Titan x 或Titan 1080ti(12GB RAM)上,甚至需要近几个月的时间进行预训练,同时还会面临显存不足的问题。

不过所幸的是谷歌满足了Issues#2(https://github.com/google-research/bert/issues/2)里各国开发者的请求,针对大部分语言都公布了BERT的预训练模型。因此在我们可以比较方便地在自己的数据集上进行fine-tune。

下载预训练模型

对于中文而言,google公布了一个参数较小的BERT预训练模型。具体参数数值如下所示:

Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters

模型的下载链接:(https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip)

对下载的压缩文件进行解压,可以看到文件里有五个文件,其中bert_model.ckpt开头的文件是负责模型变量载入的,而vocab.txt是训练时中文文本采用的字典,最后bert_config.json是BERT在训练时,可选调整的一些参数。

修改 processor

任何模型的训练、预测都是需要有一个明确的输入,而BERT代码中processor就是负责对模型的输入进行处理。我们以分类任务的为例,介绍如何修改processor来运行自己数据集上的fine-tune。在run_classsifier.py文件中我们可以看到,google对于一些公开数据集已经写了一些processor,如XnliProcessor,MnliProcessor,MrpcProcessor和ColaProcessor。这给我们提供了一个很好的示例,指导我们如何针对自己的数据集来写processor。

对于一个需要执行训练、交叉验证和测试完整过程的模型而言,自定义的processor里需要继承DataProcessor,并重载获取label的get_labels和获取单个输入的get_train_examples,get_dev_examples和get_test_examples函数。其分别会在main函数的FLAGS.do_train、FLAGS.do_eval和FLAGS.do_predict阶段被调用。

这三个函数的内容是相差无几的,区别只在于需要指定各自读入文件的地址。

以get_train_examples为例,函数需要返回一个由InputExample类组成的list。InputExample类是一个很简单的类,只有初始化函数,需要传入的参数中guid是用来区分每个example的,可以按照train-%d'%(i)的方式进行定义。text_a是一串字符串,text_b则是另一串字符串。在进行后续输入处理后(BERT代码中已包含,不需要自己完成) text_a和text_b将组合成[CLS] text_a [SEP] text_b [SEP]的形式传入模型。最后一个参数label也是字符串的形式,label的内容需要保证出现在get_labels函数返回的list里。

举一个例子,假设我们想要处理一个能够判断句子相似度的模型,现在在data_dir的路径下有一个名为train.csv的输入文件,如果我们现在输入文件的格式如下csv形式:

1,你好,您好0,你好,你家住哪

那么我们可以写一个如下的get_train_examples的函数。当然对于csv的处理,可以使用诸如csv.reader的形式进行读入。

defget_train_examples(self,data_dir):file_path=os.path.join(data_dir,'train.csv')withopen(file_path,'r')asf:reader=f.readlines()examples=[]forindex,lineinenumerate(reader):guid='train-%d'%indexsplit_line=line.strip().split(',')text_a=tokenization.convert_to_unicode(split_line[1])text_b=tokenization.convert_to_unicode(split_line[2])label=split_line[0]examples.append(InputExample(guid=guid,text_a=text_a,text_b=text_b,label=label))returnexamples

同时对应判断句子相似度这个二分类任务,get_labels函数可以写成如下的形式:

defget_labels(self):return['0','1']

在对get_dev_examples和get_test_examples函数做类似get_train_examples的操作后,便完成了对processor的修改。其中get_test_examples可以传入一个随意的label数值,因为在模型的预测(prediction)中label将不会参与计算。

修改 processor 字典

修改完成processor后,需要在在原本main函数的processor字典里,加入修改后的processor类,即可在运行参数里指定调用该processor。

processors={"cola":ColaProcessor,"mnli":MnliProcessor,"mrpc":MrpcProcessor,"xnli":XnliProcessor,"selfsim":SelfProcessor#添加自己的processor}

运行 fine-tune

之后就可以直接运行run_classsifier.py进行模型的训练。在运行时需要制定一些参数,一个较为完整的运行参数如下所示:

exportBERT_BASE_DIR=/path/to/bert/chinese_L-12_H-768_A-12#全局变量下载的预训练bert地址exportMY_DATASET=/path/to/xnli#全局变量数据集所在地址pythonrun_classifier.py--task_name=selfsim#自己添加processor在processors字典里的key名--do_train=true--do_eval=true--dopredict=true--data_dir=$MY_DATASET--vocab_file=$BERT_BASE_DIR/vocab.txt--bert_config_file=$BERT_BASE_DIR/bert_config.json--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt--max_seq_length=128#模型参数--train_batch_size=32--learning_rate=5e-5--num_train_epochs=2.0--output_dir=/tmp/selfsim_output/#模型输出路径

BERT 源代码里还有什么

在开始训练我们自己fine-tune的BERT后,我们可以再来看看BERT代码里除了processor之外的一些部分。

我们可以发现,process在得到字符串形式的输入后,在file_based_convert_examples_to_features里先是对字符串长度,加入[CLS]和[SEP]等一些处理后,将其写入成TFrecord的形式。这是为了能在estimator里有一个更为高效和简易的读入。

我们还可以发现,在create_model的函数里,除了从modeling.py获取模型主干输出之外,还有进行fine-tune时候的loss计算。因此,如果对于fine-tune的结构有自定义的要求,可以在这部分对代码进行修改。如进行NER任务的时候,可以按照BERT论文里的方式,不只读第一位的logits,而是将每一位logits进行读取。

BERT这次开源的代码,由于是考虑在google自己的TPU上高效地运行,因此采用的estimator是tf.contrib.tpu.TPUEstimator,虽然TPU的estimator同样可以在gpucpu上运行,但若想在gpu上更高效地做一些提升,可以考虑将其换成tf.estimator.Estimator,于此同时model_fn里一些tf.contrib.tpu.TPUEstimatorSpec也需要修改成tf.estimator.EstimatorSpec的形式,以及相关调用参数也需要做一些调整。在转换成较普通的estimator后便可以使用常用的方式对estimator进行处理,如生成用于部署的.pb文件等。

GitHub Issues 里一些有趣的内容

从google对BERT进行开源开始,Issues里的讨论便异常活跃,BERT论文第一作者Jacob Devlin也积极地在Issues里进行回应,在交流讨论中,产生了一些很有趣的内容。

在GitHub Issues#95 (https://github.com/google-research/bert/issues/95) 中大家讨论了BERT模型在今年AI-Challenger比赛上的应用。我们也同样尝试了BERT在AI-Challenger的机器阅读理解(mrc)赛道的表现。如果简单得地将mrc的文本连接成一个长字符串的形式,可以在dev集上得到79.1%的准确率。

如果参考openAI的GPT论文(https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf)里multi-choice的形式对BERT的输入输出代码进行修改则可以将准确率提高到79.3%。采用的参数都是BERT默认的参数,而单一模型成绩在赛道的test a排名中已经能超过榜单上的第一名。因此,在相关中文的任务中,bert能有很大的想象空间。

在GitHubIssues#123(https://github.com/google-research/bert/issues/123)中,@hanxiao(https://github.com/hanxiao)给出了一个采用ZeroMQ便捷部署BERT的service,可以直接调用训练好的模型作为应用的接口。同时他将BERT改为一个大的encode模型,将文本通过BERT进行encode,来实现句子级的encode。此外,他对比了多GPU上的性能,发现bert在多GPU并行上的出色表现。

总结

总的来说,Google此次开源的BERT和其预训练模型是非常有价值的,可探索和改进的内容也很多。相关数据集上已经出现了对BERT进行修改后的复合模型,如squad2.0上哈工大(HIT)的AoA + DA + BERT以及西湖大学(DAMO)的SLQA + BERT。 在感谢google这份付出的同时,我们也可以借此站在巨人的肩膀上,尝试将其运用在自然语言处理领域的方方面面,让人工智能的梦想更近一步。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 谷歌
    +关注

    关注

    27

    文章

    6128

    浏览量

    105008
  • 代码
    +关注

    关注

    30

    文章

    4732

    浏览量

    68274
  • tensorflow
    +关注

    关注

    13

    文章

    328

    浏览量

    60479

原文标题:干货 | 谷歌BERT模型fine-tune终极实践教程

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    GPS 设计全攻略

    GPS 设计全攻略
    发表于 09-25 14:11

    LED技术全攻略

    LED技术全攻略
    发表于 09-25 14:16

    GPS 设计全攻略

    GPS 设计全攻略
    发表于 12-05 12:08

    GPS设计全攻略

    本帖最后由 zgzzlt 于 2012-8-16 13:58 编辑 GPS设计全攻略
    发表于 08-06 12:56

    MCU解密全攻略

    MCU解密全攻略
    发表于 08-19 14:28

    FPGA开发全攻略

    电子工程师创新设计必备宝典系列之FPGA开发全攻略,下两册
    发表于 04-24 21:11

    FPGA开发全攻略

    FPGA开发全攻略
    发表于 09-27 10:59

    FPGA开发全攻略

    本帖最后由 lee_st 于 2017-10-31 08:57 编辑 FPGA开发全攻略
    发表于 10-21 20:31

    FPGA开发全攻略

    FPGA开发全攻略
    发表于 05-21 09:28

    FPGA开发全攻略

    FPGA开发全攻略
    发表于 03-03 10:30

    MCU解密全攻略

    本内容介绍了MCU解密的全攻略教程
    发表于 07-11 17:51 648次下载
    MCU解密<b class='flag-5'>全攻略</b>

    FPGA开发全攻略_

    FPGA开发全攻略_上有需要的朋友下来看看。
    发表于 05-10 11:21 29次下载

    LED调光技术全攻略

    LED调光技术全攻略
    发表于 02-08 00:50 41次下载

    智能小车的DIY全攻略

    智能小车的DIY全攻略
    发表于 10-13 09:13 28次下载
    智能小车的DIY<b class='flag-5'>全攻略</b>

    程序员跳槽全攻略

    程序员跳槽全攻略
    发表于 06-14 15:03 0次下载