前面已经说了transformer(BERT(一) Transformer原理理解)的模型以及具体结构中每一个component的作用,那么今天这一篇我将会总结BERT(Bidirectional Encoder Representations from Transformers)是如何利用transformer的结构进行自然语言处理的。关于BERT与transformer的关系大家要能理解., 这里的embedding其实就是我们encoder输出的隐藏层,其shape是[batch_size, length, embedding_size]
, 后面的自然语言处理任务则是根据这个embedding的特征编码进行任务处理,如回归分类等。
,但是我们可以利用BERT可以做很多自然语言处理的很多事情。这里我将会通过两个方向来解释BERT,分别是:
【1】 如何训练我们的BERT模型
【2】如何利用我们的BERT模型进行自然语言处理任务
一、 训练BERT模型
1、 训练方法一: 使用MLM(Masked Language Model)方法
比如上面的一句话 今天 [mask] 玩 DOTA,我们不知道这里的 [mask]究竟指代的是什么,有可能指代的是咱们,有可能是你们,我们希望我们的模型去预测这里的mask, 从图中可以很明显的看出我们在输出embedding
乘上[embedding_size, 单词数量]
的矩阵,再经过一个softmax就可以预测出该字是什么。
如果还是有点迷惑,那我们继续往下面去看。
就是随机遮盖或替换一句话里面任意字或词, 然后让模型通过上下文的理解预测那一个被遮盖或替换的部分, 之后做Loss的时候只计算被遮盖部分的Loss** , 其实是一个很容易理解的任务。
论文中是这样说的我们在输入这句话的时候需要将一句话中15%的 单词进行mask,也就是说不仅仅是这一个 mask,当然在这15%的mask中对于mask的编码有三种方式:
【1】 80%直接将mask统一编码成unknow的编码形式作为模型输入,然后去预测该输出emdedding的单词
【2】10%直接将mask替换成其他的单词编码输入,比如说"小狗",让模型预测其对应的embedding的输出
【3】10%保持不变的方式直接输入到模型中去
这里摘用论文的demo
Masked LM and the Masking Procedure Assuming the unlabeled sentence is my dog is
hairy, and during the random masking procedure
we chose the 4-th token (which corresponding to
hairy), our masking procedure can be further illustrated by
• 80% of the time: Replace the word with the [MASK] token, e.g., my dog is hairy → my dog is [MASK]
• 10% of the time: Replace the word with a random word, e.g., my dog is hairy → my dog is apple
• 10% of the time: Keep the word unchanged, e.g., my dog is hairy → my dog is hairy. The purpose of this is to bias the representation towards the actual observed word.
这里我简要说明一下具体矩阵是怎么计算的。首先在我们进行mask机制之后,让模型预测和还原呗遮盖或替换掉的部分,模型最终输出的隐藏层的计算结果的维度是:
我们初始化一个映射层的权重,
这里的就是字典中字的数量,简单理解就是字典one-hot编码。我们在用完成隐藏维度到子向量数量的映射,只要求和的矩阵进行矩阵乘法(点积)。这样我们就进行如下计算
之后把上面的计算结果在(最后一个维度)做softmax,是每个字对应的的和为1, 我们就可以通过里概率最大的字来得到模型的预测结果,就可以和我们准备好的做损失并反传梯度。注意在损失的时候,值计算句子中随机遮盖或替换的部分,其余部分不做损失,对于其他部分,模型输出什么东西,我们并不在意。
这里这么用的好处总结如下:
1、首先, 如果所有参与训练的token被100%的[MASK], 那么在fine-tunning的时候所有单词都是已知的, 不存在[MASK], 那么模型就只能根据其他token的信息和语序结构来预测当前词, 而无法利用到这个词本身的信息, 因为它们从未出现在训练过程中, 等于模型从未接触到它们的信息, 等于整个语义空间损失了部分信息. 采用80%的概率下应用[MASK], 既可以让模型去学着预测这些单词, 又以20%的概率保留了语义信息展示给模型。
2、保留下来的信息如果全部使用原始token, 那么模型在预训练的时候可能会偷懒, 直接照抄当前token信息. 采用10%概率下random token来随机替换当前token, 会让模型不能去死记硬背当前的token, 而去尽力学习单词周边的语义表达和远距离的信息依赖, 尝试建模完整的语言信息.
3、最后再以10%的概率保留原始的token, 意义就是保留语言本来的面貌, 让信息不至于完全被遮掩, 使得模型可以"看清"真实的语言面貌。
2、 训练方法二: NSP(Next Sentence Prediction)方法
首先我们拿到属于上下文的一对句子, 也就是两个句子, 之后我们要在这两段连续的句子里面加token。
,也就是在句子开头加一个, 在两句话这之中和句子的末尾加, 具体如下图所示。
- 我们看到上图中两句话是 my dog is cute he likes playing , 我的狗很可爱他喜欢玩耍, 除此之外, 我们还要准备同样格式的两句话, 但他们不属于上下文关系的情况;
我的狗很可爱企鹅不擅长飞行, 可见这属于上下句不属于上下文关系的情况; 在实际的训练中, 我们让上面两种情况出现的比例为, 也就是一半的时间输出的文本属于上下文关系, 一半时间不是. - 我们进行完上述步骤之后, 还要随机初始化一个可训练的, 见上图中, 作用就是用的信息让模型分开上下句, 我们一把给上句全的, 下句啊全的, 让模型得以判断上下句的起止位置, 例如:
我的狗很可爱企鹅不擅长飞行
上面和就是. - 还记得我们上节课说过的, 注意力机制就是, 让每句话中的每一个字对应的那一条向量里, 都融入这句话所有字的信息, 那么我们在最终隐藏层的计算结果里, 只要取出所对应的一条向量, 里面就含有整个句子的信息, 因为我们期望这个句子里面所有信息都会往所对应的一条向量里汇总:
模型最终输出的隐藏层的计算结果的维度是:
我们
我们要取出所对应的一条向量, 对应着维度的第条:
之后我们再初始化一个权重, 完成从维度到的映射, 也就是逻辑回归, 之后用函数激活, 就得到了而分类问题的推断。
二、 如何使用BERT模型
1. 实例1
Case1预测出输出的分类,输出句子分类,比如在情感分类我们就可以使用这种BERT模型案例。Linear Classifier是随机初始化的,但是在训练的时候可以让Linear Classifier调节, BERT进行微调就好。
2. 实例2
Case2这里就需要去得到每个词汇是什么词类型,只要我们得出词的embedding, 然后在接上分类网络,我们就可以得出每个词的词类型。
3. 实例3
Case3这里我们输入两个句子输出是表示根据第一句的假设,第二个是进行表示是否第二个句子可以根据第二个句子可以判断。如果可以就是True, 不可以就是False, 不知道就是Unknow。也就是我们之前说的 NSP(Next Sentence Prediction)类型很相似,预测两个句子的关联程度。
4. 实例4
Case4第四个案例其实就是为了解决QA 问题,但是此QA问题中的answer的前提条件就是能在文章中找到。如图中的橘色的weight就是预测出answer start position, 而图中蓝色的weight就是为了预测出answer的end position,后面可以接一个softmax进行分类,这样我们可以得到概率醉大的位置索引。我们就可以根据start position 以及end position的索引得到文章中的索引,但是如果start position小于end position我们可以理解中文章没有结果。
三、 额外补充
3.1 ERNIE
ERNIEERNIE模型是专门针对中文的进行的语言模型,考虑的维度不仅仅是字的维度而是单词的维度。
3.2 BERT不同层所表示的意义
通过上图我们可以看到随着NLP任务难度的加深,BERT越深层的权重越高(重要性),越简单的任务,BERT越浅层的权重越小。(浅层和文本有关,深层和语义有关)
哈哈~ 终于说完了BERT,这里我会提供一个基于BERT进行情感分类的代码,这里的代码有很多注释,可以方便去学习。
code 地址:Semantic Analysis(Pytorch)
网友评论