【NLP】BERT常见问题汇总

本篇文章是在之前文章《【NLP】BERT模型解析记录》的基础上,主要记录BERT模型的相关细节问题,并以QA形式表述。
文中会标注相关出处,如遇未注明或出现错误,请告知。如遇侵权,请告知删除~

1.讲讲bert的结构

bert结构大体上可分为输入N层transformer的encoder输出三部分组成。
输入token embeddingsegment embeddingposition embedding三部分相加组成;
N层transformer的encoder,在bert_base中N=12,bert_large中N=24
输出model.get_sequence_out()model.get_pooling_out()两种输出,其shape分别为[batch_size, seq_length, hidden_size]和[batch_size, hidden_size]。
model.get_sequence_out()输出主要用于特征提取再处理的序列任务,而model.get_pooling_out()输出可直接接softmax进行分类(当然需要外加一层dense层将hidden_size转换为num_tag)。

2.为什么BERT选择mask掉15%这个比例的词,可以是其他的比例吗?

原文链接:https://zhuanlan.zhihu.com/p/132554155
BERT采用的Masked LM,会选取语料中所有词的15%进行随机mask,论文中表示是受到完形填空任务的启发,但其实与CBOW也有异曲同工之妙。

从CBOW的角度,这里15%有一个比较好的解释是:在一个大小为100/157的窗口中随机选一个词,类似CBOW中滑动窗口的中心词,区别是这里的滑动窗口是非重叠的。那从CBOW的滑动窗口角度,10%~20%都是还ok的比例。

3.使用BERT预训练模型为什么最多只能输入512个词,最多只能两个句子合成一句?

原文链接:https://zhuanlan.zhihu.com/p/132554155
这是Google BERT预训练模型初始设置的原因,前者对应Position Embeddings,后者对应Segment Embeddings
在BERT中,Token,Position,Segment Embeddings 都是通过学习来得到的,pytorch代码中它们是这样的

self.word_embeddings = Embedding(config.vocab_size, config.hidden_size)
self.position_embeddings = Embedding(config.max_position_embeddings, > config.hidden_size)
self.token_type_embeddings = Embedding(config.type_vocab_size, config.hidden_size)

上述BERT pytorch代码来自:https://github.com/xieyufei1993/Bert-Pytorch-Chinese-TextClassification,结构层次非常清晰。
而在BERT config中

"max_position_embeddings": 512
"type_vocab_size": 2

因此,在直接使用Google 的BERT预训练模型时,输入最多512个词(还要除掉[CLS]> 和[SEP]),最多两个句子合成一句。这之外的词和句子会没有对应的embedding。

当然,如果有足够的硬件资源自己重新训练BERT,可以更改 BERT config,设置更大max_position_embeddings 和 type_vocab_size值去满足自己的需求。

4.为什么BERT在第一句前会加一个[CLS]标志?

原文链接:https://zhuanlan.zhihu.com/p/132554155
BERT在第一句前会加一个[CLS]标志,最后一层该位对应向量可以作为整句话的语义表示,从而用于下游的分类任务等。

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

具体来说,self-attention是用文本中的其它词来增强目标词的语义表示,但是目标词本身的语义还是会占主要部分的,因此,经过BERT的12层,每次词的embedding融合了所有词的信息,可以去更好的表示自己的语义。

而[CLS]位本身没有语义,经过12层,得到的是attention后所有词的加权平均,相比其他正常词,可以更好的表征句子语义。

当然,也可以通过对最后一层所有词的embedding做pooling去表征句子语义。

5.BERT非线性的来源在哪里?

原文链接:https://zhuanlan.zhihu.com/p/132554155
前馈层的gelu激活函数和self-attention,self-attention是非线性的。

6.BERT的三个Embedding直接相加会对语义有影响吗?

原文链接:https://zhuanlan.zhihu.com/p/132554155
这是一个非常有意思的问题,苏剑林老师也给出了回答,真的很妙啊:
Embedding的数学本质,就是以one hot为输入的单层全连接。
也就是说,世界上本没什么Embedding,有的只是one hot。

在这里想用一个例子再尝试解释一下:
假设 token Embedding 矩阵维度是 [4,768];position Embedding 矩阵维度是 [3,768];segment Embedding 矩阵维度是 [2,768]。
对于一个字,假设它的 token one-hot 是[1,0,0,0];它的 position one-hot 是[1,0,0];它的 segment one-hot 是[1,0]。

那这个字最后的 word Embedding,就是上面三种 Embedding 的加和。
如此得到的 word Embedding,和concat后的特征:[1,0,0,0,1,0,0,1,0],再过维度为 [4+3+2,768] = [9, 768] 的全连接层,得到的向量其实就是一样的。

再换一个角度理解:
直接将三个one-hot 特征 concat 起来得到的 [1,0,0,0,1,0,0,1,0] 不再是one-hot了,但可以把它映射到三个one-hot 组成的特征空间,空间维度是 432=24 ,那在新的特征空间,这个字的one-hot就是[1,0,0,0,0...] (23个0)。

此时,Embedding 矩阵维度就是 [24,768],最后得到的 word Embedding 依然是和上面的等效,但是三个小Embedding 矩阵的大小会远小于新特征空间对应的Embedding 矩阵大小。

当然,在相同初始化方法前提下,两种方式得到的 word Embedding 可能方差会有差别,但是,BERT还有Layer Norm,会把 Embedding 结果统一到相同的分布。

BERT的三个Embedding相加,本质可以看作一个特征的融合,强大如 BERT 应该可以学到融合后特征的语义信息的。

参考:https://www.zhihu.com/question/374835153

7.什么任务适合bert,什么任务不适合?

bert适合于自然语言理解(Natural language Understanding, NLU)类任务,如文本分类、信息抽取等;
bert不适合于自然语言生成(Natural language Generation, NLG)类任务。

因为bert采用的是双向的语言模型,除了被mask的词语外,该词语前后的词语都可以看到。
而NLG任务的目标是在已知当前词与之前词语的情况下,预测出下一个词语,直至所有词语预测完成。

8.为什么 BERT 比 ELMo 效果好?

原文链接:https://cloud.tencent.com/developer/article/1687276
从网络结构以及最后的实验效果来看,BERT 比 ELMo 效果好主要集中在以下几点原因:

  • LSTM抽取特征的能力远弱于Transformer
  • 拼接方式双向融合的特征融合能力偏弱(没有具体实验验证,只是推测)
  • 其实还有一点,BERT 的训练数据以及模型参数均多余 ELMo,这也是比较重要的一点。

9.ELMo 和 BERT 的区别是什么?

原文链接:https://cloud.tencent.com/developer/article/1687276
ELMo 模型是通过语言模型任务得到句子中单词的 embedding 表示,以此作为补充的新特征给下游任务使用。因为 ELMO 给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。
而 BERT 模型是“基于 Fine-tuning 的模式”,这种做法和图像领域基于 Fine-tuning 的方式基本一致,下游任务需要将模型改造成 BERT 模型,才可利用 BERT 模型预训练好的参数。

你可能感兴趣的:(【NLP】BERT常见问题汇总)