柠檬友玩

首页 > 游戏资讯 > 正文

干货|BERT fine-tune 终极实践教程

时间:2022-12-22 05:39:01

从11月初开始,google-research陆续开放源代码化了BERT的各个版本。 谷歌这次的开源BERT由tensorflow高级API—— tf.estimator封装( wrapper )。 因此,对于不同数据集的匹配,只需修改代码的processor部分就可以对代码进行训练、交叉检查和测试。

干货|BERT fine-tune 终极实践教程

以下是BERT中文数据集上的fine tune的最终实践教程。

在自己的数据集上执行BERT

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

预训练是BERT的重要部分,同时预训练需要巨大的计算资源。 根据论文所述参数,其Base设置位于消费显卡Titan x或titan1080ti(12GBram ),需要近几个月的预训练,同时面临内存不足的问题。 幸运的是,谷歌满足了Issues#2各国开发人员的要求,推出了几乎所有语言的BERT预培训模式。 因此,我们可以在自己的数据集上比较容易地进行fine-tune。

下载预训练模型

对于中文,谷歌推出了参数小的BERT预训练模式。 具体参数的数值如下。

chinesesimplifiedandtraditional,12-layer,768-hidden,12-heads,110 m参数

模型的下载链接位于github上的谷歌开源代码中。 解压缩下载的压缩文件后,您会发现该文件中有五个文件。 其中,bert_model.ckpt开头的文件负责加载模型变量,vocab.txt是在训练时用于中文文本的词典,最后的bert_config.json是在训练时BERT是可选的

专业技术支持更改

任何模型的训练、预测都需要明确的输入,但在BERT代码中,processor处理模型的输入。 分类任务示例说明如何更改processor以在自己的数据集上执行fine-tune。 根据run_classsifier.py文件,谷歌已经在XnliProcessor、MnliProcessor、MrpcProcessor、ColaProcessor等公共数据集上发布了一些processor 这提供了一个很好的例子,指导您如何为自己的数据集编写processor。

需要执行完整训练、交叉检查和测试流程的模型会继承自订processor的DataProcessor,并取得label的get_labels和个别输入必须重新加载get_dev_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是另一个字符串。 在进行后续输入处理后,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那样读取。

efget_train_examples(self,data_dir ) :

file_path=OS.path.join ( data _ dir,' train.csv ' ) withopen ) file _ path,' r ' ) as f :

reader=f.readlines

examples=for index,lineinenumerate(reader ) :

guid='train-%d'%index

split_line=line.strip.split (

text _ a=token ization.convert _ to _ unicode ( split _ line [1] ) ) ( ) ) ) ) ) ) ) ) ) ) 655

text _ b=token ization.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 ) ) return examples

另外,与判断句子相似度这一二分类任务相对应,get_labels函数可以写成如下:

efget_labels(self ) :

return ['0','1']

对get_dev_examples和get_test_examples函数执行类似get_train_examples的操作,即可完成processor的更改。 其中,get_test_examples可以传递任何标签值,因为标签在模型预测中不参与计算。

修改专业技术支持词典

修改processor后,必须将修改后的processor类添加到原始主函数的processor词典中。 可以指定执行参数调用其processor。

进程={

' cola': ColaProcessor,

' mnli': MnliProcessor、

' mrpc': MrpcProcessor、

' xnli': XnliProcessor,

' selfsim': SelfProcessor #添加自己的processor

() ) ) ) )。

执行精细整理

然后,可以直接运行run_classsifier.py来训练模型。 在运行时需要创建一些参数。 更完整的执行参数如下。

export Bert _ base _ dir=/path/to/Bert/Chinese _ l-12 _ h-768 _ a-12 #全局变量下载预培训Bert地址export mm

--task_name=selfsim #自己将key名称添加到processor的processors词典中

--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 _ check point=$ 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/self sim _ output/#模型输出路径

BERT源代码还有什么

开始训练我们自己的fine-tune BERT之后,让我们看看Bert代码的processor以外的部分。 process在获得字符串形式的输入后,对file _ based _ convert _ examples _ to _ features的字符串长度进行了[CLS]或[SEP]等几个处理,然后TF rep

另外,可以看出create_model的函数中,除了从modeling.py中取得模型主干输出外,还有进行fine-tune时的loss计算。 因此,如果对fine-tune结构有定制要求,则可以在此部分修改代码。 进行NER任务时,如BERT论文所示,不仅可以读取第一位的logits,还可以读取所有的logits。

estimator采用了tf.contrib.tpu.TPUestimator,因为BERT这次的开放源代码考虑到它可以在谷歌自己的TPU上高效运行。 TPU的Estimator也在gpu和cpu上运行,但为了在gpu上更高效地运行,可以考虑将其替换为tf.estimator.Estimator。 同时,model_fn的一些TF.contrib.TPU.tpuestimatorspec也需要修改为tf.estimator.EstimatorSpec的形式。在转换为更常见的estimator之后,将用于部署的

GitHub Issues的有趣内容

自从谷歌开放源代码BERT之后,在Issues上的讨论变得非常热烈,BERT论文的第一作者Jacob Devlin也在Issues上积极应对,在交流讨论中产生了有趣的内容。

GitHub Issues#95讨论了BERT模型在今年AI-Challenger竞赛中的应用。 我们也同样尝试了BERT的AI-Challenger在机器阅读理解( mrc )电路上的表现。 简单地将mrc文本连接成长字符串的形式,dev集可以获得79.1%的精度。

参考openAI的GPT论文的多选项格式修改BERT的输入输出代码,准确率提高至79.3%。 的参数都是BERT的默认参数,单一模型的成绩在课程的test a排名中超过了排名第一。 因此,bert在相关的中文任务中可以有很大的想象空间。

GitHub Issues#123提供了@hanxiao可以使用ZeroMQ轻松导入BERT的服务,可以将训练过的模型直接作为APP界面调用。 此外,将BERT改为大的encode模型,通过用BERT对文本进行编码实现了语句级编码。 另外,他比较了多GPU下的性能,发现bert在多GPU并行方面很出色。

总结

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