当前位置:   article > 正文

Bert模型详解和训练实例_bert模型训练

bert模型训练

前面已经介绍了transformer,理解了transformer,那么理解bert就简单多了。对transformer不是很了解的可以跳转到https://blog.csdn.net/one_super_dreamer/article/details/105181690

bert的核心代码解读在https://blog.csdn.net/one_super_dreamer/article/details/105344649,本文主要介绍训练实例。

Bert简介

BERT来自Google的论文Pre-training of Deep Bidirectional Transformers for Language Understanding,BERT是”Bidirectional Encoder Representations from Transformers”的首字母缩写。如下图所示,BERT能够同时利用前后两个方向的信息,而ELMo和GPT只能使用单个方向的。

BERT使用的是Transformer模型,使用的是transformer的encoder部分。那它是怎么解决语言模型只能利用一个方向的信息的问题呢?答案是它的pretraining训练的不是普通的语言模型,而是Mask语言模型。在介绍Mask语言模型之前我们先介绍BERT的输入表示。

输入表示

BERT的输入表示如图下图所示。比如输入的是两个句子”my dog is cute”,”he likes playing”。后面会解释为什么需要两个句子。这里采用类似GPT的两个句子的表示方法,首先会在第一个句子的开头增加一个特殊的Token [CLS],在cute的后面增加一个[SEP]表示第一个句子结束,在##ing后面也会增加一个[SEP]。注意这里的分词会把”playing”分成”play”和”##ing”两个Token,这种把词分成更细粒度的Word Piece的方法在前面的机器翻译部分介绍过了,这是一种解决未登录词的常见办法,后面的代码部分也会简单介绍。接着对每个Token进行3个Embedding:词的Embedding;位置的Embedding和Segment的Embedding。词的Embedding大家都很熟悉了,而位置的Embedding和词类似,把一个位置(比如2)映射成一个低维稠密的向量。而Segment只有两个,要么是属于第一个句子(segment)要么属于第二个句子,不管那个句子,它都对应一个Embedding向量。同一个句子的Segment Embedding是共享的,这样它能够学习到属于不同Segment的信息。对于情感分类这样的任务,只有一个句子,因此Segment id总是0;而对于Entailment任务,输入是两个句子,因此Segment是0或者1。

BERT模型要求有一个固定的Sequence的长度,比如128。如果不够就在后面padding,否则就截取掉多余的Token,从而保证输入是一个固定长度的Token序列,后面的代码会详细的介绍。第一个Token总是特殊的[CLS],它本身没有任何语义,因此它会(必须)编码整个句子(其它词)的语义。

如何训练Bert

以下两种训练是同时进行的。

第一种方法:随机mask掉部分词汇,让机器去学习

为了解决只能利用单向信息的问题,BERT使用的是Mask语言模型而不是普通的语言模型。Mask语言模型有点类似与完形填空——给定一个句子,把其中某个词遮挡起来,让人猜测可能的词。这里会随机的Mask掉15%的词,然后让BERT来预测这些Mask的词,通过调整模型的参数使得模型预测正确的概率尽可能大,这等价于交叉熵的损失函数。这样的Transformer在编码一个词的时候会(必须)参考上下文的信息。

但是这有一个问题:在Pretraining Mask LM时会出现特殊的Token [MASK],但是在后面的fine-tuning时却不会出现,这会出现Mismatch的问题。因此BERT中,如果某个Token在被选中的15%个Token里,则按照下面的方式随机的执行:

  • 80%的概率替换成[MASK],比如my dog is hairy → my dog is [MASK]
  • 10%的概率替换成随机的一个词,比如my dog is hairy → my dog is apple
  • 10%的概率替换成它本身,比如my dog is hairy → my dog is hairy

这样做的好处是,BERT并不知道[MASK]替换的是哪一个词,而且任何一个词都有可能是被替换掉的,比如它看到的apple可能是被替换的词。这样强迫模型在编码当前时刻的时候不能太依赖于当前的词,而要考虑它的上下文,甚至更加上下文进行”纠错”。比如上面的例子模型在编码apple是根据上下文my dog is应该把apple(部分)编码成hairy的语义而不是apple的语义。

第二种方法:预测两个句子是否连接在一起

特殊字符也需要编码。如下图左边的句子应该连在一起情况,但是右边的两个句子不应该连在一起情况。[cls]在进行编码的时候会考虑右边的所有结果,在编码时会判断是否应该连在一起。在对[cls]进行编码的时候也需要做一个分类任务,就是一个二分类任务,输出结果是判断两个句子是否应该连在一起。

BERT在第一句前会加一个[CLS]标志,最后一层该位对应向量可以作为整句话的语义表示,从而用于下游的分类任务等。

为什么选它呢,因为与文本中已有的其它词相比,这个无明显语义信息的符号会更“公平”地融合文本中各个词的语义信息,从而更好的表示整句话的语义。

安装部署

Google提供的BERT代码在https://github.com/google-research/bert,我们可以直接git clone下来。注意运行它需要Tensorflow 1.11及其以上的版本,低版本的Tensorflow不能运行。

预训练的模型(Pre-trained models)

由于从头开始(from scratch)训练需要巨大的计算资源,因此Google提供了预训练的模型(的checkpoint),目前包括英语、汉语和多语言3类模型,而英语又包括4个版本:

  • BERT-Base, Uncased 12层,768个隐单元,12个Attention head,110M参数
  • BERT-Large, Uncased 24层,1024个隐单元,16个head,340M参数
  • BERT-Base, Cased 12层,768个隐单元,12个Attention head,110M参数
  • BERT-Large, Uncased 24层,1024个隐单元,16个head,340M参数。

Uncased的意思是保留大小写,而cased是在预处理的时候都变成了小写。

对于汉语只有一个版本:BERT-Base, Chinese: 包括简体和繁体汉字,共12层,768个隐单元,12个Attention head,110M参数。另外一个多语言的版本是BERT-Base, Multilingual Cased (New, recommended),它包括104种不同语言,12层,768个隐单元,12个Attention head,110M参数。它是用所有这104中语言的维基百科文章混在一起训练出来的模型。所有这些模型的下载地址都在https://github.com/google-research/bert#pre-trained-models

这么多版本我们应该选择哪一个呢?如果我们处理的问题只包含英文,那么我们应该选择英语的版本(模型大效果好但是参数多训练慢而且需要更多内存/显存)。如果我们只处理中文,那么应该使用中文的版本。如果是其他语言就使用多语言的版本。

在压缩包里面有三类文件:

  • A TensorFlow checkpoint (bert_model.ckpt) 总共三个文件,包含的是一些预训练参数
  • A vocab file (vocab.txt) 保存的是当前模型用到的所有的词
  • A config file (bert_config.json) 包含BERT的配置,模型用到的参数

Fine-tuning with BERT

用bert来做一个fine-tuning。由于MRPC中数据集没有那么多,方面进行学习和测试,这里我们已GLUE的MRPC为例子,我们首先需要下载预训练的模型然后解压。下载GLUE数据好像需要代理,这里提供一个国内我已经下载好的数据,https://download.csdn.net/download/one_super_dreamer/12264680

需要下载的有三个,第一个是bert训练好的模型,第二个是bert-master,第三个是fine-tuning用的数据MRPC,我的目录结构如下所示:,我是用的是pycharm环境。

接下来就可以运行如下命令来进行Fine-Tuning了:

  1. python run_classifier.py \
  2. --task_name=MRPC \
  3. --do_train=true \
  4. --do_eval=true \
  5. --data_dir=$GLUE_DIR/MRPC \
  6. --vocab_file=$BERT_BASE_DIR/vocab.txt \
  7. --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  8. --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  9. --max_seq_length=128 \
  10. --train_batch_size=8 \
  11. --learning_rate=2e-5 \
  12. --num_train_epochs=3.0 \
  13. --output_dir=/tmp/mrpc_output/

这里简单的解释一下参数的含义,在后面的代码阅读里读者可以更加详细的了解其意义。

  • task_name 任务的名字,这里我们Fine-Tuning MRPC任务
  • do_train 是否训练,这里为True
  • do_eval 是否在训练结束后验证,这里为True
  • data_dir 训练数据目录,配置了环境变量后不需要修改,否则填入绝对路径
  • vocab_file BERT模型的词典
  • bert_config_file BERT模型的配置文件
  • init_checkpoint Fine-Tuning的初始化参数
  • max_seq_length Token序列的最大长度,这里是128
  • train_batch_size batch大小,对于普通8GB的GPU,最大batch大小只能是8,再大就会OOM
  • learning_rate
  • num_train_epochs 训练的epoch次数,根据任务进行调整
  • output_dir 训练得到的模型的存放目录

如果有读者使用的是pycharm,可以在run里面配置参数,下面是具体示意图。

这里最常见的问题就是内存不够,通常我们的GPU只有8G作用的显存,因此对于小的模型(bert-base),我们最多使用batchsize=8,而如果要使用bert-large,那么batchsize只能设置成1。运行结束后可能得到类似如下的结果:

  1. ***** Eval results *****
  2. eval_accuracy = 0.845588
  3. eval_loss = 0.505248
  4. global_step = 343
  5. loss = 0.505248

大家可以对不同的任务进行训练测试,对于中文模型会在后面的文章里面讲解。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/451761
推荐阅读
相关标签
  

闽ICP备14008679号