大模型处理长上下文方法一览

关于长上下文

2023年中开始,各大LLM厂商开始关注到长上下文的问题。2023年5月,Claude把长度支持到100k tokens;6、7月的时候,ChatGPT3.5也已经支持16k,而ChatGLM2-B最大长度已经可以到32k。

(插一句,ChatGLM系列做得一直很不错,从基础模型、长窗口、工具调用、Agent都一直保持在比较前沿的水平,个人最近用ChatGLM3、ChatGLM4体验还是很不错的)

差不多同时间还有LM-SYS的LongChat,MosaicLM的MPT也支持16k以及更长的上下文。

今年过年前刚出来的Qwen-1.5系列全家桶也都是32k起步了。还有一些支持超长窗口的模型
在这里插入图片描述

大厂商们卷完基础模型效果,把能刷的榜刷完,又盯上了长上下文能力(当然现在长上下文也有榜了)。

为什么要那么长?

长上下文的需求

取决于语言和所使用的tokenizer,每个token对应编码的文本有所不同。以中文为例,大部分模型每个token对应的中文字数都>1.5个字(部分高效的tokenizer可以做到2个字以上)。那么200k的token就能对应处理30w字的上下文了。

最近刚看了刘震云的长篇小说《一句顶一万句》,全书差不多27万字,也就是说现在这些长上下文大模型可以秒读完一部长篇小说,然后和我交流心得,或者告诉我全书的概要,又或者帮我找到一些文中的细节描写。

上面这个场景对应的是大模型的工具化场景。我们可以借助大模型的能力,来阅读论文,总结研报或者阅读代码,这些场景都需要比较长的上下文输入。

另外还有一个也比较火的大模型应用场景,RAG(Retrieval-augmented generation),也对长上下文输入有要求,只是在RAG中,大部分输入文本并不是直接来自于用户输入,而是通过检索得来的。

除了工具化的应用场景,还有一些个性化的场景也会对长上下文有需求。举例来说,就是一些智能助手需要对用户的偏好和设置做长期记忆,这些偏好和设置可以以prompt或者对话的形式持久化存储下来,在进行新的对话的时候就把这些内容连同用户新的输入一起给到模型进行处理。

实际上,哪怕是单次的聊天,也很有可能需要模型处理比较长的上下文。比如我们可能会让模型扮演一个特定的影视角色或者游戏角色和我们进行对话。这时通常会给模型一些设定,比如这是一个什么样的任务,故事背景世界观都是什么样的,以及现在要进行哪些方面的交流等。这些设定都会以prompt的形式在最开始输入给模型。而随着对话的进行,模型如果长文本能力比较差,就有可能忘记了我们之前给的设定,这样体验上就有问题了。

上面这个例子实际引出了对长文本需求更具体的内容:(1)在文本比较长的时候,还能说人话,ppl要低(2)说人话之余,还要能attention到前面提过的细节,不能出现自我矛盾。

模型怎么支持长上下文

看来目前的很多应用场景确实对长上下文有需求,那怎么实现呢?

如果我们直接训练2k/4k长度的模型,然后在推理的时候设定8k或者16k窗口,那么PPL会急剧上升,导致模型直接讲不了人话,原因之一在之前讲RoPE的时候也有提到,对于没有训练过的位置编码,模型不能很好地处理。

直接训练

既然训练的时候用2k/4k不能很好地在8k/16k/32k+的上下文长度下推理,那直接在训练的时候用更长的数据进行训练不就可以了?

这个思路理论上可行,只是实操的时候会遇到一些问题(壕可能觉得不是问题)。

1.训练数据

直观上来说,要训练长上下文的模型,就需要长文本。要达到32k或者更大的长度,基本都只能是书籍。

当然,我们也可以通过把多个中等长度的文本进行拼接,再用来训练。比如筛选4k长度数据,那8条拼在一起也够长了。然后通过attention mask来限制各段文本之间注意力,让它们可以在各自的位置上各训各的,互不干扰。甚至实际上即使不做attention mask,效果也挺好。

总的来说,就是【连续长文本】>【多个中等文本拼接】(也可用)

2.资源消耗

来简单看一下transformer在训练中所消耗的资源。

假设模型有 层,词表大小为 ,hidden size为 ,batch size为 ,训练窗口长度为 ,使用Adam优化器训练(需要存一阶和二阶动量),为简化估算,可以假设注意力头数为1。

(1) 参数量

在这里插入图片描述

(2) 计算量

在这里插入图片描述

看一下计算量和参数量的关系。忽略参数量和计算量中的低次项,则有

在这里插入图片描述

在这里插入图片描述

(3) 显存

在这里插入图片描述

这部分跟输入长度没有直接关系。

另外一个需要占用显存的部分是中间激活值。

保存激活值是为了计算梯度,因此每个矩阵相乘、softmax、dropout都需要保存输入值的中间的激活值。

在这里插入图片描述

小模型(比如2B、7B)可以硬刚,支持到16k或者32k长度,但是对于更大的长度(200k),或者更大的模型(34B、70B+),这么做就性价比就比较低了。

现在一般的做法是分两阶段,第一阶段用2k或者4k训练一个基础模型,等到模型把文本内容和短位置关系都学好之后,再来用相比第一阶段小的数据量优化在长上下文情况下的效果。

而第二阶段在如何用更少的训练量达到更好的效果这件事上,又有很多工作。

线性插值 Position Interpolation

23年6月,Meta在《EXTENDING CONTEXT WINDOW OF LARGE LANGUAGE MODELS VIA POSITION INTERPOLATION》中就提出了针对RoPE的线性插值方法PI(Position Interpolation),可以把2k的基础模型扩展到32k,并在1k个step的训练下就达到很好的效果。

在这里插入图片描述

In contrast, LLaMA models that are extended via direct fine-tuning only saw a minimal increase of the effective context window size kmax from 2048 to 2560, even after fine-tuning for more than 10000 steps, with no clear indication of an acceleration in the increase of window size.

相比之下,直接基于基础模型进行长文本微调的效率就比较低,训练1w步后,有效长度只是从2048提升到2560。

看来RoPE虽然拥有诸多优点,长上下文外推这个事情却不在其中。

论文中对RoPE外推性能也进行了一些分析。本来RoPE是相对位置编码,而且具有远程衰减的特性,理论上应该具备一定的外推能力,但实际上却不是这样。简单地说,论文发现,在相对位置差|m-n| 不太大的时候(<2048),确实能保持远程衰减且attention值保持在较小的区间,但是一旦|m-n| 超过这个区间,还是有可能出现很大的值。

在这里插入图片描述

看上图中间的这个图,在位置超过3000的时候,突然出现很大的attention score。而右边的图使用了插值的方式,就相对稳定。

(远程衰减上界问题具体推导的过程就不展开了,感兴趣的朋友可以看下论文原文)

而另一方面,PI甚至可以在只使用插值,而没有训练的情况下,就拥有一定的长窗口能力。

在这里插入图片描述

插值的思路是这样的:如下图所示,左上部分表示预训练过的2k长度的位置编码,右上部分表示在这个基础上直接外推,这样就会出现很多之前没有训练过的值,模型的学习成本会比较高;下半部分表示在已经训练好的2k模型基础上进行插值,类似于在每两个位置编码之间,插入一个位置点,这样总的位置表示就从2k增加到4k。在这个基础上再进行少量的微调,模型就可以很快学到新的位置表示。

在这里插入图片描述

这个思路也很符合直觉,比如原来模型针对位置1,位置2,位置3…学到了一定的规律,现在告诉模型,位置不一定是整数,变成位置1,位置1.5,位置2,位置2.5…。虽然值变了,但是相对关系还在,因此模型也能借助原来学到的关系,快速推广到“0.5”的位置中。

在这里插入图片描述

更具体来说,就是对RoPE做一点修改

在这里插入图片描述
在这里插入图片描述

(一通分析,实现却很简单,工程师的福音,真希望以后论文都能给出这样的结果)

然后使用几万到几十万条样本进行预训练,就可以了。

(文章里还埋有一个后续的关注点,在对长上下文进行训练后,在短上下文的场景下,效果略略有所下降)

NTK-Aware Interpolation

线性插值相当于直接线性拉伸了cos函数,减小了不同位置之间的差异,使得模型对于相近位置的区分度有所下降,多少有点简单粗暴,而NTK-Aware Interpolation就提出了理论上看起来更为“精致”方法,一种在RoPE上做非线性插值的方法,NTK-Aware Scaled RoPE。CodeLlama就是用这种方法把长度推广到1M。

NTK,就是Neural Tangent Kernel,神经正切核。具体是什么,让GLM4帮忙解答一下

Neural Tangent Kernel (NTK) 是深度学习理论中的一个概念,它是在训练无限宽的神经网络时出现的一个理论工具。在深度学习领域,宽度通常指的是网络中每一层的神经元数量。NTK 的提出,为理解深度学习提供了一个新的视角,特别是在网络宽度趋于无穷大时,网络的行为可以用线性模型来近似。
在理想情况下,当网络宽度趋于无穷大时,网络的训练过程可以用一个固定的核函数来描述,这个核函数就是 Neural Tangent Kernel。这个核函数描述了网络输出与输入之间关系的性质,使得我们可以用核方法来分析这类网络的训练和泛化能力。
具体来说,NTK 使得我们能够预测在无限宽的网络中,随着训练的进行,网络权重的演化情况,以及网络的损失函数如何随时间变化。这些预测在数学上更加清晰和可分析,有助于我们深入理解深度学习的工作原理,特别是在泛化和优化方面。
NTK 的研究对设计新的网络架构、训练算法和理论分析提供了重要的理论基础。它也表明,在一定的条件下,深度学习可以简化为传统的统计学习理论,如核方法,这为将深度学习与经典机器学习理论联系起来提供了桥梁。

这个了解各大概就行。那么具体在长上下文扩展这个事上,NTK有什么说法呢?

它认为,线性插值把所有方向上的分量一视同仁,把旋转速度统一变慢,这里有问题。

回顾一下在RoPE中,对位置 m的输入向量进行“旋转”的矩阵长这样

在这里插入图片描述

在这里插入图片描述

不加区分地对高低频信息进行拉伸,会丢失很多重要的高频信息,这样不是很好。高频信号应该外推,以防止分辨率太低,都挤在一起;而低频信号就适合插值。

怎么实现“高频外推,低频内插”?

先看回讲RoPE的时候,对于2维情况,有

在这里插入图片描述

推广到高维的情况,则有

在这里插入图片描述
在这里插入图片描述

在这个公式下,线性插值相当于把
在这里插入图片描述

在这里插入图片描述

引用来自知乎一篇文章的一个视角来理解NTK-Aware Interpolation

有意思的解释一下,RoPE 的行为就像一个时钟。12小时时钟基本上是一个维度为 3、底数为 60 的 RoPE。因此,每秒钟,分针转动 1/60 分钟,每分钟,时针转动 1/60。现在,如果将时间减慢 4 倍,那就是二使用的线性RoPE 缩放。不幸的是,现在区分每一秒,因为现在秒针几乎每秒都不会移动。因此,如果有人给你两个不同的时间,仅相差一秒,你将无法从远处区分它们。NTK-Aware RoPE 扩展不会减慢时间。一秒仍然是一秒,但它会使分钟减慢 1.5 倍,将小时减慢 2 倍。这样,您可以将 90 分钟容纳在一个小时中,将 24 小时容纳在半天中。所以现在你基本上有了一个可以测量 129.6k 秒而不是 43.2k 秒的时钟。由于在查看时间时不需要精确测量时针,因此与秒相比,更大程度地缩放小时至关重要。不想失去秒针的精度,但可以承受分针甚至时针的精度损失。

另外苏剑林从“进制”角度对RoPE作了分析,感兴趣的朋友可以看下原文,也很巧妙。

在YaRN的论文中,对NTK的优缺点作了点评

Given the results from [6], this method performs much better at extending the context size of non-finetuned models compared to PI [9]. However, one major disadvantage of this method is that given it is not just an interpolation scheme, some dimensions are slightly extrapolated to “out-of-bound” values, thus fine-tuning with “NTK-aware” interpolation [6] yields inferior results to PI [9]. Furthermore, due to the “out-of-bound” values, the theoretical scale factor s does not accurately describe the true context extension scale. In practice, the scale value s has to be set higher than the expected scale for a given context length extension.

在这里插入图片描述

NTK-by-parts

NTK-by-parts的方法在NTK插值的基础上又多想了一层。它认为无论是线性插值还是NTK-aware插值,认为RoPE的所有分量都对网络有同样的重要性。而NTK-by-parts的思路认为,应该区别对待不同分量,他们对网络的影响有所不同。

对于分量 j,RoPE嵌入的波长

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Dynamically NTK Scaled RoPE

无论是线性插值还是NTK-Aware Interpolation,都是通过使用一个固定的系数,对原RoPE做了一个缩放,这样就会有一些局限。一方面,这种情况下,模型能支持的最大上下文就由使用的这个缩放系数来决定了,超出这个范围的,依然会出现attention score暴增的风险。另一方面,在解码过程中,当已解码的长度l 还没有达到训练长度 L时,就使用 来修改base,也可能带来一些损失。Dynamically NTK Scaled RoPE是在NTK插值的基础上,把固定的系数改成动态的系数。

具体来说,就是

在这里插入图片描述

在这里插入图片描述

有一点要注意的是,使用动态的系数时要注意kv-cache的缓存机制是否正确,记得要缓存使用应用RoPE之前的值。

YaRN

上面的方法都是使用插值,研究者发现,随着插值,token之间的距离变得更近(因为现在旋转角度变小了),平均最小距离在减小,这样注意力softmax的分布会变得更尖(也就是都集中在某个区间)。换句话说,就是RoPE原本远距离衰减的特性变弱了,衰减得更不明显,就会导致模型更平均地关注到更多的token,这样就削弱了注意力机制,导致输出质量下降。

在这里插入图片描述

YaRN最终的方法就是结合NTK-by-parts,以及使用这个温度值对attention score进行调整。

YaRN在微调以及无微调的情况下,效果都比上面的几种都要好。

logn

在这里插入图片描述

其他

在扩展推理长度上,还有很多其他有效的工作,比如各种window attention,streaming LLM,LongLoRA,Focus Transformer等,还有数据、评测等更方面的分析,待逐个梳理。

小结

较短的预训练模型(2k、4k)应用在长上下文会因为训练和推理的两个不一致导致效果下降

  • 推理时用到了没训练过的位置编码
  • 推理时注意力机制所处理的token数量远超训练时的数量,导致注意力机制的崩坏

这两个问题分别可以从位置编码和attention score的放缩来缓解。

线性插值PI、NTK插值、分部NTK插值都可以缓解第一个问题,logn和YaRN则把第二个问题纳入的考虑。目前这些方法在实际应用中也有很多变体,包括超参的修改,函数的重定义等。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NNLM模型在嵌入上下文时,使用n-gram语言模型,将n-gram中的每个单词表示成一个向量,这些向量在模型中被称为嵌入(embedding)。具体来说,NNLM模型嵌入上下文的步骤如下: 1. 对每个单词进行one-hot编码,将其转换为一个稀疏向量,其中只有一个元素为1,其余元素均为0。例如,对于一个包含10个单词的词汇表,单词"apple"的one-hot向量表示为[0, 0, 0, 0, 0, 1, 0, 0, 0, 0]。 2. 对词汇表中的每个单词,使用一个小型的神经网络(称为投影层),将其one-hot向量映射到一个低维的稠密向量(称为嵌入向量)。嵌入向量的维度通常在几十到几百之间,比one-hot向量要小得多。投影层通常由一个线性变换和一个非线性变换(如tanh函数)组成。 3. 对于一个包含n个单词的上下文,将其各个单词的嵌入向量相加,得到上下文的嵌入表示。具体来说,设上下文为C={w1, w2, ..., wn},其中wi表示第i个单词的嵌入向量,则上下文的嵌入表示为: h = v1 + v2 + ... + vn 其中,+表示向量相加的运算。 4. 最后,将上下文的嵌入表示h作为输入,使用一个softmax分类器预测下一个单词。softmax分类器通常由一个线性变换和一个softmax函数组成,将上下文的嵌入向量映射到一个概率分布,表示下一个单词出现的概率。 这就是NNLM模型嵌入上下文的过程,通过将上下文中的每个单词嵌入成一个低维的稠密向量,并将它们相加得到上下文的嵌入表示,从而更好地预测下一个单词。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值