西湖大学蚂蚁集团新剪枝框架:校准数据错位,稀疏解码反而变慢有解了
你有没有想过,为什么有些大模型剪枝后用起来感觉怪怪的,明明测试集上分数不低,一到真实对话或者长文写作就露馅?这篇来自西湖大学和蚂蚁集团的论文,就是在挖这个问题的根。他们发现了一个被整个领域忽略的bug:剪枝时用来校准的数据,和模型实际生成时看到的数据,压根不是同一种分布。这个发现听起来简单,但顺着往下...
有些大模型剪完枝,分数看着不低,可一进真实对话或长文写作就露馅。这问题不少人碰到过。西湖大学和蚂蚁集团的一篇论文就顺着这个现象往下挖。
他们找到的症结,是整个领域此前没注意的一处错位:剪枝时拿来校准的数据,跟模型实际生成时面对的数据,分布根本不是一回事。顺着这条线,论文搭出一套新的剪枝框架,还把稀疏计算在解码阶段反而变慢的怪事一并处理了。核心问题就落在校准数据和真实场景对不上。
先看背景。大语言模型写文档、写代码这类长文本生成,走的是自回归解码:模型一个词一个词往外蹦,每生成一个新词,就把它接到已有文本后面,当作下一次预测的输入,如此循环。
这个过程的瓶颈不在算力,而在内存:每一步都得把模型权重从显存搬到计算单元,搬运的数据量直接决定速度。模型越大,卡得越明显,生成几千字长文时延迟会很直观。
剪枝是常规解法,思路是把模型里不那么重要的参数直接归零,搬运的数据少了,速度自然上去。当前训练后剪枝的主流方法,大多建立在OBS这套理论上。OBS全称Optimal Brain Surgeon,1992年提出,靠二阶信息算每个权重的重要性,近几年被SparseGPT等方法重新激活,用到大模型上。
这类方法有个共同动作:先喂一批"校准数据"给模型,记下内部的激活值,再据此判断哪些权重能删、删完怎么补误差。问题恰恰出在这批校准数据上。
传统做法是从C4这类固定文本语料库里抽一段话,强行灌给模型,这个过程叫teacher forcing——训练或校准时,不管模型自己预测得对不对,都用真实的、提前准备好的文本作为后续输入,而不是让模型顺着自己的输出往下走。
静态输入场景下这么做没问题,可自回归生成完全不是这回事。模型生成第一个词之后,第二个词是基于第一个词算出来的,第三个词又基于前两个词,层层累积。剪枝若在早期步骤引入一点误差,误差会顺着生成链条不断传递放大,真实生成时模型看到的"上下文",和校准时用的固定文本就越走越远。
论文里有张图很直观:他们测量了剪枝后模型与原始模型之间激活值的差异,看它随解码步数怎么变。结果差异在最初十几步之内就快速涨到平台期的90%,后面哪怕再生成几百步,也基本不再变化。校准数据的偏差,从解码一开始就已定型,根子就在最初那几步没对齐。
打个比方。你要训练一个翻译,校准数据就像提前备好的标准答案本。让翻译对照答案本练习,一切顺;可一旦上了真实谈判桌,对方说的话是临场即兴的,前后文完全是根据翻译自己刚才说的话推出来的。如果平时只练照本宣科,从没适应过"根据自己刚才说的话决定接下来怎么说",临场的小偏差就会一步步累积,越说越偏题。这个问题不解决,剪枝后的模型在短文本测试里可能表现正常,一到长文生成就状态失控,这正是论文观测到的现象。
解法一:拿模型自己生成的内容做校准。既然症结是校准数据和真实解码不匹配,方案也就很直接:别用固定文本了,让模型自己生成,拿生成出来的内容做校准。
具体流程是这样。先备一批任务相关的提示词,写作任务用LongWriter的提示词,代码任务用LiveCodeBench的题目描述。然后让没剪枝的原始模型针对这些提示词自己往下续写。生成过程中记录每一层、每一步的输入激活值,但只留"解码阶段"产生的激活,"预填充阶段"的激活全部丢弃。
解码(decode)阶段和预填充(prefill)阶段是两回事:前者是模型不断根据自己已经生成的内容去猜下一个词,后者只是模型在处理输入提示词本身,那部分内容事先就给定好了,不牵涉模型自己给出的预测。
论文之所以把预填充阶段的数据单独拿掉,是因为这一段处理的是用户提供的提示词,说到底仍属"外部给定",和校准时拿固定文本用没有实质差别。模型"照着自己输出接着往下生成"这一点,只在解码阶段才真正体现出来。论文校准要做的,正是把这部分激活分布准确地抓住。
解码阶段的激活值收集齐后,论文构建出一个新的校准矩阵,记作XAR。原来的OBS剪枝流程完全不用动,只把输入校准矩阵换成这个新矩阵。整个过程不需要额外训练,也不用换优化器,只是换了一批更贴近真实场景的"参考样本"。
论文还做了理论证明,严格推导出校准目标与真实解码目标之间"最坏情况相对误差"的精确上界,并证明这个上界可以取到,不是松散的估计。实验在Qwen3-14B和32B两个模型上验证:用新方法校准,超过87%的可剪枝模块里误差都比传统C4校准更小,中位数误差比值在1.81到3.26倍之间。换句话说,新方法的校准偏差只有旧方法的三分之一到一半左右。
效果上,论文在WritingBench长文写作评测和ClassEval代码生成评测上都做了验证。以Qwen3-14B为例,2:4稀疏度下(每4个权重里保留2个),传统C4校准的写作总分只有1.85分(满分10分),换成新方法直接跳到4.18分,翻了一倍还多。代码生成任务里更夸张:Llama-3.1-8B在2:4稀疏度下,用C4校准的Pass@1是0%,一个测试都过不了,换成新方法后恢复到4%。绝对值还不高,但从0到有,说明模型至少恢复了基本的代码生成能力。
论文还跑了一个颇有意思的消融实验:拿更大的32B模型生成的内容,去校准14B的小模型,效果会不会胜过小模型自己产出的校准数据?答案是并不会,自己生成的反而更好。可见重点不只在「用生成数据替换固定文本」,数据还得是模型本人产出的,由别人代写同样不灵。打个比方,要适应自己说话的节奏和习惯,找旁人替你练口才,解决不了你开口时真正碰上的麻烦。
解法二:为解码阶段单独打造一把「稀疏计算钥匙」
校准数据选对了,也只是走完一半。剪完的模型想真跑得快,还得看硬件如何执行这些稀疏权重的运算。论文在这里挖出了第二个坑:现成的稀疏计算库,一到解码阶段反倒把速度拖了下来。
要讲清楚这件事,得先看矩阵运算的两种形态。模型计算的内核,说到底是权重矩阵与输入向量相乘。
SpMM是稀疏矩阵乘稠密矩阵(Sparse Matrix-Matrix),一次啃下一大批数据;SpMV则是稀疏矩阵乘单个向量(Sparse Matrix-Vector),一次只处理一个token。预填充阶段要同时处理整段输入文本,天然适合SpMM;解码阶段每回只吐一个新词,天生就是SpMV的场子。
英伟达的cuSPARSELt这类现有稀疏计算库,优化重心都放在SpMM这种批量场景上。论文实测了一把:Llama-3.1-8B配上2:4稀疏度(英伟达Tensor Core原生支持的一种稀疏模式),预填充阶段确实拿到1.31到1.46倍加速,符合预期。可一进解码阶段,同样的稀疏权重跑起来,速度只剩稠密模型的0.85到0.87倍,比不剪枝还慢。
乍听有点反直觉:剪枝不该让计算更快吗,怎么反而拖慢了?问题出在SpMV本身数据量就小,稀疏存储格式附带的索引开销,已经超过省下来的那点计算量。好比为了省几粒米,反倒多花更多工夫去称米、找米。
论文为此专门设计了一个面向解码场景的SpMV计算内核,里头用了两个关键技巧。头一个叫位掩码索引。
位掩码(bitmask)索引:过去的做法,是给每个保留下来的非零权重单独存一个32位列索引,好让计算单元知道这个权重原本落在矩阵的哪一列。论文换成位掩码,一位对一列,用0和1标注该位置的权重留没留,32个连续位打包进一个32位整数。
这么一来,元数据体积大幅缩水。50%稀疏度下,原本每个非零权重得花32位存索引,现在只要2位,缩小了16倍;跟另一种常见的8位偏移表示法比,也小了4倍。解码阶段本来就是内存带宽说了算,元数据越小搬运越快,这一刀正好切在瓶颈上。
第二个技巧叫固定步长遍历。论文选的是N:M稀疏模式,每32位掩码里恰好有16个位置1,于是每一行要扫的步数固定,编译期就能定死,不会出现有的行扫得快、有的行扫得慢。GPU上成千上万个线程因此能齐步走,不会有些线程早早算完干等、有些还在慢慢磨,负载不均的问题就没了。
可以借一个具体场景来理解。设想仓库里的拣货员,每拣一次货都得先翻厚厚的索引手册查货架编号,翻手册的时间没准比拣货还长。要是仓库提前按固定规律摆好货架,拣货员清楚自己走固定步数就一定能找到货,手册不必翻,效率自然上来。少了这层优化,权重即便已经稀疏化,GPU仍要大把时间花在「非零元素在哪儿」上,省下的计算量根本补不回索引开销,cuSPARSELt在解码阶段反而变慢,根子就在这里。
落到最终效果,论文用这套内核在A100 GPU上测了2:4、4:8、8:16、16:32四种N:M稀疏比例,结果一致得惊人:每种比例都稳定拿到1.34到1.48倍解码加速。同一个模型下,不同N:M比例的速度几乎没差别,因为它们保留的权重比例都是50%,吃掉的带宽一样,这恰好印证了内核设计的逻辑站得住。
| 模型 | 稠密基线 | 2:4稀疏 | 4:8稀疏 | 8:16稀疏 | 16:32稀疏 |
|---|---|---|---|---|---|
| Llama-3.1-8B | 1.00× | 1.42× | 1.42× | 1.42× | **1.42×** |
| Llama-3.3-70B | 1.00× | 1.39× | 1.46× | 1.38× | **1.48×** |
| Qwen3-14B | 1.00× | 1.34× | 1.35× | 1.34× | **1.35×** |
| Qwen3-32B | 1.00× | 1.45× | 1.45× | 1.45× | **1.45×** |
换一种剪枝算法,结论照样成立
论文还验了一件挺关键的事:这套新校准方法难道只对SparseGPT一种剪枝算法有效?他们特意换成另一个常用剪枝方法Wanda重测,在Qwen3-14B和32B上,新校准方法依旧稳定领先。
可见症结在于校准数据自身的分布偏差,跟具体选哪种剪枝算法关系不大。说白了,它不是某个算法的专属补丁,而是一个普适的改进方向;任何基于OBS框架或类似思路的训练后剪枝方法,理论上都能直接套用这套解码感知校准的思路。
论文另外补了实验,改用Pile和RedPajama这两个常见语料库做对比,新方法照样更优。这进一步说明,问题不在挑哪个语料库,而在「固定文本」这个校准范式本身,它跟解码场景存在根本性的错位。
写在后面
通读这篇论文,最让人记住的不是1.48倍这个加速数字,而是文里那张激活差异曲线图:差异在解码头十几步内就迅速定型,往后几百步基本不再变化。
这个现象值得琢磨。模型在生成的开头几步就把“轨道”定好了,之后不过是顺着这条轨道往下走。校准一旦出了偏差,模型第一步就带着误差出发,这个误差不会自行修正,只会越滚越大。机器学习训练里也有类似的“早期决定论”:神经网络初始化往哪个方向走,往往就决定了后面收敛到什么路径。解码阶段的这种早期锁定效应,可能比直觉上以为的更常见。
还有一点出乎意料:论文专门做了跨模型校准的消融实验,结果用更强模型生成的内容去校准小模型,效果反倒不如小模型自己生成的数据。这跟一个常见直觉相悖——大模型写的文本质量更高,拿来当“标准答案”校准小模型不是更说得通吗?可实验结果正好反过来。它说明校准要的不是“更好的文本”,而是“能更真实反映目标模型自身行为分布”的数据,这两件事并不等价。
论文没回答的问题是:这套解码感知校准的思路,放到更极端的稀疏比例下(比如90%以上)还管不管用?论文测到的最高稀疏度是2:4,也就是50%。压缩再激进一些,解码阶段的激活分布偏移会不会更难处理,这得留待后续追问。
Q&A
Q1:SparseDecoding解决的核心问题是什么?
A:现有的大模型剪枝方法拿固定文本语料库做校准,可模型真正解码时输入的却是自己生成的内容,两边分布对不上,剪枝后的模型在长文本生成这类真实场景里表现就会下滑。
Q2:SparseDecoding的N:M稀疏内核为什么能在解码阶段提速?
A:它用位掩码替代传统的列索引来存非零权重位置,元数据体积缩小4到16倍;再靠固定步长遍历让GPU线程负载均衡,传统稀疏计算库在解码阶段反而变慢的问题也就解决了,实测加速1.34到1.48倍。
Q3:SparseDecoding是否只适用于特定的剪枝算法?
A:不是。论文在SparseGPT和Wanda两种剪枝算法上分别做了验证,新校准方法都稳定压过传统的C4校准,可见改进来自校准数据本身,跟具体算法无关。