面向长文本处理的键值缓存压缩技术:智能压缩,无损性能,免微调

随着输入长度的增加,大型语言模型(LLMs)中的键值(KV)缓存需要存储更多的上下文信息以维持性能,这导致内存消耗和计算时间急剧上升。KV缓存的增长对内存和时间效率的挑战主要表现在两个方面:一是在处理长文本时,模型需要更多的内存资源来存储KV缓存,这不仅增加了硬件成本,还可能因内存限制而影响模型规模的扩展;二是在生成文本时,模型需要对KV缓存中的每个键值对进行注意力计算,随着缓存的增大,这个过程变得更加耗时,从而降低了模型的解码速度。

在深入分析大型语言模型(LLMs)的注意力机制时,研究者发现了一些关键模式,这些模式对于优化KV缓存至关重要。某些键在令牌生成期间始终吸引着模型的注意力,无论上下文的长度如何,这些“活跃”的键展现出稳定的高注意力权重。在长摘要和问答任务中,问题的位置(无论是在提示的开头还是结尾)对模型的注意力分配模式影响不大,显示出模型在处理长文本时的鲁棒性。研究者还发现注意力模式高度依赖于上下文,与用户的具体指令密切相关,这意味着不同的指令会引导模型关注不同的信息。

在超过 3k 的平均输入长度下,重要位置在生成过程中的逐层平均命中率。它显示了在多轮对话中,观察窗口中识别出的关键特征在随后的标记生成中保持了显著的一致性

这些观察结果促成了SnapKV的开发,它是一种创新的KV缓存压缩方法。SnapKV的创新之处在于它提出了一种无需微调的压缩方法,通过观察模型在生成过程中的注意力分配模式,自动识别并压缩KV缓存中的关键信息。SnapKV通过“投票”机制选出每个注意力头关注的关键KV位置,并通过聚类算法保留这些关键特征周围的信息,从而在不牺牲准确性的前提下显著减少KV缓存的大小。这种方法不仅减少了计算开销,还提高了内存效率,使得模型在处理长文本时更为高效。SnapKV在解码速度上实现了3.6倍的提升,在内存效率上实现了8.2倍的提升,同时在多个长序列数据集上保持了与基线模型相当的性能。SnapKV还能够与现有的深度学习框架轻松集成,仅需少量代码调整,为长文本处理提供了一种实用的解决方案。

SnapKV 的简化工作流程。橙色区域表示 SnapKV 为每个注意力头选择的每头一组位置的聚类。这些聚类特征随后与观察窗口中的标记一起形成新的键值对,与观察窗口(标记为 "Window")连接。所选的前缀和观察窗口共同构成了用于生成的新 KV 缓存

SnapKV 的核心思想是在生成过程中保持提示(prompt)的 KV 缓存数量恒定,从而显著减少长上下文 LLMs 的服务时间。这是通过识别和选择每个注意力头(attention head)最关键的注意力特征(attention features)来实现的,以此创建一个新的、更小的 KV 缓存。

实现步骤

SnapKV 的实现分为两个主要阶段:

  1. 投票选择重要特征(Voting for Important Previous Features):

    • 利用定义好的投票过程(如公式1所示),基于观察窗口(observation window)——即提示的最后部分——来选择重要的特征。
    • 通过分析发现,这些特征在整个序列生成过程中表现出显著的一致性,表明它们对后续生成至关重要。
    • 此外,实施聚类算法以保留选定特征周围的特征,这有助于保留信息的完整性并避免丢失上下文。
  2. 更新和存储截断的键和值(Update and Store Truncated Key and Value):

    • 将选定的特征与观察窗口的特征连接起来,这些特征包含了所有提示信息。
    • 将连接后的 KV 缓存存储起来,以供后续生成使用,同时节省内存使用。

代码示例

def snap_kv(query_states, key_states, value_states, window_size, max_capacity_prompt, kernel_size):bsz, num_heads, q_len, head_dim = query_states.shape# 确保当前是处理提示阶段assert key_states.shape[-2] == query_states.shape[-2]if q_len < max_capacity_prompt:return key_states, value_stateselse:# 计算观察窗口的查询和前缀上下文的键的注意力权重attn_weights = compute_attn(query_states[..., -window_size:, :], key_states, attention_mask)# 沿着查询维度对权重求和attn_weights_sum = attn_weights[..., -window_size:, :-window_size].sum(dim=-2)# 应用1D池化进行聚类attn_cache = pool1d(attn_weights_sum, kernel_size=kernel_size, padding=kernel_size // 2, stride=1)# 基于池化后的权重选择每个头的top-k索引,以识别重要位置indices = attn_cache.topk(max_capacity_prompt - window_size, dim=-1).indices# 扩展索引以匹配头维度进行聚集indices = indices.unsqueeze(-1).expand(-1, -1, -1, head_dim)# 根据选定的索引聚集压缩的过去键和值状态k_past_compress = key_states[..., :-window_size, :].gather(dim=2, index=indices)v_past_compress = value_states[..., :-window_size, :].gather(dim=2, index=indices)k_obs = key_states[..., -window_size:, :]v_obs = value_states[..., -window_size:, :]# 将压缩后的过去键和观察窗口的键拼接在一起key_states = torch.cat([k_past_compress, k_obs], dim=2)# 将压缩后的过去值和观察窗口的值拼接在一起value_states = torch.cat([v_past_compress, v_obs], dim=2)return key_states, value_states
  • snap_kv 函数接受查询状态 query_states、键状态 key_states、值状态 value_states,以及其他参数如窗口大小 window_size、最大提示容量 max_capacity_prompt 和池化核大小 kernel_size
  • 首先,检查是否处于处理提示的阶段,如果不是,则直接返回原始的键和值状态。
  • 然后,计算观察窗口内查询和前缀上下文键之间的注意力权重 attn_weights
  • 对这些权重进行求和 attn_weights_sum,然后应用一维池化 pool1d 来聚类,以便选择重要的特征。
  • 使用 topk 方法根据池化后的权重选择每个头的重要位置 indices
  • 根据这些索引聚集压缩后的键和值状态 k_past_compress 和 v_past_compress
  • 最后,将压缩的键和值状态与观察窗口的键和值状态拼接起来,形成新的键和值状态,这些状态将用于后续的生成过程。

SnapKV方法论包含两个主要阶段:首先是通过一个称为“投票”的过程来识别重要的先前特征,其次是更新并存储截断的键和值。

在第一阶段,SnapKV利用了一个观察窗口,这个窗口位于提示的末端,它的作用是捕捉模型在生成过程中所关注的关键特征。通过计算观察窗口中每个查询的注意力权重,并在所有注意力头上聚合这些权重,SnapKV能够突出显示被认为是最重要的前缀位置。这个过程称为投票,它帮助系统识别出那些在生成文本时需要特别关注的KV位置。

第二阶段中,SnapKV将这些选出的重要特征与观察窗口中的特征结合起来,形成一个新的键值对。这个新的键值对随后被用于生成过程,同时通过仅保留这些关键特征,系统能够显著减少所需的内存和计算资源。此外,为了保持信息的完整性并避免因过度压缩而导致的细节丢失,SnapKV采用了一种基于池化的聚类算法。这个算法通过池化层对信息进行细粒度的压缩,确保了在压缩KV缓存的同时,依然能够保留足够的上下文信息,从而维持模型的准确性。

SnapKV的实现是高效的,因为它只需要对现有的深度学习框架进行少量的代码调整。这意味着它可以轻松地集成到现有的系统中,而无需进行大规模的重构。在实验中,SnapKV显示出了卓越的性能,它不仅在解码速度上实现了显著的提升,还在内存效率上达到了大幅度的增强。这些改进使得SnapKV成为一个在处理长文本方面极具潜力的解决方案,特别是在需要处理大量输入序列的应用场景中,如聊天机器人、代理服务、文档处理等。SnapKV通过其创新的方法论,为长文本处理中的内存和时间效率问题提供了一个有效的解决方案。

在对SnapKV进行的实验中,研究团队采取了一系列严谨的测试,旨在评估该方法在不同模型和长文本数据集上的性能。实验的目的是验证SnapKV在减少计算和内存负担的同时,是否能够保持或甚至提升模型的生成质量和效率。

实验首先在LWM-Text-Chat-1M模型上进行了压力测试,这是当时最先进的模型之一,能够处理长达一百万个令牌的上下文。测试中,SnapKV展现了其算法效率,特别是在硬件优化方面。通过“Needle-in-a-Haystack”测试,即在长达380K令牌的文档中准确检索特定句子的能力,SnapKV证明了其在极端条件下处理长文本的能力,即便在极高的压缩比下也能保持精确性。

在单 A100-80GB GPU 上,使用 SnapKV 优化的模型与原始实现在 "Needle-in-a-Haystack" 测试中的性能比较。图表显示了 SnapKV 在处理极长输入上下文时准确管理细节的潜力

实验通过不同的批处理大小对LWM-Text-Chat-1M模型进行了解码速度和内存限制的基准测试。结果表明,SnapKV优化的模型在解码速度上保持了稳定,与输入序列长度的增加无关,这与基线实现形成了鲜明对比,后者的解码速度随输入长度的增加而指数级增长。SnapKV显著提高了模型处理长序列的能力,显著减少了内存消耗。

在不同批量大小设置下,基线实现与 SnapKV 优化模型在解码速度和输入序列长度方面的比较。图表显示了 SnapKV 在保持解码速度恒定方面的优势

为了进一步验证SnapKV的有效性,研究团队还对Mistral-7B-Instruct-v0.2模型进行了消融研究,以理解池化技术对模型信息检索性能的影响。消融研究结果表明,通过池化增强了检索准确性,这可能是因为强大的注意力机制倾向于关注令牌序列的初始部分。

池化技术在 LongEval-Lines 测试中对检索准确性的影响。结果表明,使用池化的模型在压缩 KV 缓存时的性能显著优于不使用池化的模型

最后,实验使用了LongBench,这是一个多任务基准测试,旨在全面评估长文本理解能力。SnapKV在多个不同设置下进行了测试,包括压缩KV缓存到1024、2048和4096个令牌,并使用最大池化和观察窗口。测试结果显示,即使在压缩率高达92%的情况下,SnapKV与原始实现相比,在16个不同数据集上的性能下降可以忽略不计,某些情况下甚至超过了基线模型。

SnapKV 和 H2O 在 LongBench 数据集上不同 LLMs 的性能比较。表格显示了 SnapKV 在压缩提示 KV 缓存时的性能与原始实现相比几乎没有下降

实验结果,SnapKV证明了其作为一种有效的KV缓存压缩方法,在保持大型语言模型处理长文本的能力的同时,显著提升了效率和减少了资源消耗。这些发现不仅证实了SnapKV的实用性,还为未来的研究和应用提供了有价值的见解。

SnapKV代码可在https://github.com/FasterDecoding/SnapKV上找到

论文链接:https://arxiv.org/abs/2404.14469

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/22720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

元宇宙数字藏品交易所,未来发展的大趋势

随着科技的飞速进步&#xff0c;元宇宙以其独特的魅力为数字世界绘制了一幅前所未有的宏伟蓝图。在这一宏大的背景下&#xff0c;数字藏品交易所作为连接虚拟与现实的桥梁&#xff0c;正以其卓越的优势&#xff0c;引领着数字藏品市场迈向新的高度。 首先&#xff0c;元宇宙为…

【相关概念】经济金融中的Momentum

张张张三丰de思考与总结&#xff1a; 最近做的期货价格泡沫中&#xff0c;一直在说&#xff0c;momentum&#xff0c;momentum&#xff0c;momentum&#xff0c;那么究竟什么是momentum呢&#xff1f; 目前&#xff0c;在有关期货价格泡沫的研究文献中&#xff0c;一般都是研究…

本轮牛市新趋势,跟随The First捕捉牛市Alpha

与以往牛市“百花齐放”的繁荣景象相比&#xff0c;本轮牛市颇具独特走势&#xff0c;呈现出了资金集中度高、财富聚集效应小的特点&#xff0c;绝大部分加密资产甚至跑不赢BTC的涨幅幅度。而以往大放色彩的公链币价值币的走势&#xff0c;甚至比不过牛尾才爆发的MEME币。这使得…

Java项目之消息队列(手写java模拟实现mq)【三、MQ的核心类-消息类的存储(用文件存储消息)】✔ ★

Java项目之MQ 七. 消息存储设计设计思路为什么要用文件存储文件存储结构queue_data.txt ⽂件格式:queue_stat.txt ⽂件格式: 创建 MessageFileManager 类定义一个内部类, 来表示该队列的统计信息 Stat实现统计⽂件Stat读写&#xff08;文本文件的读写&#xff09;InputStream—…

python爬虫入门教程(一)

上一篇文章讲了爬虫的工作原理&#xff0c;这篇文章以后就要重点开始讲编程序了。 简单爬虫的的两个步骤&#xff1a; 使用HTTPRequest工具模拟HTTP请求&#xff0c;接收到返回的文本。用于请求的包有: requests、urllib等。 对接收的文本进行筛选,获取想要的内容。用户筛选文…

JavaScript-内存分配,关键字const

内存空间 内存分为栈和堆 栈&#xff1a;由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆&#xff1a;存储引用类型 &#xff08;数组&#xff0c;对象&#xff09; 对象会先将数据存放在堆里面&#xff0c;堆的地址放在栈里面 关键…

VMD-PSO-LSTM单维时序预测模型(单输入单输出)-附代码

VMD-PSO-LSTM单维时序预测模型&#xff08;单输入单输出&#xff09; 1&#xff09;首先对原始单维数据进行VMD分解&#xff0c;分解为K个模态分量和1个残差分量 2&#xff09;将各个模态分量输入模型&#xff0c;建立模型进行预测 3&#xff09;将各个预测结果相加得到最终…

clickhouse(十五、存储优化实践)

文章目录 背景问题定位优化方式排序键设计写入顺序压缩算法 DoubleDeltaLowCardinality避免使用Nullable 总结 背景 clickhouse集群容量告警&#xff0c;项目中某些表占据大量的存储空间&#xff0c;借此机会对ck的存储优化进行实践学习&#xff0c;并通过多种方式测试验证优化…

React(五)useEffect、useRef、useImperativeHandle、useLayoutEffect

(一)useEffect useEffect – React 中文文档 useEffect hook用于模拟以前的class组件的生命周期&#xff0c;但比原本的生命周期有着更强大的功能 1.类组件的生命周期 在类组件编程时&#xff0c;网络请求&#xff0c;订阅等操作都是在生命周期中完成 import React, { Com…

【前端】响应式布局笔记——flex

二、Flex Flex(FlexiableBox:弹性盒子&#xff0c;用于弹性布局&#xff0c;配合rem处理尺寸的适配问题)。 1、flex-direction:子元素在父元素盒子中的排列方式。 父级元素添加&#xff1a;flex-direction: row; 父级元素添加&#xff1a;flex-direction: row-reverse; 父…

家政预约小程序13我的订单

目录 1 我的订单页面布局2 全部订单页面3 完善订单状态4 查询订单信息总结 现在我们已经完成了家政预约小程序主体功能的开发&#xff0c;包含服务的查看&#xff0c;在线预约已经登录等功能。预约之后就需要家政公司的客服进行派单&#xff0c;由服务人员进行上门服务。在小程…

Hotcoin精彩亮相Consensus 2024 Austin,探索行业风向标

5 月 31 日&#xff0c;由CoinDesk主办的“Consensus 2024”大会在德克萨斯州的奥斯汀市正式落下帷幕。作为全球规模最大、最具影响力的加密货币、区块链、Web3盛会&#xff0c;本次Consensus 2024 Austin吸引来自 100 多个国家/地区的 15,000 多名与会者、6,800 家公司、850 多…

【C++】手动模拟String底层与深浅拷贝

在string类&#xff1a;版本、组件、构造、操作及应用和 C中string的一些超常用函数 (附习题)这两篇文章中我们已经了解到了string&#xff0c;现在让我们再来手动实现模拟一下吧~ 模拟实现string是为了更好的理解string函数的使用和深浅拷贝方面的知识~ 总体整理了两张思维导…

【Python编程】【Jupyter Notebook】启动时报错:no available port could be found

一、报错描述 在Jupyter Notebook中编写程序&#xff0c;无法运行&#xff0c;提示由于没有可供监听的端口&#xff0c;无法启动Jupyter服务器&#xff0c;如下图所示&#xff1a; 二、原因分析 通过报错信息&#xff0c;猜测大概是由于网络环境的原因。首先&#xff0c;关闭…

C语言(结构体)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…

AIGC实战!7个超热门的 Midjourney 关键词教程

一、剪纸风格 核心词&#xff1a; paper art&#xff08;剪纸艺术&#xff09; 关键技巧&#xff1a; 主体物&#xff1a;可以换成任意主角&#xff0c;Chinese illustration &#xff08;中国风插画&#xff09;&#xff1b;艺术风格&#xff1a;paper art &#xff08;剪纸…

ruoyi vue 集成积木报表真实记录

按官方文档集成即可 积木报表官方集成文档 集成问题 1.注意 idea 配置的 maven 需要设置成 本地配置&#xff0c;不可以使用 idea 自带的 maven,自带 maven 会导致私有源调用不到 后端代码 新建 base 模块 maven配置 <project xmlns"http://maven.apache.org/POM/…

微软云计算[3]之Windows Azure AppFabric

Windows Azure AppFabric AppFabric概述AppFabric关键技术服务总线访问控制高速缓存 AppFabric概述 AppFabric为本地应用和云中应用提供了分布式的基础架构服务 用户本地应用与云应用之间进行安全联接和信息传递 云应用和现有应用或服务之间的连接及跨语言、跨平台、跨不同标…

C++数据结构之:哈希表Hash

摘要&#xff1a; it人员无论是使用哪种高级语言开发东东&#xff0c;想要更高效有层次的开发程序的话都躲不开三件套&#xff1a;数据结构&#xff0c;算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合&#xff0c;即带“结构”的数据元素的集合&am…

鸿蒙开发 之 ArkUI路由

1.页面路由 页面路由是指在应用程序中实现不同页面之间的跳转和数据传递 比如说你打开一个app&#xff0c;首先进入的是登陆页&#xff0c;首页&#xff0c;列表搜索页&#xff0c;详情页&#xff0c;你打开几个页面都会存储在页面栈里&#xff0c;页面栈的最大容量上限为32个&…