1. 图像领域的预训练
我们设计好网络结构以后,对于图像来说一般是 CNN 的多层叠加网络结构,可以先用某个训练集合比如训练集合 A 或者训练集合 B 对这个网络进行预先训练,在 A 任务上或者 B 任务上学会网络参数,然后存起来以备后用。假设我们面临第三个任务 C,网络结构采取相同的网络结构,在比较浅的几层 CNN 结构,网络参数初始化的时候可以加载 A 任务或者 B 任务学习好的参数,其它 CNN 高层参数仍然随机初始化。之后我们用 C 任务的训练数据来训练网络,此时有两种做法,一种是浅层加载的参数在训练 C 任务过程中不动,这种方法被称为 “Frozen”; 另外一种是底层网络参数尽管被初始化了,在 C 任务训练过程中仍然随着训练的进程不断改变,这种一般叫 “Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的 C 任务。
--- 已知任务训好模型,在未知任务C上再训练,A. 浅层 frozen,高层train B.load model,整体fine-tuning
对于层级的 CNN 结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构,如上图所示,如果我们手头是个人脸识别任务,训练好网络后,把每层神经元学习到的特征可视化肉眼看一看每层学到了啥特征,你会看到最底层的神经元学到的是线段等特征,图示的第二个隐层学到的是人脸五官的轮廓,第三层学到的是人脸的轮廓,通过三步形成了特征的层级结构,越是底层的特征越是所有不论什么领域的图像都会具备的比如边角线弧线等底层基础特征,越往上抽取出的特征越与手头任务相关。正因为此,所以预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,越具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。而高层特征跟任务关联较大,实际可以不用使用,或者采用 Fine-tuning 用新数据集合清洗掉高层无关的特征抽取器。
--- 对CNN来说,底层越通用,高层 跟任务相关联,所以要新数据慢慢更新高层网络
2. nnlm
学习任务是输入某个句中单词
前面句子的 t-1 个单词,要求网络正确预测单词 Bert,即最大化:
前面任意单词
用 Onehot 编码(比如:0001000)作为原始单词输入,之后乘以矩阵 Q 后获得向量
,每个单词的
拼接,上接隐层,然后接 softmax 去预测后面应该后续接哪个单词。这个
是什么?这其实就是单词对应的 Word Embedding 值,那个矩阵 Q 包含 V 行,V 代表词典大小,每一行内容代表对应单词的 Word embedding 值。只不过 Q 的内容也是网络参数,需要学习获得,训练刚开始用随机值初始化矩阵 Q,当这个网络训练好之后,矩阵 Q 的内容被正确赋值,每一行代表一个单词对应的 Word embedding 值。所以你看,通过这个网络学习语言模型任务,这个网络不仅自己能够根据上文预测后接单词是什么,同时获得一个副产品,就是那个矩阵 Q,这就是单词的 Word Embedding 是被如何学会的。
--- nnlm 学习当前词,输入历史词。第一个线性层对one-hot编码变换,得到word embedding
3.Word2Vec
Word2Vec 的网络结构其实和 NNLM 是基本类似的,只是这个图长得清晰度差了点,看上去不像,其实它们是亲兄弟。不过这里需要指出:尽管网络结构相近,而且也是做语言模型任务,但是其训练方法不太一样。Word2Vec 有两种训练方法,一种叫 CBOW,核心思想是从一个句子里面把一个词抠掉,用这个词的上文和下文去预测被抠掉的这个词;第二种叫做 Skip-gram,和 CBOW 正好反过来,输入某个单词,要求网络预测它的上下文单词。而你回头看看,NNLM 是怎么训练的?是输入一个单词的上文,去预测这个单词。这是有显著差异的。为什么 Word2Vec 这么处理?原因很简单,因为 Word2Vec 和 NNLM 不一样,NNLM 的主要任务是要学习一个解决语言模型任务的网络结构,语言模型就是要看到上文预测下文,而 word embedding 只是无心插柳的一个副产品。但是 Word2Vec 目标不一样,它单纯就是要 word embedding 的,这是主产品,所以它完全可以随性地这么去训练网络。
--- Word2Vec只是为了得到word embedding,作用类似nnlm 的第一个线性层。训练: A. 输入这个词的历史和未来,学习这个词。 B. 输入这个词,学习这个词的历史和未来。
4.以前nlp 使用word embedding
使用 Word Embedding 等价于什么?等价于把 Onehot 层到 embedding 层的网络用预训练好的参数矩阵 Q 初始化了。这跟前面讲的图像领域的低层预训练过程其实是一样的,区别无非 Word Embedding 只能初始化第一层网络参数,再高层的参数就无能为力了。下游 NLP 任务在使用 Word Embedding 的时候也类似图像有两种做法,一种是 Frozen,就是 Word Embedding 那层网络参数固定不动;另外一种是 Fine-Tuning,就是 Word Embedding 这层参数使用新的训练集合训练也需要跟着训练过程更新掉。
--- 下游NLP任务使用we,网络输入的是每个词的onehot乘上矩阵Q得到we。使用we预训练 ,类似图像预训练的做法。
5. Word Embedding 存在什么问题
这片在 Word Embedding 头上笼罩了好几年的乌云是什么?是多义词问题。我们知道,多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现。多义词对 Word Embedding 来说有什么负面影响?如上图所示,比如多义词 Bank,有两个常用含义,但是 Word Embedding 在对 bank 这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过 word2vec,都是预测相同的单词 bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的 word embedding 空间里去。所以 word embedding 无法区分多义词的不同语义,这就是它的一个比较严重的问题。
--- we存在多义词问题,同一个词在不同的语句中含义可能不一样的,但是得到的we却是一样的,这就有问题了。
6.ELMO
ELMO 是 “Embedding from Language Models” 的简称,其实这个名字并没有反应它的本质思想,提出 ELMO 的论文题目:“Deep contextualized word representation” 更能体现其精髓,而精髓在哪里?在 deep contextualized 这个短语,一个是 deep,一个是 context,其中 context 更关键。在此之前的 Word Embedding 本质上是个静态的方式,所谓静态指的是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的 Word Embedding 不会跟着上下文场景的变化而改变,所以对于比如 Bank 这个词,它事先学好的 Word Embedding 中混合了几种语义 ,在应用中来了个新句子,即使从上下文中(比如句子包含 money 等词)明显可以看出它代表的是 “银行” 的含义,但是对应的 Word Embedding 内容也不会变,它还是混合了多种语义。这是为何说它是静态的,这也是问题所在。ELMO 的本质思想是:我事先用语言模型学好一个单词的 Word Embedding,此时多义词无法区分,不过这没关系。在我实际使用 Word Embedding 的时候,单词已经具备了特定的上下文了,这个时候我可以根据上下文单词的语义去调整单词的 Word Embedding 表示,这样经过调整后的 Word Embedding 更能表达在这个上下文中的具体含义,自然也就解决了多义词的问题了。所以 ELMO 本身是个根据当前上下文对 Word Embedding 动态调整的思路。
ELMO 采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的 Word Embedding 作为新特征补充到下游任务中。上图展示的是其预训练过程,它的网络结构采用了双层双向 LSTM,目前语言模型训练的任务目标是根据单词
的上下文去正确预测单词
,
之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。图中左端的前向双层 LSTM 代表正方向编码器,输入的是从左到右顺序的除了预测单词外
的上文 Context-before;右端的逆向双层 LSTM 代表反方向编码器,输入的是从右到左的逆序的句子下文 Context-after; 左端的编码器的输入为当前单词的 WordEmbedding 以及上文,而没有下文。右端编码器输入当前单词的 WordEmbedding 以及下文。最后然后将当前单词的 embedding 以及上文和下文信息拼接在一起。 每个编码器的深度都是两层 LSTM 叠加。这个网络结构其实在 NLP 中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子
,句子中每个单词都能得到对应的三个 Embedding: 最底层是单词的 Word Embedding,往上走是第一层双向 LSTM 中对应单词位置的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层 LSTM 中对应单词位置的 Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的 LSTM 网络结构,而这两者后面都有用。
--- 一个词得到 3个we,第一个还是跟以前we类似,另两个是过了双向lstm的we,有未来信息了。
上面介绍的是 ELMO 的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是 QA 问题,此时对于问句 X,我们可以先将句子 X 作为预训练好的 ELMO 网络的输入,这样句子 X 中每个单词在 ELMO 网络中都能获得对应的三个 Embedding,之后给予这三个 Embedding 中的每一个 Embedding 一个权重 a,这个权重可以学习得来,根据各自权重累加求和,将三个 Embedding 整合成一个。然后将整合后的这个 Embedding 作为 X 句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务 QA 中的回答句子 Y 来说也是如此处理。因为 ELMO 给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为 “Feature-based Pre-Training”。至于为何这么做能够达到区分多义词的效果,你可以想一想,其实比较容易想明白原因。
--- 为啥elmo的词向量能区分多义词?因为有3个we,第一个还是以前的那种,另两个we过了双向lstm,包含了整句信息,所以能够区分多义词
--- elmo怎么使用,3个we加权,到网络里的单词的输入。权重可以学习。
前面我们提到静态 Word Embedding 无法解决多义词的问题,那么 ELMO 引入上下文动态调整单词的 embedding 后多义词问题解决了吗?解决了,而且比我们期待的解决得还要好。上图给了个例子,对于 Glove 训练出的 Word Embedding 来说,多义词比如 play,根据它的 embedding 找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含 play 的句子中体育领域的数量明显占优导致;而使用 ELMO,根据上下文动态调整后的 embedding 不仅能够找出对应的 “演出” 的相同语义的句子,而且还可以保证找出的句子中的 play 对应的词性也是相同的,这是超出期待之处。之所以会这样,是因为我们上面提到过,第一层 LSTM 编码了很多句法信息,这在这里起到了重要作用。
ELMO 经过这般操作,效果如何呢?实验效果见上图,6 个 NLP 任务中性能都有幅度不同的提升,最高的提升达到 25% 左右,而且这 6 个任务的覆盖范围比较广,包含句子语义关系判断,分类任务,阅读理解等多个领域,这说明其适用范围是非常广的,普适性强,这是一个非常好的优点。
那么站在现在这个时间节点看,ELMO 有什么值得改进的缺点呢?首先,一个非常明显的缺点在特征抽取器选择方面,ELMO 使用了 LSTM 而不是新贵 Transformer,Transformer 是谷歌在 17 年做机器翻译任务的 “Attention is all you need” 的论文中提出的,引起了相当大的反响,很多研究已经证明了 Transformer 提取特征的能力是要远强于 LSTM 的。如果 ELMO 采取 Transformer 作为特征提取器,那么估计 Bert 的反响远不如现在的这种火爆场面。另外一点,ELMO 采取双向拼接这种融合特征的能力可能比 Bert 一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。
我们如果把 ELMO 这种预训练方法和图像领域的预训练方法对比,发现两者模式看上去还是有很大差异的。除了以 ELMO 为代表的这种基于特征融合的预训练方法外,NLP 里还有一种典型做法,这种做法和图像领域的方式就是看上去一致的了,一般将这种方法称为 “基于 Fine-tuning 的模式”,而 GPT 就是这一模式的典型开创者。
--- ELMO 没用transformer
7. GPT
GPT 是 “Generative Pre-Training” 的简称,从名字看其含义是指的生成式的预训练。GPT 也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过 Fine-tuning 的模式解决下游任务。上图展示了 GPT 的预训练过程,其实和 ELMO 是类似的,主要不同在于两点:首先,特征抽取器不是用的 RNN,而是用的 Transformer,上面提到过它的特征抽取能力要强于 RNN,这个选择很明显是很明智的;其次,GPT 的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,所谓 “单向” 的含义是指:语言模型训练的任务目标是根据
单词的上下文去正确预测单词
,
之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。ELMO 在做语言模型预训练的时候,预测单词
同时使用了上文和下文,而 GPT 则只采用 Context-before 这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。如果预训练时候不把单词的下文嵌入到 Word Embedding 中,是很吃亏的,白白丢掉了很多信息。
--- GPT 用了transformer 当作特征抽取器 代替了ELMO的lstm。没有做双向,只是单向,没有未来信息。
上面讲的是 GPT 如何进行第一阶段的预训练,那么假设预训练好了网络模型,后面下游任务怎么用?它有自己的个性,和 ELMO 的方式大有不同。
上图展示了 GPT 在第二阶段如何使用。首先,对于不同的下游任务来说,本来你可以任意设计自己的网络结构,现在不行了,你要向 GPT 的网络结构看齐,把任务的网络结构改造成和 GPT 的网络结构是一样的。然后,在做下游任务的时候,利用第一步预训练好的参数初始化 GPT 的网络结构,这样通过预训练学到的语言学知识就被引入到你手头的任务里来了,这是个非常好的事情。再次,你可以用手头的任务去训练这个网络,对网络参数进行 Fine-tuning,使得这个网络更适合解决手头的问题。就是这样。看到了么?这有没有让你想起最开始提到的图像领域如何做预训练的过程(请参考上图那句非常容易暴露年龄的歌词)?对,这跟那个模式是一模一样的。
--- GPT怎么使用,输入we的部分改成gpt网络,load model,fine-tuning
这里引入了一个新问题:对于 NLP 各种花样的不同任务,怎么改造才能靠近 GPT 的网络结构呢?
GPT 论文给了一个改造施工图如上,其实也很简单:
对于分类问题,不用怎么动,加上一个起始和终结符号即可;
对于句子关系判断问题,比如 Entailment,两个句子中间再加个分隔符即可;
对文本相似性判断问题,把两个句子顺序颠倒下做出两个输入即可,这是为了告诉模型句子顺序不重要;
对于多项选择问题,则多路输入,每一路把文章和答案选项拼接作为输入即可。从上图可看出,这种改造还是很方便的,不同任务只需要在输入部分施工即可。
GPT 的效果是非常令人惊艳的,在 12 个任务里,9 个达到了最好的效果,有些任务性能提升非常明显。
8.BERT
我们经过跋山涉水,终于到了目的地 Bert 模型了。
Bert 采用和 GPT 完全相同的两阶段模型,首先是语言模型预训练;其次是使用 Fine-Tuning 模式解决下游任务。和 GPT 的最主要不同在于在预训练阶段采用了类似 ELMO 的双向语言模型,当然另外一点是语言模型的数据规模要比 GPT 大。所以这里 Bert 的预训练过程不必多讲了。
第二阶段,Fine-Tuning 阶段,这个阶段的做法和 GPT 是一样的。当然,它也面临着下游任务网络结构改造的问题,在改造任务方面 Bert 和 GPT 有些不同,下面简单介绍一下。
在介绍 Bert 如何改造下游任务之前,先大致说下 NLP 的几类问题,说这个是为了强调 Bert 的普适性有多强。通常而言,绝大部分 NLP 问题可以归入上图所示的四类任务中:
一类是序列标注,这是最典型的 NLP 任务,比如中文分词,词性标注,命名实体识别,语义角色标注等都可以归入这一类问题,它的特点是句子中每个单词要求模型根据上下文都要给出一个分类类别。
第二类是分类任务,比如我们常见的文本分类,情感计算等都可以归入这一类。它的特点是不管文章有多长,总体给出一个分类类别即可。
第三类任务是句子关系判断,比如 Entailment,QA,语义改写,自然语言推理等任务都是这个模式,它的特点是给定两个句子,模型判断出两个句子是否具备某种语义关系;
第四类是生成式任务,比如机器翻译,文本摘要,写诗造句,看图说话等都属于这一类。它的特点是输入文本内容后,需要自主生成另外一段文字。
对于种类如此繁多而且各具特点的下游 NLP 任务,Bert 如何改造输入输出部分使得大部分 NLP 任务都可以使用 Bert 预训练好的模型参数呢?上图给出示例:
对于句子关系类任务,很简单,和 GPT 类似,加上一个起始和终结符号,句子之间加个分隔符即可。对于输出来说,把第一个起始符号对应的 Transformer 最后一层位置上面串接一个 softmax 分类层即可。
对于分类问题,与 GPT 一样,只需要增加起始和终结符号,输出部分和句子关系判断任务类似改造;
对于序列标注问题,输入部分和单句分类是一样的,只需要输出部分 Transformer 最后一层每个单词对应位置都进行分类即可。从
这里可以看出,上面列出的 NLP 四大任务里面,除了生成类任务外,Bert 其它都覆盖到了,而且改造起来很简单直观。尽管 Bert 论文没有提,但是稍微动动脑子就可以想到,其实对于机器翻译或者文本摘要,聊天机器人这种生成式任务,同样可以稍作改造即可引入 Bert 的预训练成果。只需要附着在 S2S 结构上,encoder 部分是个深度 Transformer 结构,decoder 部分也是个深度 Transformer 结构。根据任务选择不同的预训练数据初始化 encoder 和 decoder 即可。这是相当直观的一种改造方法。当然,也可以更简单一点,比如直接在单个 Transformer 结构上加装隐层产生输出也是可以的。不论如何,从这里可以看出,NLP 四大类任务都可以比较方便地改造成 Bert 能够接受的方式。这其实是 Bert 的非常大的优点,这意味着它几乎可以做任何 NLP 的下游任务,具备普适性,这是很强的。
Bert 采用这种两阶段方式解决各种 NLP 任务效果如何?在 11 个各种类型的 NLP 任务中达到目前最好的效果,某些任务性能有极大的提升。一个新模型好不好,效果才是王道。
到这里我们可以再梳理下几个模型之间的演进关系。从上图可见,Bert 其实和 ELMO 及 GPT 存在千丝万缕的关系,比如如果我们把 GPT 预训练阶段换成双向语言模型,那么就得到了 Bert;而如果我们把 ELMO 的特征抽取器换成 Transformer,那么我们也会得到 Bert。所以你可以看出:Bert 最关键两点,一点是特征抽取器采用 Transformer;第二点是预训练的时候采用双向语言模型。
那么新问题来了:对于 Transformer 来说,怎么才能在这个结构上做双向语言模型任务呢?乍一看上去好像不太好搞。我觉得吧,其实有一种很直观的思路,怎么办?看看 ELMO 的网络结构图,只需要把两个 LSTM 替换成两个 Transformer,一个负责正向,一个负责反向特征提取,其实应该就可以。当然这是我自己的改造,Bert 没这么做。那么 Bert 是怎么做的呢?我们前面不是提过 Word2Vec 吗?我前面肯定不是漫无目的地提到它,提它是为了在这里引出那个 CBOW 训练方法,所谓写作时候埋伏笔的 “草蛇灰线,伏脉千里”,大概就是这个意思吧?前面提到了 CBOW 方法,它的核心思想是:在做语言模型任务的时候,我把要预测的单词抠掉,然后根据它的上文 Context-Before 和下文 Context-after 去预测单词。其实 Bert 怎么做的?Bert 就是这么做的。从这里可以看到方法间的继承关系。当然 Bert 作者没提 Word2Vec 及 CBOW 方法,这是我的判断,Bert 作者说是受到完形填空任务的启发,这也很可能,但是我觉得他们要是没想到过 CBOW 估计是不太可能的。
从这里可以看出,在文章开始我说过 Bert 在模型方面其实没有太大创新,更像一个最近几年 NLP 重要技术的集大成者,原因在于此,当然我不确定你怎么看,是否认同这种看法,而且我也不关心你怎么看。其实 Bert 本身的效果好和普适性强才是最大的亮点。