NLP 表征的历史与未来

从 Ngram 这样最简单的 SLM(Statistical Language Model)和 OneHot、LSA 以及其他 Co-Occurrence 的 VSM 模型,到 Word2Vec Glove 等考虑简单上下文的词向量模型,再到 CNN RNN BI-LSTM 等更多上下文和更复杂结构的模型,再到基于 Self-Attention 的 Bert 等考虑注意力的模型。我们能够感觉到每一次的变革一定是某种 ”模式“ 层面发生了变化。

历史

词向量之前的模型结构简单,表征能力弱,想法都非常的直接,甚至可以说是简单粗暴。偏偏有时候这种简单粗暴的方法也还很有效,比如文档分类,再比如语义消歧、输入法的词推荐、纠错等。但计算机不太好对词和句子进行表征,这就导致使用有局限。

词向量

2013 年的 Word2Vec 是一个突破,它首次同时考虑了上下文且将文本进行了高维稠密表征。这虽然导致我们不知道表征到底是啥意思,但不影响我们拿来做一些简单应用,比如基于同义词的 query 扩展、纠错等。此时其实已经可以采用简单的拼接或平均方法来对句子进行表征了,只是效果不太好。因为前者导致数据维度太大,后者会丢失掉句子间的前后关系。所以,那时候虽然 Word2Vec 满天飞,但工业界真正能用的地方并不多,基本也就是 “巴黎+法国-北京=中国” 这样的应用。FaceBook 的 FastText 的分类模型用的就是词向量平均,而且使用了子词用以解决未登录词问题。这里需要插一句,为啥句子的表征比较重要,因为我们日常生活中的基本 “语义单位” 其实并不是 “词”,而是 “句”,也就是说,自然语言理解,其实最小的单位是句子,所以 “词” 搞得再准确,上下文一变,马上就没意义了。所以 Glove 聪(鸡)明(贼)地给词向量加入了外部知识。

CNN

CNN 的应用是革命性的,让我们先膜拜一下 Yann LeCun 大佬(三巨头最喜欢他,看起来很是慈祥呢)。图像领域自不必说,可以说是开启了一个新时代,就连 NLP 领域又有人 “聪明” 地将其拉过来用上了,于是 TextCNN 问世,首次将 “句子” 以一种很 Make Sense 的方法表征了出来,甚至直到今天,依然备受工业界青睐,也常被用来作为 BaseLine。大佬应该膜拜的差不多了,我们想想为什么它就有效?形象地来看,和 CNN 一样,TextCNN 可以看成是一个滑块(扫描器)滑过句子,然后依次记住(Pooling)每个局部信息(Max 或 Average),是不是很 Make Sense。你甚至可能马上就想到要用 Word2Vec(也许就是 Glove)的预训练 + TextCNN 做 FineTune,以此引入外部信息提升效果。不过这里又要插一句,CNN 可是大佬在 20 世纪 80 年代提出来的,为啥直到 2010 年以后经过多场比赛检验后才得以被大家熟悉呢?这里除了算法层面的 “反向传播” 外就要归功于 GPU 的成功应用了,GPU 可以让模型更深更宽,进而学习到更抽象更丰富的特征。

RNN

RNN 也是 20 世纪 80 年代提出来的,GPU 的广泛使用后,RNN 作为一种时间序列模型自然会被拉出来遛。RNN 类似于语言的生成过程,所以一开始被用来做 NLG,遥想几年前,GitHub 上突然就充斥这各种魔改的吐字生成器,吐散文的、吐小说的、吐诗歌的……无良的媒体天天吹水能写小说,要替代这个替代那个,结果现在也没当年吹的那么好用。作为序列模型,RNN 每往前移动一个 Token,都会依赖之前的 Context,所以当移动到最后一个 Token 时,得到的向量天然就是整句的表征。而且 RNN 相比 CNN 有个优势:它可以捕捉到整句的长依赖以及前后顺序信息,CNN 由于 Kernal 的存在,一般获得的都是多个局部信息。但是 RNN 的劣势更加明显:太长的依赖容易导致梯度消失或爆炸,这主要是由于反向传播传递的放大效应,和经济学中的 “牛鞭效应” 有异曲同工之妙;而且 RNN 没法并行,因为它是一个一个吐过去的;另外,RNN 还有语义偏移的问题,也就是越后面的 Token 会显得越重要。后面的 LSTM 和 GRU 都是对它的优化,甚至还有 Bi-系列充分考虑前面和后面的 Context。RNN 系列被充分运用到 Token 级别的任务上,相比整体的表征而言,这里显然才是它大展身手的地方,直到今天,Bi-LSTM + CRF 依然是 Token 级任务的标准方法。所以,我们开篇把 CNN 和 RNN 系列放一块,就是因为它们几乎处于同一时期,且侧重于不同的角度。如果单纯从表征句子的角度看,直觉上 CNN 也要优于 RNN。不信话的你看,从整体角度的看,序顺貌似没么那重要。

BERT 系列

2017 年 Transformer 横空出世,又一个革命性的时代来临。它的思想来源于 14、15 年的 Encoder-Decoder 架构之间的 Attention(Bahdanau 和 Luong),我在这里有比较深入的分析,直观上看,可以理解为对不同位置的 Token 给予不同的权重(即所谓的注意力)。如果说 CNN 的灵感来自人眼看东西的 “扫描”,RNN 来自人讲话的方式,那么 Self-Attention 就是人大脑关注的 “信息”。如果从这个角度看,词向量更像是一种 “局部记忆”。显然,每种模型背后都可以对应到人类的某种认知模式,从简单到复杂,从初级到高级。模式的更新,往往意味着新模型的出现,也同时意味着新时代的来临。2018 年,基于 Transformer Encoder 架构的 Bert 一出现就上天(Google 会宣传也很重要),当然 Bert 的创新还有 MLM 和 CLS,前者是用遮盖的方式取巧地利用了上下文信息,后者则是可以直接拿来表征整个句子。Bert 之后至今出现的一系列 Bert 系列基本都是修修补补,或者各种脑洞创新,并没有在模式上取得新的突破。即便是目前大火的知识图谱也只不过是去借助更多的外部信息,这种方法都成套路了。又要插一句,我个人觉得 Bert 的架构是相对比较简洁的,不过后面出来的系列里总有一些把它搞复杂的,兄弟这是浪费生命啊。说回老套路,虽然模式上没有创新,但由于加入了关系推理、实体链接、领域和意图识别等内容,如今的 NLP 处理流程已经越来越向人类真实的思考过程靠近了。试想,我们思考时,不也是从 Input 中 get 到一些关键信息(比如实体、意图,或者提前知道意图和领域),然后在大脑中完成知识链接和推理的吗。

未来

到这一步了,我们很自然想开开脑洞,展望一下未来的可能在哪里。

特别声明:一家之言,不一定准确,甚至有可能由于自己所知有限导致展望的东西现在已经很成熟了(希望不会如此,不然就尴尬了),因此有任何不当之处,还望不吝批评指正。

认知角度

短期来看,从认知的角度,我们首先需要的可能是多维度的感知。人类在理解语言时,除了文字本身,音调音高、面部表情、肢体语言甚至周围的环境等都可能在辅助性地表达语义。其实目前已经有不少相关工作了,只是还不够广泛,也没有(难有)一个很好的通用模型去覆盖掉这么多内容。然后可能需要一些 “规则”,这些规则可以理解为一种导向(以及长期看的 “进化”),比如最省力法则——人倾向于使用最简单的方式做出反馈。这里面有控制理论、强化学习和对抗学习的影子,规则可以塑造 AI 的 “性格”。Bengio 在 AAAI 2020 上也有类似的观点。最后,我们应该对系统分层。在之前分析分类的文章里我们已经比较深入的分析过,分层是分类(人类认识和了解这个世界的基本方法,本能)到一定阶段后自然的产物。分层其实就是抽象,而抽象也是智能的体现。这在西蒙的《人工智能》中有提及,具体可参考这里

哲学角度

长期来看,从哲学的角度,我们可能需要重新界定何为理解,何为语言。理解是否一定需要语言的参与?语言又是否能真正表达出想要的意义?谈到这里不得不提的一个人就是维特根斯坦。在早期的《逻辑哲学论》中他认为语言只有一种 “语言逻辑”——即映示世界的功能,他在书中提出过现在已经广为人知的一个说法:“可以说的,都可说清;不可说的,只可不说。”不过后期在《哲学研究》中又进行了调整,认为有多种 “语言逻辑”,语言是由各有其自身逻辑的实践组成的广大集合。也就是说,语言并不是某种完备而独立的东西,它交织在人类全部的活动和行为之中,语言的不同用法正是通过人们彼此之间以及同所处的世界之间的交往才获得内容和意义的。关于 “理解” 维特根斯坦说:“理解一个句子意味着理解一种语言,理解一种语言意味着掌握一种技能。” 他将 “理解” 看作我们施展的一种能力,作为一种实践能力的理解是某种由外界标准——人们从事的活动和行为方式——来确认和衡量的,它是某种公开存在于公共领域的东西,而不是在个人精神生活内部或者属于私人的东西。这样看来,也许有两个方向可以拓展:第一,AI 在人类语言之间建立某种形式的映射,融入人类生活;第二,AI 在他们自己的领域内互相理解,形成独立的生命体。

模式角度

之前提到过人类表达语义的基本单位应该是 “句子”,因此对于句子的表征最为常见。之前提到的 CNN RNN Bert 等模型也是以句子表征为主。那就马上有个问题:“段落级别的表征是否和句子一致?”如果用词和句子来类比,显然答案是 “不一致”——词向量关注上下文、句子关注关键点。我们不妨想象一下当人类在阅读一句话和一段话(包括多句)时是如何处理信息的。句子之前分析过了,就是一句话的关键信息点,这个信息点可能包括:意图、实体、关系等。那么段落呢?当然可能是多个意图、实体和关系,但本文的观点是——并不止如此。段落是对多个句子的组装,是对信息的系统整合,这里涉及到句子之间内在的结构和关联。我们在阅读一个段落时,往往是读完以后有个整体印象后再去寻找答案,这和句子的处理思路并不完全相同。

当然,利用现有方案也是能够进行段落表征的,比如 Naive 的方法可以像当时词向量表征句子一样,将段落拆为多个句子,获得句子表征后取平均,或者直接将多个句子表征串起来,甚至直接表征整段(现有方案)。但这些方法感觉都有不少问题,比如取平均会丢失信息,串起来其实和直接表征类似,都会维度太大。也可以像 TextCNN 一样在句子(也可能是子句)之间做卷积,或者在 Bert 上用类似的方法(比如 LongFormer)。但是正如上面所说,段落其实和句子不是一回事,处理方法自然应该有所区别。我们是不是也可以为这种处理思路设计一种架构?比如我们是不是可以对 Bert 分层?首先扫描全段,然后抽出关键点重新组装后再输出作为表征(过程有点类似抽取关键词再生成摘要)。

方法角度

模型蒸馏在我看来并不是一种很优雅(显得非常繁琐)的方法,不过如果在算力有限的情况下,倒不失为一种行之有效的手段。目前针对 Bert 的 “瘦小版” 非常多,不过 Student 架构大多集中在 Transformer 和 CNN 两种结构上,对 Student 架构的探索相对不足。之所以提出这点出于两方面原因:第一,无论是 Teacher 还是 Student,本质上都是一种表征,既然是要用一种表征去拟合另一种表征,那架构方面自然可以按照这角度去专门设计;第二,灵感来自字节跳动的 Bert-Flow,它是将 Bert 的句子表征到一个标准的高斯隐空间,这个 Idea 感觉完全可以放大。不过正如本节开头所言,这种方法总体而言不够优雅,长期并不看好。

Reference