多模态大模型前传——DL-based NLP的前世今生
去年 10 月,OpenAI 正式发布 GPT-4V,将多模态大模型的能力提升到了一个新的层次。目前主流的 VL 大模型擅长对视觉和文本两个模态进行理解,本文将从文本模态,聚焦于基于深度学习方法,梳理大模型时代之前的自然语言处理脉络。篇幅有限,而自然语言处理的话题却如此庞大,笔者只能以自己的视角描述这段技术史诗的其中一面。
前深度学习时代的自然语言处理
站在 2024 年的今天,深度学习模型的参数量动辄以 10B 计算,回头看前深度学习时代的算法会或许让人感到简陋,但是笔者认为诸多统计机器学习算法不仅不简陋,反而设计巧妙,借助精心设计的特征工程和先验假设的简化,用最少的参数量完成了复杂的任务,也为深度学习时代算法提供了灵感。
传统机器学习算法因为参数有限,很难完美的处理复杂的任务,对于高维度的非结构化数据一般要增加一些先验假设进行简化,并用精心设计的特征工程将数据转化为更容易处理的形式,然后构造特定的模型进行建模,最后选择最合适的优化方法进行训练以确定参数。
词袋模型
词袋模型 bag of words 或许是传统 NLP 方法中最著名的建模方法,原理清晰,快速高效,至今也活跃在工业界。
顾名思义,就是将文本看成为一袋子词,具体来说就是将一段文本建模为一个词语的无序集合,只用每个词的频率作为来描述这段文本。词袋模型忽略了文本的词语顺序、语法结构,因此虽然在相当多的任务中可以取得不错的效果,但是仍然存在巨大的问题:
- 忽略了词语的顺序导致的问题:如
芙丽莲比费伦强和费伦比芙丽莲强的特征是一致的,但是意义相反; - 忽略了句子的语法结构导致的问题:给定一个句子
芙丽莲最爱魔法,如果用词袋模型的特征进行度量,那么芙丽莲很爱魔法与芙丽莲不爱魔法两个句子与原句的距离是相同的,但是含义完全相反。
为了修复上述问题,出现了能够在一定程度上捕捉上下文信息的 n-gram 模型。所谓 n-gram 模型,即将文本中的 n 个连续 token 作为一个特征,这样就可以在一定的窗口内对词汇之间的顺序进行建模,现在回头看颇有些 CNN 卷积核的感觉。
另一个改进的方向就是对每个 token 赋予权重,这也是一种非常自然的想法,毕竟句子中不是每个词语对整体文本的含义起到相等的作用。TF-IDF 和 BM25 或许是应用最广的两种赋予权重的方式,他们的核心思想是:如果某个词语在一片文档中频繁出现,但是在其他文档中很少出现,则认为这个词语具有很好的区分能力,因此具有更高的权重。
具体来说,TF-IDF 算法中,对于某个文档 $y$ 和文档中的词语 $x$,词权重 $w_{x,y}=TF_{x,y}log(\frac{N}{DF_x})$,其中:
- $TF_{x,y}$ 是词语 $x$ 在文档 $y$ 中出现的频率
- $IDF=log(\frac{N}{DF_x})$ 叫做逆文档频率
- $N$ 是数据库中文档总数
- $DF$ 是包含 $x$ 的文档数
- 这样如果 $x$ 在越多的文档中出现则权重越低
而 BM 25 算法则是在 TF-IDF 的基础上进行了改进,引入了更多参数,也成为了字面检索上应用最广泛的算法,如 elasticsearch 中默认的匹配方法即为 BM25,另外该算法也可以作为目前大模型 RAG 方案的字面检索方法。
词袋模型及相关改进算法高效且可解释,但是缺点也很明显,即无法捕捉相对的语义关系和语序信息。另外词袋模型因为 token 间的独立性,特征维度与词表的维度一致,如果采用 ngram 建模则会进一步扩大特征维度,这种指数级增长的特征空间,无论是计算还是存储成本都十分高昂,且深度学习模型也不擅长处理这种高维度稀疏的 one-hot 特征。
深度学习时代的自然语言处理
机器学习算法的优化,往往有数据、特征、模型三个视角。
Word Embedding
从特征值分布的角度看,机器学习算法的特征可以分为稀疏特征和稠密特征两种。
稀疏特征直白的讲,就是特征向量中大多数为 0 的特征,如上一节词袋模型相关特征,均为 one-hot 形式的特征向量。但在神经网络却不擅长直接处理如此高维、稀疏的向量,这主要因为全连接层需要与特征向量每一个维度连接,过高的维度极大的增大了神经网络的参数量,而大多数 0 特征不包含信息,这就使神经网络直接使用稀疏特征性价比很低,因此用稠密特征建模自然语言对深度学习来说就很必要了。
其实早在深度学习时代之前的 2003 年,大佬 Yoshua Bengio 的 word2vec[^3] 就是 word embedding 的开山之作(至少是笔者熟知的方法中的开山之作)。该工作在 2013 年被谷歌研究院重新拿出来进行了预训练从而广为人知[^4],这正是因为 2012 年的 AlexNet 在图像领域的大获成功拉开了深度学习时代的序幕,而 word embedding 作为连接神经网络和自然语言的桥梁,自然也被研究者们关注起来。
图片来自于 CSDN Caffiny
模型的结构非常简单,只有一个全连接神经网络层,用无监督的方式通过上下文将 word 转为了 embedding。具体训练的方式我们在预训练语言模型章节详聊。
CNN
在特征层面 word embedding 让海量稀疏的 word 变成了稠密的 embedding,那么下一步就是选择神经网络模型结构了。
2012 年的 AlexNet 及后续的一系列工作 GoogleNet/ResNet/SENet 等证明了卷积神经网络(CNN)是当时最好的视觉特征抽取器,而 2014 年的 TextCNN[^6]是 NLP 领域应用 CNN 的一个经典案例。
TextCNN 工作本身是应用于文本分类任务,与应用于图像的 CNN 相比网络结构甚至更为简单(卷积核少了一个维度,并且整体只有一个卷积层)。整体流程是分词->embedding->CNN->pooling->softmax 分类,当然这也是用深度学习进行 NLP 任务的基本流程,即分词、embedding、神经网络层、输出层。 CNN 在 NLP 的应用还有很多,在此不展开细说,但是要注意到 CNN 的一个问题,即感受野相对狭窄,每层只能捕捉上一层卷积核宽度的特征,往往需要堆叠多层才能对全局进行建模。
RNN
递归神经网络由来已久,在上世纪六七十年代就诞生了。RNN 擅长处理序列数据,如文本、音频或者时序指标数据等。RNN 的设计核心是将过去时间步的信息储存在当前时间步的输入中,因此它获得了处理时间步依赖的能力。
从 RNN 到 LSTM
具体来说,RNN 模块接受了当前时间步的输入和来自上一个时间步的状态,经过神经网络计算得到当前时间步的输出,并把状态储存到下一个时间步,如此往复。能够看出状态的存储是时间步之间共享信息的关键,也是 RNN 能够处理序列特征的原因,因此优化也是以状态变量为核心。
大名鼎鼎的 LSTM 就是通过几个 gate 对神经元内的状态变量和输入变量进行操作并且确保状态可以有一条“通路”不受影响的向下传递,为了提升模型对语言序列的建模能力,往往使用双向的 RNN 网络,这样同时对正反两个方向进行描述能明显提升效果。篇幅有限,关于 LSTM 的相关细节可以看这篇博客 Understanding LSTM Networks1。个人感觉这种 gate 网络颇有几分注意力机制的感觉,而这条为状态变量设计通路以防止时间步骤过长导致遗忘的设计也与 Resnet 的思想殊途同归。GRU 是对 LSTM 的简化,减少了一个 gate,但是思想是完全一致的。这两种结构大大提升了 RNN 对于长序列的建模能力,并在 NLP 的各个任务中大放异彩。
NLP 四大基本任务
自然语言处理中的任务种类繁多,一般可以分为四种:
- 文本分类:如句子分类、情感分类等
- 序列标注:如实体识别、分词等
- 句子关系:语义相似度等
- 生成任务:如机器翻译、文本摘要等
而这四种任务通过稍微改造网络结构的输出层均可以实现,以双向 LSTM 为例列举一些典型任务中的工作:
分类任务
分类任务可能是最经典的机器学习任务,网络结构也相对简单,可以用每个时间步的状态或者输出作为输出层也可以用最后一个时间步的状态。而多个时间步产生的可变数量的 tensor 却要求输入固定维度的分类层,那这里如果要在粗暴的 pooling 的基础上做一些优化,那么 attenion 机制是一个很自然的想法,比如 ICLR 2016[^2]的这个网络结构,用每个时间步的状态变量生成一个重要性权重再与自身相乘加权最终得到输出。
命名实体识别任务
命名实体识别任务在这个阶段也有了一个标准答案:Bi-LSTM+CRF
语义相似度任务
对于语义相似度任务应用最广的就是搜广推中常见的向量召回,最常见的思路就是用表示学习的方法训练一个特征网络,即将文本向量化,配合向量数据库可以进行海量数据的高效召回。而在 LSTM 时代也有类似的工作产生,如 2016 年的孪生 lstm[^9]:
生成式任务
至于生成式任务不得不提的就是 sequence to sequence[^10]架构,seq2seq 也可以称作 encoder-decoder 架构,由一个编码器 encoder 和解码器 decoder 组成。在 rnn 时代自然它们分别由 rnn(lstm)组成。具体来说通过 encoder 将输入文本编码为一个向量,被称作 context vector,认为包含了输入句子的所有信息。然后 context vector 作为 decoder 的初始状态,将输出文本依次输出。
讲到这里 encoder、decoder、自回归这些大模型时代出现频率很高的词汇也渐渐出现,而这个架构正是如今 openai 的首席科学家 Ilya Sutskever 在 Google 担任研究员时的一项工作,可以说后续的 bert、gpt 等语言模型都离不开这个架构。
RNN 的问题
RNN 在当时基本称为了 NLP 的通用网络结构,在各种任务中取得了很好的效果,LSTM/GRU 的出现也极大程度改进了长序列的建模能力,成为对比 CNN 最大的优势。但是深度学习除了效果外最大的约束就是性能,而 RNN 最大的短板也在于此。RNN 前向传播的时候每一个状态的输入都依赖上一个状态的输出,而这两个状态在时间上无法并行,这个问题在训练和推理中均难以解决(有一些工作试图优化 RNN 的并行问题,但是在笔者看来都没有很好的真正解决这个自回归结构本身的问题)。这种性能问题在输入输出序列很长的时候尤为明显,而且 RNN 对长序列的建模能力也十分有限,双向 RNN 是一个常见的 trick 但是在序列 token 达到百级别的时候效果仍会大幅下降。
那么是否有一个结构能够像 CNN 一样并行计算,同时又可以很好的对长序列进行建模呢?答案是 transformer。
Transformer
深度学习的研究方向有很多,而在初期的时候网络机构是大家最喜欢卷的方向,而在实际工作中其实对网络结构的优化其实意义并不算很大,因为各种 Net 汗牛充栋,在论文中说的天花乱坠,实际用下来区别不大,大部份工作很难说提升来自于网络结构的改进还是 trick 亦或是数据集的 overfitting。笔者经过多年踩坑也形成了一些技术审美,至少在网络结构这里,好的改进一定是自然的,堆砌感不强的,创新点直观而合理的。多年下来精读过或者试验过的各种网络结构肯定是百这个数量级了,其中有两个工作笔者一直认为是最优秀的,一个是视觉领域的 ResNet,另外一个就是 2017 年的 Attention is all you need,也就是 transformer。
Transformer 的结构相信大家都比较熟悉,细节可以参考 illustrated-transformer[^13] 这个博客,讲的非常直观,这里我们简单介绍一下。
attention 机制在上文中也有提到,在图像和文本领域已经有诸多应用,按照笔者的理解 attention 机制最突出的特点就是“加权”,张俊林老师的 深度学习中的注意力模型[^14] 文章也有很好的解释。
Attention 机制的具体计算过程,如果对目前大多数方法进行抽象的话,可以将其归纳为两个过程:第一个过程是根据 Query 和 Key 计算权重系数,第二个过程根据权重系数对 Value 进行加权求和。而第一个过程又可以细分为两个阶段:第一个阶段根据 Query 和 Key 计算两者的相似性或者相关性;第二个阶段对第一阶段的原始分值进行归一化处理;这样,可以将 Attention 的计算过程抽象为图展示的三个阶段。
![]()
attention机制
而 self-attention 顾名思义,就是 query/key/value 这三个元素都来自每个 token 自身。这就在一次 self-attention 计算中每个 token 都可以感知其他所有 token,突破了序列长度的限制,解决了长序列依赖的问题。而序列顺序也不再由 rnn 的时间步来描述,而是在输入的时候除了 word embedding,增加了一种 position embedding,用 embedding 来描每个 token 的位置,这就解决了并行计算的问题。当然后续有研究指出 transformer 是 self-attention 与其他结构的组合才得到最好的效果,与其说 attention is all you need,不如说 transformer is all you need,但是 self-attention 无疑是最大的创新点。
在论文刚出现的时候 attention is all you need 多多少少让大家觉得口气很大,后续 all you need 体的标题党论文层出不穷。但是 2018 年的 BERT 让这个工作全面出圈,不仅在网络结构层面让大家认可 transformer 是 NLP 任务的标准答案,也让预训练 NLP 模型的进展超过了 CV 领域,这个领先直到今天也没有再度逆转。而在其他模态领域,随着 ViT 等工作的问世,transformer 也打败 CNN 成为了 CV 领域最优秀的特征抽取器。在去年 meta 开源的 LLAMA 2 模型中也可以看到,多年后性能如此强大的 LLAMA 2 采用的结构仍然是 2017 年 transformer 论文中结构的小修小补。站在 2024 年的今天,无论是在学术界还是工业界都可以明确attention is ALL you need!
回过头来,笔者为什么认为 resnet 和 transformer 是网络结构领域最重要的两个工作?其实原因都是一致的,用今天很火的一个词说就是让 scaling 成为了 law。Resnet 通过一个简单的残差结构让非常深的网络训练成为了可能,在那之后基于这个结构出现了 CV 领域的预训练,让大家可以专注将网络做深做大容纳更多数据,而不必为将数据灌在哪个“瓶子”里费心。要知道市面上每个会议的模型结构实在太多了,早期算法工程师的工作经常是拿着数据在各个模型上试一遍,然后苦思冥想是不是调调模型结构,改改参数。而确定了网络结构大家发现那些奇技淫巧都不如实打实多一些数据,多一些模型的 scale,而残差结构好像让这个 scale 没有上限(实际还是有很多问题的)!而 transformer 更是将之前深度学习网络结构中最重要的全连接层、归一化、残差连接、attention 相结合,打造了各个模态通用的特征抽取器(从 GPT 看也是最优秀的生成器),同样使后人在此基础上专注作出更大的模型、容纳更多的数据。直到 OpenAI 在 2022 年让这个事情产生了质变。
预训练语言模型
按照刚才说的深度学习时代 NLP 模型的架构,分词、embedding、神经网络层、输出层,如果在神经网络层选定了网络结构,那么对于不同任务来说只有输出层是需要根据不同任务变化的,而其他的参数是可以一定程度上复用的,用大量数据进行预先训练在下游任务使用时进行一些微调即可。这一节将自然语言处理中的预训练技术进行一个简单的梳理,参考了张俊林老师的 从 Word Embedding 到 Bert 模型-自然语言处理中的预训练技术发展史[^16]。
既然说到预训练语言模型那首先明确一下语言模型的定义,其实很简单,就是预测一句话在该语言中出现概率的模型,一般用一句话中各 token 的联合概率来表示:$$p(s)=p(w_1)p(w_2|w_1)p(w_3|w_1,w_2)…p(w_i|w_1,…,w_{i-1})$$ 其中 s 为句子,$w_i$ 为第 i 个 token。
Word2Vec
这里其实已经埋下了后续 NLP 预训练反超 CV 预训练的伏笔。CV 预训练在当时的主流方式还是采用 ImageNet 数据集,通过分类任务作为进行预训练。而这个分类任务本质是一个有监督任务,需要人工标注数据,这就限制了预训练数据数量。而通过代理任务自监督预训练的 word2vec 则没有这个问题,可以将源源不断的数据转化为预训练的样本。但是此时此刻还没有一个足够好的模型结构来承接这样大量的数据。
ELMO
在深度学习时代,如前所述 RNN 最先成为了自然语言处理最优秀的网络结构,基于 RNN 的预训练工作应运而生——ELMO。
图片来自于知乎张俊林
ELMO 采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的 Word Embedding 作为新特征补充到下游任务中。上图展示的是其预训练过程,它的网络结构采用了双层双向 LSTM,目前语言模型训练的任务目标是根据单词 $W_i$ 的上下文去正确预测单词 $W_i$,$W_i$ 之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。图中左端的前向双层 LSTM 代表正方向编码器,输入的是从左到右顺序的除了预测单词外的上文 Context-before;右端的逆向双层 LSTM 代表反方向编码器,输入的是从右到左的逆序的句子下文 Context-after;每个编码器的深度都是两层 LSTM 叠加。这个网络结构其实在 NLP 中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子 $S_{new}$,句子中每个单词都能得到对应的三个 Embedding: 最底层是单词的 Word Embedding,往上走是第一层双向 LSTM 中对应单词位置的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层 LSTM 中对应单词位置的 Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的 LSTM 网络结构,而这两者后面都有用。
在具体使用中既可以将学到的两个 word embedding 拼接使用,也可以将整个双向 LSTM 网络作为下游任务的底层网络使用。这样就解决了 word embedding 中同一个 token 只能有一个 embedding 表示导致的同义词表示能力确实的问题。但是 ELMO 由于网络结构的限制,仍存在对长序列建模能力弱、性能较慢的问题。
GPT/BERT
时间到了 2017 年,transformer 横空出世让大家看到了一个性能效果全面超越 rnn 的 nlp 特征抽取器,于是 OpenAI 和 Google 分别基于 transformer 做了各自的预训练工作:GPT 和 BERT。
两者的共同点刚才也说过就是名字中的 T,即使用了 transformer 作为网络结构。但是他们预训练的代理任务不同,GPT 是一个自回归语言模型,根据上文内容预测下一个可能的单词,就是常说的自左向右的语言模型任务,或者反过来也行,就是根据下文预测前面的单词。而 BERT 是一个自编码语言模型,对输入的句子随机 Mask 其中的单词,然后预训练过程的主要任务之一是根据上下文单词来预测这些被 Mask 掉的单词,那些被 Mask 掉的单词就是在输入侧加入的噪音。而在训练后进行简单改造就可以在下游任务中使用,无论是 GPT 还是 BERT 改造方式均类似,都是取最后一层输出的某些张量然后增加一个输出层,以 GPT 为例:
总结
从简单优雅的统计模型到百亿参数的语言模型,自然语言处理在过去的 10 年可以说发生了翻天覆地的变化。现在回想 10 年前的 2014 年,对复杂文本的分类、对长句的机器翻译好像都是一个很有挑战性的前沿任务,而制作一个看起来足够智能的对话系统更是无从下手。记得 2017/18 年,笔者在阿里巴巴做对话相关的工作,沮丧的发现被视为最能体现 AI 智能的任务——对话系统,如果想要真正产生价值还是无法摆脱无数硬性规则。而彼时生成模型还在解决模型输出结巴的问题,看起来一个模型驱动的端到端的对话系统简直是天方夜谭。但是短短四五年时间 ChatGPT 就可以仅靠一个独立的模型成为世界上智能化水平最高的闲聊对话系统(甚至搜索引擎)。不禁感叹,人工智能的魅力和焦虑都来自于此,每当 AI 技术突破都有人疾呼 XX 已死,但是我们复盘 OpenAI 的技术路径可以发现,NLP 从没有死反而发展越来越快,但如果对新技术的学习能力和突破桎梏的勇气丧失掉了,这恐怕就会转瞬间被时代落下。
共勉。
[^1] 传统 NLP 之 Bag of Words, https://zhuanlan.zhihu.com/p/667280452 [^2] 从 Word Embedding 到 Bert 模型-自然语言处理中的预训练技术发展史, https://zhuanlan.zhihu.com/p/49271699 [^3] A Neural Probabilistic Language Model, https://proceedings.neurips.cc/paper_files/paper/2000/hash/728f206c2a01bf572b5940d7d9a8fa4c-Abstract.html [^4] Efficient Estimation of Word Representations in Vector Space, https://arxiv.org/abs/1301.3781 [^5] rnn vs lstm vs gru, https://www.shiksha.com/online-courses/articles/rnn-vs-gru-vs-lstm [^6] TextCNN, https://arxiv.org/abs/1408.5882 [^7] A Brief Introduction to Recurrent Neural Networks, https://towardsdatascience.com/a-brief-introduction-to-recurrent-neural-networks-638f64a61ff4 [^8] Feed-Forward Networks with Attention Can Solve Some Long-Term Memory Problems, https://arxiv.org/pdf/1512.08756.pdf [^9] Siamese Recurrent Architectures for Learning Sentence Similarity, http://www.mit.edu/~jonasm/info/MuellerThyagarajan_AAAI16.pdf [^10] Sequence to Sequence Learning with Neural Networks, https://arxiv.org/pdf/1409.3215.pdf [^11] 大语言模型历史之:seq2seq 模型与注意力机制 Attention, https://zhuanlan.zhihu.com/p/676539861 [^12] 整理了 12 小时,只为让你 20 分钟搞懂 Seq2seq, https://zhuanlan.zhihu.com/p/147310766 [^13] illustrated-transformer, https://jalammar.github.io/illustrated-transformer [^14] 深度学习中的注意力模型, https://zhuanlan.zhihu.com/p/37601161
-
Understanding LSTM Networks, http://colah.github.io/posts/2015-08-Understanding-LSTMs [^16] 从 Word Embedding 到 Bert 模型-自然语言处理中的预训练技术发展史, https://zhuanlan.zhihu.com/p/49271699 ↩︎
-
No backlinks found.