作者:张俊林
链接:https://zhuanlan.zhihu.com/p/49271699
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Bert最近很火,应该是最近最火爆的AI进展,网上的评价很高,那么Bert值得这么高的评价吗?我个人判断是值得。那为什么会有这么高的评价呢?是因为它有重大的理论或者模型创新吗?其实并没有,从模型创新角度看一般,创新不算大。但是架不住效果太好了,基本刷新了很多NLP的任务的最好性能,有些任务还被刷爆了,这个才是关键。另外一点是Bert具备广泛的通用性,就是说绝大部分NLP任务都可以采用类似的两阶段模式直接去提升效果,这个第二关键。客观的说,把Bert当做最近两年NLP重大进展的集大成者更符合事实。
本文的主题是自然语言处理中的预训练过程,会大致说下NLP中的预训练技术是一步一步如何发展到Bert模型的,从中可以很自然地看到Bert的思路是如何逐渐形成的,Bert的历史沿革是什么,继承了什么,创新了什么,为什么效果那么好,主要原因是什么,以及为何说模型创新不算太大,为何说Bert是近年来NLP重大进展的集大成者。我们一步一步来讲,而串起来这个故事的脉络就是自然语言的预训练过程,但是落脚点还是在Bert身上。要讲自然语言的预训练,得先从图像领域的预训练说起。图像领域的预训练
自从深度学习火起来后,预训练过程就是做图像或者视频领域的一种比较常规的做法,有比较长的历史了,而且这种做法很有效,能明显促进应用的效果。
那么图像领域怎么做预训练呢,上图展示了这个过程,我们设计好网络结构以后,对于图像来说一般是CNN的多层叠加网络结构,可以先用某个训练集合比如训练集合A或者训练集合B对这个网络进行预先训练,在A任务上或者B任务上学会网络参数,然后存起来以备后用。假设我们面临第三个任务C,网络结构采取相同的网络结构,在比较浅的几层CNN结构,网络参数初始化的时候可以加载A任务或者B任务学习好的参数,其它CNN高层参数仍然随机初始化。之后我们用C任务的训练数据来训练网络,此时有两种做法,一种是浅层加载的参数在训练C任务过程中不动,这种方法被称为“Frozen”;另外一种是底层网络参数尽管被初始化了,在C任务训练过程中仍然随着训练的进程不断改变,这种一般叫“Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的C任务。一般图像或者视频领域要做预训练一般都这么做。
这么做有几个好处,首先,如果手头任务C的训练集合数据量较少的话,现阶段的好用的CNN比如Resnet/Densenet/Inception等网络结构层数很深,几百万上千万参数量算起步价,上亿参数的也很常见,训练数据少很难很好地训练这么复杂的网络,但是如果其中大量参数通过大的训练集合比如ImageNet预先训练好直接拿来初始化大部分网络结构参数,然后再用C任务手头比较可怜的数据量上Fine-tuning过程去调整参数让它们更适合解决C任务,那事情就好办多了。这样原先训练不了的任务就能解决了,即使手头任务训练数据也不少,加个预训练过程也能极大加快任务训练的收敛速度,所以这种预训练方式是老少皆宜的解决方案,另外疗效又好,所以在做图像处理领域很快就流行开来。
那么新的问题来了,为什么这种预训练的思路是可行的?
目前我们已经知道,对于层级的CNN结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构,如上图所示,如果我们手头是个人脸识别任务,训练好网络后,把每层神经元学习到的特征可视化肉眼看一看每层学到了啥特征,你会看到最底层的神经元学到的是线段等特征,图示的第二个隐层学到的是人脸五官的轮廓,第三层学到的是人脸的轮廓,通过三步形成了特征的层级结构,越是底层的特征越是所有不论什么领域的图像都会具备的比如边角线弧线等底层基础特征,越往上抽取出的特征越与手头任务相关。正因为此,所以预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,越具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。而高层特征跟任务关联较大,实际可以不用使用,或者采用Fine-tuning用新数据集合清洗掉高层无关的特征抽取器。
一般我们喜欢用ImageNet来做网络的预训练,主要有两点,一方面ImageNet是图像领域里有超多事先标注好训练数据的数据集合,分量足是个很大的优势,量越大训练出的参数越靠谱;另外一方面因为ImageNet有1000类,类别多,算是通用的图像数据,跟领域没太大关系,所以通用性好,预训练完后哪哪都能用,是个万金油。分量足的万金油当然老少通吃,人人喜爱。
听完上述话,如果你是具备研究素质的人,也就是说具备好奇心,你一定会问下面这个问题:”既然图像领域预训练这么好用,那干嘛自然语言处理不做这个事情呢?是不是搞NLP的人比搞CV的傻啊?就算你傻,你看见人家这么做,有样学样不就行了吗?这不就是创新吗,也许能成,万一成了,你看,你的成功来得就是这么突然!”
嗯,好问题,其实搞NLP的人一点都不比你傻,早就有人尝试过了,不过总体而言不太成功而已。听说过word embedding吗?2003年出品,陈年技术,馥郁芳香。word embedding其实就是NLP里的早期预训练技术。当然也不能说word embedding不成功,一般加到下游任务里,都能有1到2个点的性能提升,只是没有那么耀眼的成功而已。
没听过?那下面就把这段陈年老账讲给你听听。 Word Embedding考古史
这块大致讲讲Word Embedding的故事,很粗略,因为网上关于这个技术讲的文章太多了,汗牛冲动,我不属牛,此刻更没有流汗,所以其实丝毫没有想讲Word Embedding的冲动和激情,但是要说预训练又得从这开始,那就粗略地讲讲,主要是引出后面更精彩的部分。在说Word Embedding之前,先更粗略地说下语言模型,因为一般NLP里面做预训练一般的选择是用语言模型任务来做。
什么是语言模型?其实看上面这张PPT上扣下来的图就明白了,为了能够量化地衡量哪个句子更像一句人话,可以设计如上图所示函数,核心函数P的思想是根据句子里面前面的一系列前导单词预测后面跟哪个单词的概率大小(理论上除了上文之外,也可以引入单词的下文联合起来预测单词出现概率)。句子里面每个单词都有个根据上文预测自己的过程,把所有这些单词的产生概率乘起来,数值越大代表这越像一句人话。语言模型压下暂且不表,我隐约预感到我这么讲你可能还是不太会明白,但是大概这个意思,不懂的可以去网上找,资料多得一样地汗牛冲动。
假设现在让你设计一个神经网络结构,去做这个语言模型的任务,就是说给你很多语料做这个事情,训练好一个神经网络,训练好之后,以后输入一句话的前面几个单词,要求这个网络输出后面紧跟的单词应该是哪个,你会怎么做?
你可以像上图这么设计这个网络结构,这其实就是大名鼎鼎的中文人称“神经网络语言模型”,英文小名NNLM的网络结构,用来做语言模型。这个工作有年头了,是个陈年老工作,是Bengio 在2003年发表在JMLR上的论文。它生于2003,火于2013,以后是否会不朽暂且不知,但是不幸的是出生后应该没有引起太大反响,沉寂十年终于时来运转沉冤得雪,在2013年又被NLP考古工作者从海底湿淋淋地捞出来了祭入神殿。为什么会发生这种技术奇遇记?你要想想2013年是什么年头,是深度学习开始渗透NLP领域的光辉时刻,万里长征第一步,而NNLM可以算是南昌起义第一枪。在深度学习火起来之前,极少有人用神经网络做NLP问题,如果你10年前坚持用神经网络做NLP,估计别人会认为你这人神经有问题。所谓红尘滚滚,谁也挡不住历史发展趋势的车轮,这就是个很好的例子。
上面是闲话,闲言碎语不要讲,我们回来讲一讲NNLM的思路。先说训练过程,现在看其实很简单,见过RNN、LSTM、CNN后的你们回头再看这个网络甚至显得有些简陋。学习任务是输入某个句中单词