《本草纲目》的作者是谁?三个剪枝版的 DeepSeek-V4-Flash,三个都答错,三个都 0 分。秦始皇本名叫什么?还是三个 0 分。
我把这两道题当成铁证,写下结论:剪枝不背锅,原版模型自己就不行。
后来直接调官方接口,同一套题再跑一遍。这两道,原版各拿 10 分。总分 9.21,是我那张对比表上的最高分。
中间我做了两轮统计,第二轮推翻了第一轮,然后被官方接口推翻。第一轮的结论是对的,可它对得靠运气。这篇讲第二轮那个统计为什么在这个问题上天生没有分辨力,以及怎么在跑它之前就看出来。
想直接拿判据的看第 5 节,那是一个问自己的问题;想看怎么读剪枝仓库自带的跑分表,看第 6 节。
1. 问题本身:剪完掉了 1.9 分,还是它本来就这样?
DeepSeek-V4-Flash 是一个 MoE 模型。MoE 的意思是模型里面分了很多个「专家」,每次只叫醒其中几个干活。这个版本一共 256 个专家,完整权重 155.4 GiB。
我手上是两张 64 GB 的卡,扣掉运行时的开销,能给权重用的大概 122 GiB。原版塞不进去。
所以社区有人做了剪枝版:给每个专家按「它对输出有多重要」打分,排在后面的直接砍掉。我前后跑了三个公开的剪枝版:
| 剪枝版 | 保留专家 | 剪掉 |
|---|---|---|
| 变体 A | 178 | 30.5% |
| 变体 B | 160 | 37.5% |
| 变体 C | 144,再叠 2bit 量化 | 44% |
拿我自己攒的 140 道中文题去测,分四个方向:幻觉抵抗(问它不存在的东西,看它会不会编)、知识、推理、工具调用。一个大模型当裁判,每题 0 到 10 分。
三个变体的总分挤在 7.29 到 7.37 之间。工具调用很好,9.1 到 9.5;幻觉抵抗很差,4.90 到 5.63。我在同一套题上测过的另一个 35B 模型,幻觉抵抗有 8.20。
于是问题就来了:这三个变体这么差,是剪枝剪坏的,还是 DeepSeek-V4-Flash 原版本来就这个水平?
最干净的回答是把原版也跑一遍。可原版装不下。我第一反应是去设计一个间接检验。
2. 第一轮:答错的题不重合,我判是剪枝的锅
思路很朴素。如果原版底子有个盲区,那所有从它剪出来的版本都应该在同一批题上翻车。如果是剪枝各自随机丢了知识,两个变体答错的题就该各错各的,重合度跟瞎蒙差不多。
衡量重合度用一个除法:
期望重合 = 题数 × (A 答错的比例) × (B 答错的比例)
富集倍数 = 实际重合 ÷ 期望重合
富集倍数 1 就是跟随机一样,大于 1 就是错得扎堆。
我把 3 分及以下算作「答错」。幻觉方向 30 道题,变体 A 错 15 道,变体 C 错 10 道:
期望重合 = 30 × (15/30) × (10/30) = 5
实际重合 = 5
富集倍数 = 1.00
正好 1.00,跟随机一模一样。我的结论:不共享病灶,剪枝是主因。
这个结论碰巧是对的。可当时我自己的笔记里就写着它只证了一半:它排除了「原版在某几道题上有固定盲区」,排除不了「原版整体爱编」。而且它只有一对变体。
3. 第二轮:加一个变体,富集到 2 到 3 倍,我推翻了自己
变体 B 下载好了,我把三个变体放一起重算。三方同时答错的期望值,就是把三个比例乘起来:
期望三方重合 = 题数 × (fA/题数) × (fB/题数) × (fC/题数)
幻觉方向,三个变体分别错 15、11、10 道:
期望 = 30 × 0.500 × 0.367 × 0.333 = 1.83
实际 = 4
富集 = 2.18
知识方向 40 道,分别错 8、16、11 道:
期望 = 40 × 0.200 × 0.400 × 0.275 = 0.88
实际 = 3
富集 = 3.41
错题一下子扎堆了。三个剪枝方法不同、剪枝率不同、其中一个还叠了量化、跑在另一台机器上,却在同几道题上一起翻车。我写下「这不是随机丢专家能解释的」,然后推翻第一轮:病灶在原版。
再去翻那几道三方全 0 分的题,其中四道我的另一个对照模型是满分,包括开头那两道。连《本草纲目》的作者都答不出来,三个版本一起答不出来,我觉得够硬了。
中间我还干了件蠢事。想绕开「装不下」,给推理框架开了把一部分权重放到内存里的选项。结果整台机器 SSH 失联,只能去按电源键。日志停在建内存映射那一步,第一个权重文件都还没读到。这条路在那台机器上是死的,而且这个结论我之前的笔记里早就记过。
4. 官方接口一跑:9.21
最后直接调 DeepSeek 的官方接口,同一套 140 题,同一个裁判:
| 官方原版(256) | A(178) | B(160) | C(144) | |
|---|---|---|---|---|
| 幻觉 | 7.90 | 4.90 | 5.53 | 5.63 |
| 知识 | 9.80 | 6.40 | 5.47 | 5.90 |
| 推理 | 9.44 | 8.69 | 8.84 | 8.80 |
| 工具 | 9.40 | 9.52 | 9.48 | 9.12 |
| 总分 | 9.21 | 7.37 | 7.29 | 7.35 |
《本草纲目》10 分,秦始皇本名 10 分。
要判断这个差距是不是真的,我用的是配对检验:同一道题上,原版分减变体分,140 个差值算平均和波动:
t = 差值的平均 ÷ (差值的标准差 ÷ √题数)
|t| 过了 2 左右,基本就可以当成真差异。三个变体的结果:
| 平均差 | t | |
|---|---|---|
| 原版 vs A | +1.84 | 6.28 |
| 原版 vs B | +1.92 | 5.76 |
| 原版 vs C | +1.86 | 6.09 |
三个都在 6 上下,方向完全一致。分方向拆开看更干净:知识每题差 3.4 到 4.3 分,t 在 6.0 到 6.3;幻觉差 2.3 到 3.0 分,t 在 2.9 到 3.5;工具调用三个都在噪声里,有一个变体还比原版略高。
剪枝的代价大约是 1.9 分,几乎全落在「记住的事实」和「不知道就别编」上。会不会调工具,剪完一点没掉。
那四道「铁证」题,两道知识题原版满分;另两道是幻觉题,原版也答错了。真正算得上原版毛病的,就这两道。
5. 错在哪:这个统计的「零假设」从一开始就是假的
富集 2 到 3 倍这个数是真的。我读错的是它在说什么。
剪枝的做法是给专家按重要性排序,留前面的,砍后面的。三个变体用的都是这一类打法。那么在所有变体里都排得靠后的那批「冷门专家」,在三个版本里都会被砍掉。依赖这批专家的题,三个版本自然一起翻车。
所以富集来自剪枝手段本身的一致性。我写「这不是随机丢专家能解释的」,这句话是对的:它从来就没有随机丢过,每次丢的都是同一批。我错在下一步,把「不随机」直接读成了「跟剪枝无关」。
把这件事写成判据,就是一个跑统计之前该问自己的问题:
如果原版完全没问题,这个统计会长什么样?
如果原版确实有问题,这个统计又会长什么样?
两个答案一样 → 这个统计在这个问题上没有分辨力,别跑了。
套进来:原版没问题,三个变体都按重要性砍掉同一批专家,错题扎堆。原版有问题,错题也扎堆。两个世界给出同一个读数,我却拿这个读数去分辨这两个世界。
重合度检验的零假设是「各个变体独立地、随机地丢东西」。这个前提在确定性的剪枝方法下根本不成立,所以它被拒绝了,什么新信息都没有。
间接统计能用来证伪。第一轮那个 1.00 至少说明了「原版在这些题上有固定盲区」这个说法不成立。可它推不出因果方向。只要有直接对照能拿,先去拿:官方接口、没处理过的原版、上一个版本、别人公开跑过的基线。
这一回的账:两轮统计、一次物理重启,对面是一个官方接口,十几分钟。
6. 拆穿别人的数字:剪枝仓库自带的那张跑分表
选剪枝版的时候,其中一个仓库的模型卡上有张跑分表,我一开始直接引用了:
| 专家数 | GSM8K | MATH-500 | HumanEval+ | MBPP+ | 平均 | |
|---|---|---|---|---|---|---|
| 原版 | 256 | 0.9484 | 0.7060 | 0.8720 | 0.7407 | 0.8168 |
| 剪到 178 | 178 | 0.9401 | 0.6880 | 0.8720 | 0.7407 | 0.8102 |
| 剪到 132 | 132 | 0.9295 | 0.7140 | 0.8963 | 0.7593 | 0.8248 |
我当时的说法是「剪到 178 平均只掉 0.66 分,质量有保障」。然后被问了一句:剪到 132 的怎么反而比原版分还高?
剪得更狠反而更强,这种排序先别急着找解释,先算误差。每项的准确率是「答对题数 ÷ 总题数」,它的抖动幅度可以直接算:
标准误 = √( p × (1 − p) ÷ 题数 )
HumanEval+ 只有 164 道题,p 在 0.87 附近,一个标准误是 2.61 个百分点。一道题就是 0.61 个百分点。
剪到 132 的那三个「赢」:
- MATH-500 +0.80,0.39 个标准误,多做对 4 题
- HumanEval+ +2.43,0.93 个标准误,也是多做对 4 题
- MBPP+ +1.86,0.83 个标准误,多做对 7 题
全在 1 个标准误以内,噪声。四项里唯一跳出噪声的是 GSM8K,1319 道题,掉了 1.89 个百分点,等于 −3.1 个标准误,少做对 25 题。唯一能信的信号,方向朝下。
平均那一列更要小心:它把 164 题的 HumanEval+ 和 1319 题的 GSM8K 等权相加,噪声最大的那项拿到了跟最稳的那项一样的话语权。
还有更要命的一层:这四项全是数学和写代码。对照第 4 节,剪枝在推理上每题只掉 0.6 到 0.8 分,在工具调用上没掉,伤全在知识和幻觉。这张表测的恰好是剪枝伤得最轻的那几个方向,它说「几乎没掉」一点也不奇怪。
读这类表,先问三句:每项多少题;差值几个标准误;测的方向是不是你关心的方向。
7. 这一轮实验自己的毛病
- 裁判是单个大模型。 几天后我用同一个裁判把官方那份重判了一遍,140 题里 6 道分数变了,平均高了 0.06。跟 1.9 的差距比起来不影响结论,可小于 0.1 的差别在这套评分下都别当回事。
- 题量小。 幻觉 30 道、知识 40 道。富集算到个位数的题,期望值 0.88、1.83 这种量级,本身抖得厉害。「3 分及以下算错」这个门槛也是我拍的;换成「0 分才算错」,方向一样,可期望值掉到 0.3 到 0.4,那几个倍数就完全没法读了。
- 原版和剪枝版跑在不同的地方。 官方接口背后用什么精度、什么推理框架我看不到,剪枝版跑在我自己的卡上。1.9 分里理论上混着一点运行环境的差别。好在差距集中在知识和幻觉、工具调用纹丝不动,这个形状不像环境差异造成的。
- 关思考的写法不一样。 本地推理框架关掉模型「先想再答」的那个参数,官方接口不认,会悄悄忽略,返回里照样带着思考用的 token。我在对拍时撞上了这个坑,换成官方接口自己的写法才对齐。如果你也拿官方接口跟本地对比,先看返回里思考 token 是不是 0。
- 变体 C 叠了 2bit 量化,还跑在另一台机器上。 它多了两个变量,但分数跟另外两个打平,三个变体之间两两配对检验都在噪声里(B 对 A 是 −0.09,t = −0.28)。
- 只有一个底座模型。 「剪枝伤知识、不伤工具调用」这件事,我只在这一个模型上验证过,别直接套到别的 MoE 上。
8. 下次想知道「是处理的锅还是原件的锅」,照这个顺序做
- 先问有没有直接对照能拿。 官方接口、没处理过的原件、上一个版本、别人公开的基线。几美元的接口费对几小时的推演,几乎永远划算。
- 跑任何间接统计之前,写下两个预期:假说 A 成立时这个数应该是多少,假说 B 成立时是多少。两个预期一样,这个统计就别跑了。
- 处理手段是确定性的时候(按重要性留前 K 个、用同一份校准数据、同一种量化方案),别拿「多个处理版本一起错」去推原件有问题,它们本来就会一起错。
- 间接统计只拿来证伪和缩小范围。 汇报时说「这批数据跟 X 一致,还没排除 Y,区分它们需要 Z」,别说「结论是 X」。
- 引用剪枝或量化仓库的跑分表之前,每项算标准误、把百分比换回题数、确认它测的方向就是你在乎的方向。
- 想在本地硬塞装不下的原版之前,先翻一下自己的笔记里有没有写过这条路是死的。