那么图像领域怎么做预训练呢,上图展示了这个过程,我们设计好网络结构以后,对于图像来说一般是 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 用新数据集合清洗掉高层无关的特征抽取器。
这块大致讲讲 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 后的你们回头再看这个网络甚至显得有些简陋。学习任务是输入某个句中单词前面句子的 t-1 个单词,要求网络正确预测单词 Bert,即最大化:前面任意单词用Onehot编码(比如:0001000)作为原始单词输入,之后乘以矩阵 Q 后获得向量,每个单词的拼接,上接隐层,然后接 softmax 去预测后面应该后续接哪个单词。这个是什么?这其实就是单词对应的 Word Embedding 值,那个矩阵 Q 包含 V 行,V 代表词典大小,每一行内容代表对应单词的 Word embedding 值。只不过 Q 的内容也是网络参数,需要学习获得,训练刚开始用随机值初始化矩阵 Q,当这个网络训练好之后,矩阵 Q 的内容被正确赋值,每一行代表一个单词对应的 Word embedding 值。所以你看,通过这个网络学习语言模型任务,这个网络不仅自己能够根据上文预测后接单词是什么,同时获得一个副产品,就是那个矩阵 Q,这就是单词的 Word Embedding 是被如何学会的。2013 年最火的用语言模型做 Word Embedding 的工具是 Word2Vec,后来又出了 Glove,Word2Vec 是怎么工作的呢?看下图。Word2Vec 的网络结构其实和 NNLM 是基本类似的,只是这个图长得清晰度差了点,看上去不像,其实它们是亲兄弟。不过这里需要指出:尽管网络结构相近,而且也是做语言模型任务,但是其训练方法不太一样。Word2Vec 有两种训练方法,一种叫 CBOW,核心思想是从一个句子里面把一个词抠掉,用这个词的上文和下文去预测被抠掉的这个词;第二种叫做 Skip-gram,和 CBOW 正好反过来,输入某个单词,要求网络预测它的上下文单词。而你回头看看,NNLM 是怎么训练的?是输入一个单词的上文,去预测这个单词。这是有显著差异的。为什么 Word2Vec 这么处理?原因很简单,因为 Word2Vec 和 NNLM 不一样,NNLM 的主要任务是要学习一个解决语言模型任务的网络结构,语言模型就是要看到上文预测下文,而 word embedding 只是无心插柳的一个副产品。但是 Word2Vec 目标不一样,它单纯就是要 word embedding 的,这是主产品,所以它完全可以随性地这么去训练网络。为什么要讲 Word2Vec 呢?这里主要是要引出 CBOW 的训练方法,BERT 其实跟它有关系,后面会讲它们之间是如何的关系,当然它们的关系 BERT 作者没说,是我猜的,至于我猜的对不对,后面你看后自己判断。使用 Word2Vec 或者 Glove,通过做语言模型任务,就可以获得每个单词的 Word Embedding,那么这种方法的效果如何呢?上图给了网上找的几个例子,可以看出有些例子效果还是很不错的,一个单词表达成 Word Embedding 后,很容易找出语义相近的其它词汇。我们的主题是预训练,那么问题是 Word Embedding 这种做法能算是预训练吗?这其实就是标准的预训练过程。要理解这一点要看看学会 Word Embedding 后下游任务是怎么用它的。
假设如上图所示,我们有个 NLP 的下游任务,比如 QA,就是问答问题,所谓问答问题,指的是给定一个问题 X,给定另外一个句子 Y, 要判断句子 Y 是否是问题 X 的正确答案。问答问题假设设计的网络结构如上图所示,这里不展开讲了,懂得自然懂,不懂的也没关系,因为这点对于本文主旨来说不关键,关键是网络如何使用训练好的 Word Embedding 的。它的使用方法其实和前面讲的 NNLM 是一样的,句子中每个单词以 Onehot 形式作为输入,然后乘以学好的 Word Embedding 矩阵 Q,就直接取出单词对应的 Word Embedding 了。这乍看上去好像是个查表操作,不像是预训练的做法是吧?其实不然,那个 Word Embedding 矩阵 Q 其实就是网络 Onehot 层到 embedding 层映射的网络参数矩阵。所以你看到了,使用 Word Embedding 等价于什么?等价于把 Onehot 层到 embedding 层的网络用预训练好的参数矩阵 Q 初始化了。这跟前面讲的图像领域的低层预训练过程其实是一样的,区别无非 Word Embedding 只能初始化第一层网络参数,再高层的参数就无能为力了。下游 NLP 任务在使用 Word Embedding 的时候也类似图像有两种做法:
一种是 Frozen,就是 Word Embedding 那层网络参数固定不动;
另外一种是 Fine-Tuning,就是 Word Embedding 这层参数使用新的训练集合训练也需要跟着训练过程更新掉。
上面这种做法就是 18 年之前 NLP 领域里面采用预训练的典型做法,之前说过,Word Embedding 其实对于很多下游 NLP 任务是有帮助的,只是帮助没有大到闪瞎忘记戴墨镜的围观群众的双眼而已。那么新问题来了,为什么这样训练及使用 Word Embedding 的效果没有期待中那么好呢?答案很简单,因为 Word Embedding 有问题呗。这貌似是个比较弱智的答案,关键是 Word Embedding 存在什么问题?这其实是个好问题。
这片在 Word Embedding 头上笼罩了好几年的乌云是什么?是多义词问题。我们知道,多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现。多义词对 Word Embedding 来说有什么负面影响?如上图所示,比如多义词 Bank,有两个常用含义,但是 Word Embedding 在对 bank 这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过 word2vec,都是预测相同的单词 bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的 word embedding 空间里去。所以 word embedding 无法区分多义词的不同语义,这就是它的一个比较严重的问题。你可能觉得自己很聪明,说这可以解决啊,确实也有很多研究人员提出很多方法试图解决这个问题,但是从今天往回看,这些方法看上去都成本太高或者太繁琐了,有没有简单优美的解决方案呢?ELMO 提供了一种简洁优雅的解决方案。
▌从 Word Embedding 到 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;每个编码器的深度都是两层 LSTM 叠加。这个网络结构其实在 NLP 中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子,句子中每个单词都能得到对应的三个Embedding:最底层是单词的 Word Embedding,往上走是第一层双向 LSTM中对应单词位置的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层 LSTM 中对应单词位置的 Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的 LSTM 网络结构,而这两者后面都有用。
上面介绍的是 ELMO 的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是 QA 问题,此时对于问句 X,我们可以先将句子 X 作为预训练好的 ELMO 网络的输入,这样句子 X 中每个单词在 ELMO 网络中都能获得对应的三个 Embedding,之后给予这三个 Embedding 中的每一个 Embedding 一个权重 a,这个权重可以学习得来,根据各自权重累加求和,将三个 Embedding 整合成一个。然后将整合后的这个 Embedding 作为 X 句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务 QA 中的回答句子 Y 来说也是如此处理。因为 ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。至于为何这么做能够达到区分多义词的效果,你可以想一想,其实比较容易想明白原因。
内容反馈