# 好久没更新博客了,有时候随手在本上写写,或者Evernote上记记,零零散散的笔记带来零零散散的记忆o(╥﹏╥)o。。还是整理到博客上比较有整体性,也方便查阅~
自google在2018年10月底公布BERT在11项nlp任务中的卓越表现后,BERT(Bidirectional Encoder Representation from Transformers)就成为NLP领域大火、整个ML界略有耳闻的模型,网上相关介绍也很多,但很多技术内容太少,或是写的不全面半懂不懂,重复内容占绝大多数(这里弱弱吐槽百度的搜索结果多样化。。)
一句话概括,BERT的出现,彻底改变了预训练产生词向量和下游具体NLP任务的关系,提出龙骨级的训练词向量概念。
目录:
- 词向量模型:word2vec, ELMo, BERT比较
- BERT细则:Masked LM, Transformer, sentence-level
- 迁移策略:下游NLP任务调用接口
- 运行结果:破11项NLP任务最优纪录
一、词向量模型
这里主要横向比较一下word2vec,ELMo,BERT这三个模型,着眼在模型亮点与差别处。
传统意义上来讲,词向量模型是一个工具,可以把真实世界抽象存在的文字转换成可以进行数学公式操作的向量,而对这些向量的操作,才是NLP真正要做的任务。因而某种意义上,NLP任务分成两部分,预训练产生词向量,对词向量操作(下游具体NLP任务)。
从word2vec到ELMo到BERT,做的其实主要是把下游具体NLP任务的活逐渐移到预训练产生词向量上。下面是一个大体概括,具体解释后面会写到。。
word2vec——>ELMo:
结果:上下文无关的static向量变成上下文相关的dynamic向量,比如苹果在不同语境vector不同。
操作:encoder操作转移到预训练产生词向量过程实现。
ELMo——>BERT:
结果:训练出的word-level向量变成sentence-level的向量,下游具体NLP任务调用更方便,修正了ELMo模型的潜在问题,。
操作:使用句子级负采样获得句子表示/句对关系,Transformer模型代替LSTM提升表达和时间上的效率,masked LM解决“自己看到自己”的问题。
1. word2vec
# 反正一直以来用的这个,感觉方便有效率,后来才知道too young。。。
线性模型:
很神奇的地方,从而也说明高维空间映射的词向量可以很好体现真实世界中token之间的关系。如:king-man = queen-woman
负采样:
由于训练词向量模型的目标不是为了得到一个多么精准的语言模型,而是为了获得它的副产物——词向量。所以要做到的不是在几万几十万个token中艰难计算softmax获得最优的那个词(就是预测的对于给定词的下一词),而只需能做到在几个词中找到对的那个词就行,这几个词包括一个正例(即直接给定的下一词),和随机产生的噪声词(采样抽取的几个负例),就是说训练一个sigmoid二分类器,只要模型能够从中找出正确的词就认为完成任务。
这种负采样思想也应用到之后的BERT里,只不过从word-level变成sentence-level,这样能获取句子间关联关系。
缺点是上下文无关(static):
因而为了让句子有一个整体含义(context),大家会在下游具体的NLP任务中基与词向量的序列做encoding操作。
下面是一个比较表格,模型不细讲了,预测目标这里的next word下一个词,是所有传统语言模型都做的事——寻找下一个词填什么。

2. ELMo
# 10月份初做一个任务还被建议使用ELMo提升模型效率,但后来可能哪里没调好导致运行时间很长,所以放弃了。。。
ELmo模型是AllenNLP在2018年8月发布的一个上下文无关模型,甚至在9月10月BERT没出来时,也小火了一把。但据说使用时很慢效率很低,再加上马上就提出的强势BERT,ELMo很快就被人们忘掉了。。。但BERT的提出,算是对ELMo的致敬,硬是凑了一个和ELMo一个动画片里的角色名。。。(下面左图,红色的是ELMo,右二是BERT)
这里介绍ELMo的两方面,一个是它的encoder模型Bi-LSTM,另一个是它和下游具体NLP任务的接口(迁移策略)。
Bi-LSTM做encoder实现上下文相关(context):
这里就是之前说的把下游具体NLP任务放到预训练产生词向量里面,从而达到获得一个根据context不同不断变化的dynamic词向量。具体实现方法是使用双向语言模型(BiLM)Bi-LSTM来实现,如下面左图所示。从前到后和后到前分别做一遍LSTM的encoding操作,从而获得两个方向的token联系,进而获得句子的context。
但这里有两个潜在问题,姑且称作“不完全双向”和“自己看见自己”。
首先,“不完全双向”是指模型的前向和后向LSTM两个模型是分别训练的,从图中也可以看出,对于一个序列,前向遍历一遍获得左边的LSTM,后向遍历一遍获得右边的LSTM,最后得到的隐层向量直接拼接得到结果向量(前向的hidden state1 + 后向的hidden state2 = 总的hidden state,+是concat),并且在最后的Loss function中也是前向和后向的loss function直接相加,并非完全同时的双向计算。
另外,“自己看见自己”是指要预测的下一个词在给定的序列中已经出现的情况。传统语言模型的数学原理决定了它的单向性。从公式
可以看出,传统语言模型的目标是获得在给定序列从头到尾条件概率相乘后概率最大的下一词,而双向模型会导致预测的下一词已经在给定序列中出现了的问题,这就是“自己看见自己”。如下面右图所示(图片从下往上看),最下行是训练数据A B C D,经过两个bi-lstm操作,需要预测某个词位置的内容。比如第二行第二列A|CD这个结果是第一层bi-lstm在B位置输出内容,包括正向A和反向CD,直接拼接成A|CD。比如第三行第二例ABCD这个结果是前向BCD和反向AB|D拼接结果,而当前位置需要预测的是B,已经在ABCD中出现了,这就会有问题。因而
