西湖大学蚂蚁新剪枝框架:校准数据错位怎么破?
sina qqZone renren ydCloud 0

大模型剪枝后,测试集分数挺好看,可一进真实对话或长文写作就掉链子,这背后的原因是什么?
西湖大学和蚂蚁集团的一篇论文盯上了这个现象的根源。他们发现,整个领域此前漏掉了一个问题:剪枝时拿来校准的数据,跟模型实际生成时面对的数据,分布根本对不上。顺着这条线往下挖,他们搭出了一整套新的剪枝框架,还顺带解释了稀疏计算在解码阶段反而变慢的怪事。
**核心问题:校准数据和真实场景的错位**
先说背景。写文档、写代码这类长文本生成,大语言模型走的是自回归解码。
所谓自回归解码,就是模型一个词一个词往外吐,每生成一个新词,就把它接到已有文本后面,当作下一次预测的输入,如此循环。
这个过程受内存限制——瓶颈不在算力,而在每一步都得把模型权重从显存搬到计算单元,搬运的数据量直接决定速度。模型越大,这个瓶颈越突出,生成几千字的长文章时延迟会非常明显。
剪枝是应对这个问题的常规手段,思路是把模型里不那么重要的参数直接归零,搬运的数据少了,速度自然就上去了。目前训练后剪枝的主流方法,大多建立在一个叫OBS的理论框架上。
OBS全称Optimal Brain Surgeon,1992年提出,靠二阶信息计算每个权重的重要性,近几年被SparseGPT等方法重新激活,用于大模型。
这类方法有个共同操作:先拿一批"校准数据"喂给模型,记下模型内部的激活值,再根据这些激活值判断哪些权重可以删、删了之后怎么补偿误差。问题就出在这批校准数据上。
传统做法是从C4这类固定文本语料库里抽一段话,强行灌给模型,这个过程叫teacher forcing。
Teacher forcing 说的是,训练或者校准时,模型自己预测得准不准并不重要,后续输入一律用真实、事先备好的文本,而不是拿模型自己的输出接着往下喂。
这种做法的前提是输入固定不变,可自回归生成压根不是这个路数。模型先出第一个词,第二个词靠第一个词算出来,第三个词又要看前两个词,一层层叠上去。剪枝要是在前几步带进一点偏差,偏差就会沿着生成链一路传下去、越放越大。结果就是真实生成时模型面对的"上下文",跟校准时那批固定文本差得越来越远。
论文里有张图把这事画得很清楚:他们测了剪枝后模型与原始模型之间激活值的差异,看它随解码步数怎么变。差异在开头十几步里就冲到了平台期的90%,之后再生成几百步也基本不动了。也就是说,校准数据的偏差在解码刚起步时就已定型,问题出在最初那几步没对上。
打个比方。你要训练一个翻译,校准数据就像你提前准备好的标准答案本。让翻译对照着答案本练习,一切都顺,可一旦上了真实谈判桌,对方说的话是临场即兴的,前后文完全是根据翻译自己刚才说的话推出来的。如果翻译平时只练习照本宣科,从没适应过"根据自己刚才说的话决定接下来怎么说"这种模式,那临场的小偏差会一步步累积,越说越偏题。这个问题不解决,剪枝后的模型在短文本测试里可能表现正常,一到长文生成就会状态失控,这正是论文观测到的现象。
**解法一:用模型自己生成的内容做校准**
既然问题是校准数据和真实解码不匹配,论文给出的方案也很直接:别用固定文本了,让模型自己生成,拿生成出来的内容做校准。
流程大致是这样:先备一批跟任务相关的提示词,写作任务用LongWriter的提示词,代码任务用LiveCodeBench的题目描述。接着让未剪枝的原始模型对着这些提示词自行续写。续写过程中逐层逐步记下输入激活值,但只留"解码阶段"的,凡属"预填充阶段"的激活一概不要。
预填充(prefill)处理的是输入提示词本身,这部分内容提前就给定好了,不牵扯模型自己的预测。解码(decode)阶段才不一样,模型要根据已经生成的内容不断往下猜下一个词。
那为什么非要把预填充阶段的数据剔掉?因为这一阶段处理的是用户给的提示词,说到底还是"外部给定"的东西,跟校准时拿固定文本没两样。真正能体现"模型照着自己的输出继续生成"的,只有解码阶段。论文要校准的目标,正是把这部分的激活分布抓准。
解码阶段的激活值收集齐后,论文据此构造了一个新的校准矩阵,记作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是稀疏矩阵乘稠密矩阵,一次吞下一大批数据;SpMV是稀疏矩阵乘单个向量,一次只处理一个token。预填充阶段要一口气处理整段输入,天然走SpMM;解码阶段每步只吐一个新词,天然是SpMV的场子。
现有稀疏计算库,比如英伟达的cuSPARSELt,优化重心都放在SpMM这类批量场景上。论文在Llama-3.1-8B上实测,用2:4稀疏度(英伟达Tensor Core原生支持的一种稀疏模式),预填充阶段确实拿到1.31到1.46倍加速,符合预期。可到了解码阶段,同一批稀疏权重跑起来只有稠密模型的0.85到0.87倍,比不剪枝还慢。
乍听有点反直觉:剪枝不该让计算更快吗,怎么还倒退了?问题在于SpMV本身数据量就小,稀疏存储格式带来的索引开销,比省下的计算量还大。好比为了省点米,结果花在称米、找米上的功夫更多。
论文为此专门做了一个面向解码场景的SpMV计算内核,用了两个关键技巧。第一个是位掩码索引。传统做法给每个保留下来的非零权重单独存一个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解决的核心问题是什么?现有大模型剪枝方法用固定文本语料库做校准,可模型实际解码时输入的却是自己生成的内容,两边分布对不上,剪枝后的模型在长文本生成这类真实场景里表现就往下掉。
Q2:SparseDecoding的N:M稀疏内核为什么能在解码阶段提速?它用位掩码代替传统列索引来存非零权重的位置,元数据体积缩小4到16倍;再靠固定步长遍历让GPU线程负载均衡,传统稀疏计算库在解码阶段反而变慢的问题由此解决,实测加速1.34到1.48倍。
Q3:SparseDecoding是否只适用于特定的剪枝算法?并非如此。论文分别在SparseGPT和Wanda两种剪枝算法上做了验证,新校准方法都稳定优于传统C4校准,可见改进来自校准数据本身,与具体算法无关。