想象你是一位果农,果园里有一棵果树疯长了几百根枝条,密密麻麻的绿叶抢走了大量养分,可结出的果子又小又涩。老园丁拿起剪刀,专挑那些细弱、干枯、不结果实的枝条剪掉。枝条少了,养分集中了,果树反而更健康,果子又大又甜。 边缘AI的“剪枝”(Pruning)技术,干的正是园丁的活儿。神经网络为了学得动复杂任务,天生“长得太茂盛”——动辄几百万个参数,可其中大量参数的数值非常小,对最终输出几乎没什么贡献。把这些“冗余枝条”剪掉,模型体积变小、推理变快,精度却几乎不掉。这篇文章会带你从园丁的视角,完整认识剪枝的六个环节:剪枝是什么、怎么判断该剪谁、用什么手法剪、剪完怎么让模型恢复元气、如何和量化打“组合拳”,以及最终怎么在手机和芯片上落地。全程不堆术语,用果园的故事把技术讲透。
学会剪枝,意味着你能在不换硬件、不动训练数据的前提下,把大模型“塞”进手机和嵌入式芯片——这是边缘AI部署工程师最核心的看家本领之一。
可视化演示
剪枝是让模型变瘦变小跑得更快的重要技术,通过去掉不重要的参数来压缩模型节省算力。这篇讲剪枝的基本原理、重要性评... 切换模式查看不同维度。
本节配有交互动效(进入视口后自动加载,约 3KB)。
剪枝基本原理:核心原理 动态展示关键流程与数据流动 交互控件调节参数实时渲染 f(x) = transform(x) 核心概念的可视化呈现
剪枝基本原理
老园丁常说:“果树不是枝越多越好。”一棵疯长的果树,几百根枝条互相抢养分,光合作用效率低下,果子又小又涩。神经网络也一样——为了学会复杂任务,模型在设计时往往“铺得很开”,参数量动辄几十万、几百万甚至上亿,就像一棵没人打理、疯长的树。
深度学习模型天生“过参数化”,意思是参数量远多于任务真正需要的数量。训练结束后你会发现,大量权重的数值非常小,接近于零,它们在推理时贡献的乘积结果几乎可以忽略。剪枝技术(Pruning)的核心思想,就是把这些“不重要的枝条”——也就是数值很小、贡献很低的参数——直接置零或从计算图中删掉。
剪枝带来的好处很直接:存储上,大量零参数可以用稀疏格式压缩,模型文件变小;计算上,零乘以任何数都是零,跳过这些乘法就能降低计算量,加快推理。为了衡量“瘦身程度”,我们引入稀疏率这个概念——被剪掉的参数占总参数的比例。稀疏率越高,模型越“瘦”。
回到果园:稀疏率 30% 的模型,就像老园丁只修剪掉三成细枝的果树,树冠依旧茂盛;稀疏率 90% 的模型则像几乎被剃光的树干,虽然极省养分,但果子还能不能结好,就需要后面几节的技术来保障了。
- 分子 $N_{\text{zero}}$(被剪参数个数)它统计被判定为不重要、置为零的权重数量。就像果园里被锯掉的枯枝数量,每锯掉一根,计数就加一。
- 分母 $N_{\text{total}}$(全部参数个数)它是整个模型或某一层里所有权重的总数,对应果树修剪前全部的枝条数,包括留下的和剪掉的。
- 两者相除得到稀疏率分子分母一比,得到一个 0 到 1 之间的小数,直观反映压缩程度。
重要性评估
老园丁判断该剪哪根枝条,靠三招:一捏粗细,二看位置,三晃果实。AI 判断哪些参数该剪,也需要给每个权重“打分”。最朴素也最常用的打分方法,是看权重本身的“粗细”——幅值。
幅值剪枝(Magnitude Pruning)的逻辑非常符合直觉:一个权重的绝对值越大,说明它对前一层信号的放大或抑制越强,对输出的影响越大;反之,绝对值越小的权重,就像一个营养不良的细枝,剪掉它对整棵树几乎没有影响。所以幅值剪枝的做法是:把所有权重按绝对值从小到大排序,剪掉最小的那批。
但老园丁知道,不同位置的枝条“待遇”不同——靠近主干的大枝不能乱动,末梢的细枝则可以多剪。神经网络也一样,不同层对剪枝的容忍度千差万别。敏感度分析(Sensitivity Analysis)就是逐层地实验:先给某一层设置一个剪枝率剪一剪,观察精度掉多少,从而找出哪些层“碰不得”、哪些层“随便剪”。更精细的做法是借助梯度信号,用“梯度 × 权重”来估计剪掉某个参数后损失函数会上升多少,相当于给每次下剪前做一个“损失预估”。
敏感度分析可以看作给果园画一张“枝干地图”:每个树杈(层)标出“能承受剪几成”。把这些评估方法组合起来,老园丁的剪刀就不再是凭感觉乱剪,而是每一剪都有依据。评估得越准,剪完之后果树恢复得越快。
- 权重 $w_i$第 $i$ 个连接权重,对应果园里一根具体的枝条。每个枝条有自己的粗细。
- 取绝对值 $|w_i|$不管权重是正还是负,只看它的“力度”有多大。一根枝条不论向左长还是向右长,只要粗壮就重要。
- 重要性打分绝对值越大的权重,importance 值越高,越要保留;越小的越先被剪掉。
剪枝类型策略
同样是剪枝,手法可以很不一样。老园丁有时候只摘掉几片黄叶,有时候却要锯掉一整根大枝。对应到模型上,就有了两种截然不同的剪枝类型。
非结构化剪枝(Unstructured Pruning)像“摘叶子”:它单独地把某些权重置零,不管位置在哪。这种方式最灵活,能把稀疏率做到很高,缺点是留下的权重分布得乱七八糟,形成一个不规则的稀疏矩阵,普通的矩阵运算库很难加速——就像树叶摘得零零散散,打扫起来反而更费劲。结构化剪枝(Structured Pruning)则像“锯整枝”:它以通道(Channel)或滤波器(Filter)为单位整块删除,剪完之后矩阵形状依然规整,CPU、GPU、NPU 都能直接受益——类似把一整根枝条从分叉处锯掉,树冠依然整洁有序。
除了剪的“颗粒度”,剪的“节奏”也有讲究。一次性猛剪 80% 的参数,就像把果树剃成光杆,树很可能缓不过来。迭代剪枝(Iterative Pruning)采用“剪一点、恢复一点、再剪一点”的循环:每轮只剪掉一小部分,然后让模型恢复训练,再进入下一轮。这样循序渐进,精度曲线像走楼梯一样平缓下滑,而不是自由落体。
结构化剪枝还是非结构化剪枝,迭代还是一步到位,没有绝对的好坏。老园丁得看天气、看树龄;工程师得看目标硬件支持什么样的稀疏加速、看项目工期允许多少轮训练。这些都是在实际落地时需要权衡的取舍。
- 当前保留率 $r_t$第 $t$ 轮剪枝后仍然保留的参数比例。相当于果树当前剩下的健康枝条占比。
- 每轮剪除比例 $\alpha$每一轮计划剪掉当前剩余参数的百分之几。老园丁每次只动一小撮枝条,比如 10%。
- 下一轮保留率 $r_{t+1}$用当前保留率乘以 $(1-\alpha)$,得到下一轮开始时的保留率。循环往复,直到达到目标稀疏度。
恢复与微调
剪完枝的果树,最怕园丁转身就走。被剪的伤口需要愈合,剩下的枝条需要重新分配养分,这时候必须浇水、施肥、精心养护。模型剪枝之后也一样——被删掉的参数原本承载着一部分“知识”,剩下的参数需要重新调整来弥补损失,这个过程叫做微调(Fine-tuning),也叫重训练。
微调的做法很朴素:在剪枝后的稀疏模型上,用原来的训练数据继续训练若干个 epoch(轮次)。只是这时的“浇水”要格外温柔——学习率(Learning Rate)要调小,通常是原始训练学习率的十分之一甚至更小。原因很好理解:模型已经学会了大部分知识,如果还用大的学习率猛灌,就像给刚修剪的果树浇滚烫的开水,反而会把根烧坏。小学习率让权重在原有基础上做精细的微调,慢慢适应“带伤工作”的状态。
有时候精度会跌得特别厉害,比如一次性剪了太多、剪到了要害层。这时候老园丁的经验是“及时止损”:不要硬着头皮继续训练,而是回到剪枝前保存的 checkpoint,调低剪枝率重新来一遍,或者换一种重要性评估方法。这种“精度挽救”策略在实际工程中非常重要——剪枝率不是越高越好,而是要在精度允许的范围内取最大值。
养护期结束后,被剪过的果树往往比原来更精神——因为养分集中了,剩下的枝条长得更壮。微调后的稀疏模型也常常出现类似现象:精度不仅追回来,有时甚至超过原始模型,这就是剪枝带来的“意外之喜”。
- 剪枝后的参数 $\theta_p$这是经过剪枝、只剩下一部分非零权重的模型参数集合。$\theta_p$ 里的很多元素已经是零,在训练中要保持它们的稀疏状态。
- 对数概率项 $-\log p(y_i \mid x_i)$模型给正确类别打分的负对数概率。打分越准,这个值越小。整体相当于“这次剪枝后,你答对了多少题”。
- 求平均 $\frac{1}{N}\sum_{i=1}^{N}$对所有样本的损失取平均,得到一个整体指标。微调就是在不断最小化这个指标,让精度逐步爬升。
与量化配合
老园丁的果园在山坡上,土薄水少,果树还得搬家到更轻的花盆里才能运下山。剪枝解决了“枝条太多”的问题,但每一根留下的枝条依然很“重”——每个权重都用 32 位浮点数存储。这时候,另一项模型压缩技术——量化(Quantization)登场了:它把参数从 32 位浮点数变成 8 位甚至 4 位整数,相当于把每根枝条从实心木头换成轻质塑料。
剪枝和量化是一对完美的“组合拳”,它们各自管一个维度:剪枝管“数量”,把参数个数砍掉,让计算次数变少;量化管“位宽”,把每个参数的存储位数压低,让每次计算更快、每字节存得更多。两者的流水线顺序通常是先剪枝、后量化:先剪掉冗余,再对剩下的参数做低比特表示。这样组合下来,模型体积可以压缩到原来的十分之一甚至更低,推理速度大幅提升。
不过天下没有免费的午餐,老园丁也明白:花盆换得太小,根可能舒展不开。量化会带来一定的精度损失,剪枝也会带来精度损失,两个损失叠加时,需要仔细权衡。部署工程师要做一个“三角平衡”:压缩率要够高、精度要能接受、硬件的算子库要支持这种组合方案。比如某些 NPU 对 4 位量化支持得好但要求结构规整,那就优先用结构化剪枝配 4 位量化;如果硬件没有稀疏加速单元,非结构化剪枝的意义就大打折扣。
把“剪数量”和“降位宽”合起来看,老园丁的果树终于装进了轻便的花盆,可以稳稳当当地运下山,种到手机、摄像头和智能音箱那片“贫瘠但广阔”的土地上。
- 原始体积 $b \times N$$b$ 是原始位宽(如 32 位),$N$ 是原始参数个数。两者相乘就是模型原始的存储体积,相当于果树满枝时的总体积。
- 压缩后体积 $b_q \times N_p$$b_q$ 是量化后的位宽(如 8 位),$N_p$ 是剪枝后剩下的参数个数。剪枝和量化各减一项,体积双重缩水。
- 两者相除得到压缩比压缩比越大说明瘦身效果越好。比如原始 32 位、剪掉一半参数、再量化到 8 位,压缩比就是 8 倍。
端侧落地
老园丁的终极目标,是把果树种到山坡上那片土壤贫瘠、水源紧张的荒地里——对应到工程上,就是把模型部署到手机、摄像头、嵌入式芯片这些算力有限、内存紧张、电池宝贵的“边缘设备”上。端侧落地,是检验剪枝价值的最终考场。
剪枝带来的收益在这里体现得淋漓尽致。存储上,模型文件从几百 MB 缩到几十 MB,App 安装包和固件体积显著下降;推理上,计算量(FLOPs)随剪枝率近似线性下降,单次推理延迟缩短,功耗也随之降低。以 MobileNetV3 为例,在 ImageNet 上做 30% 的结构化剪枝并微调后,精度仅下降约 0.3%,而端侧推理延迟可以降低约 25%——多出来的电量,足够让智能摄像头多工作好几个小时。
工程落地离不开工具链支持。PyTorch 内置了 torch.nn.utils.prune 剪枝模块,支持幅值剪枝和自定义剪枝方法;剪完的模型可以导出为 ONNX,再交给 TensorRT、MNN、TFLite 等推理引擎做稀疏化加速或量化编译。选型建议上,如果目标是手机 SoC 上的 NPU,优先结构化剪枝配合 INT8 量化;如果是纯 CPU 推理,可以尝试高稀疏率的非结构化剪枝,配合稀疏算子库获得极致压缩。
从疯长的果树到山坡上健康的小树,剪枝的六个环节环环相扣:理解原理让你知道为什么要剪,重要性评估告诉你剪谁,类型策略决定怎么剪,微调负责剪后恢复,量化配合进一步瘦身,最终在端侧落地收获成果。
- 原始计算量 FLOPs$_{\text{原始}}$模型剪枝前完成一次推理需要的浮点运算次数。相当于果树满枝时,蜜蜂采遍所有花朵要飞的路程。
- 剪枝后计算量 FLOPs$_{\text{剪枝后}}$被剪枝的参数不再参与计算,乘法次数大幅减少,相当于蜜蜂只拜访留下的花朵。
- 两者相除得到加速比加速比越高,端侧推理越快,越省电。这就是老园丁把果园搬上山坡的底气——树小了,果子一个不少,山路也好走了。
AI 应用场景
手机端人脸检测模型瘦身
阶段:端侧部署优化
解决的问题:传统人脸检测模型上百 MB,直接放进手机 App 会导致安装包臃肿、启动加载慢、推理时发热耗电。用结构化剪枝去掉不重要的卷积通道,再配合 INT8 量化,模型体积可压缩到原来的 1/6,精度损失控制在 1% 以内。
具体案例:某美颜相机 App 将 120 MB 的人脸关键点模型剪枝量化到 20 MB,在骁龙 8 系列手机上单帧检测延迟从 120 ms 降到 40 ms,用户自拍美颜更加跟手,夜间待机功耗明显改善。
智能摄像头目标检测
阶段:模型压缩与推理加速
解决的问题:智能摄像头需要在设备端实时识别行人、车辆和异常事件,但嵌入式芯片算力只有服务器的几十分之一。通过敏感度分析确定各层可承受的剪枝率,对 YOLO 系列检测模型做迭代结构化剪枝,再导出到 TensorRT 加速。
具体案例:某安防厂商在边缘盒子(Jetson Orin NX)上部署剪枝后的 YOLOv5s,mAP 仅下降 0.8%,推理帧率从 25 FPS 提升到 45 FPS,一台设备可以同时分析两路高清视频流,硬件采购成本直接减半。
嵌入式语音唤醒词识别
阶段:超低功耗部署
解决的问题:智能音箱和 TWS 耳机的唤醒词模型必须常驻运行,功耗预算只有几毫瓦。非结构化剪枝把模型稀疏率做到 85%,再用稀疏算子库加速,配合 4 位量化,把模型压进几百 KB 的 SRAM。
具体案例:某智能耳机厂商将 2.3 MB 的唤醒词模型剪枝量化到 180 KB,集成到 MCU 上,唤醒延迟从 800 ms 降到 300 ms,待机功耗下降 40%,一次充电续航从 5 小时延长到 8 小时。
Python 演示
import numpy as np def make_data(n=600, dim=8, seed=42): rng = np.random.default_rng(seed) x = rng.standard_normal((n, dim)) y = (x[:, 0] + 0.5 * x[:, 1] - 0.3 * x[:, 2] > 0).astype(int) return x, y def make_mlp(dims=(8, 16, 8, 2), seed=7): rng = np.random.default_rng(seed) model = [] for i in range(len(dims) - 1): model.append({ "W": rng.standard_normal((dims[i], dims[i + 1])) * 0.3, "b": np.zeros((1, dims[i + 1])) }) return model def forward(model, x): caches = [x] a = x for i, layer in enumerate(model): z = a @ layer["W"] + layer["b"] a = z if i == len(model) - 1 else np.maximum(z, 0) caches.append(a) return a, caches def train_step(model, x, y, lr): out, caches = forward(model, x) m = len(y) p = np.exp(out - out.max(axis=1, keepdims=True)) p /= p.sum(axis=1, keepdims=True) p[np.arange(m), y] -= 1 grad = p / m for i in range(len(model) - 1, -1, -1): layer = model[i] grad_w = caches[i].T @ grad grad_b = grad.sum(axis=0, keepdims=True) if i > 0: grad = (grad @ layer["W"].T) * (caches[i] > 0) layer["W"] -= lr * grad_w layer["b"] -= lr * grad_b def train(model, x, y, steps=300, lr=0.05): for _ in range(steps): train_step(model, x, y, lr) def accuracy(model, x, y): out, _ = forward(model, x) return np.mean(out.argmax(axis=1) == y) def prune_by_magnitude(model, ratio): all_w = np.concatenate([layer["W"].ravel() for layer in model]) threshold = np.percentile(np.abs(all_w), ratio * 100) masks = [] for layer in model: mask = np.abs(layer["W"]) >= threshold masks.append(mask) layer["W"] *= mask return masks def apply_masks(model, masks): for layer, mask in zip(model, masks): layer["W"] *= mask def sparsity(model): total = sum(layer["W"].size for layer in model) zero = sum(np.sum(layer["W"] == 0) for layer in model) return zero / total def main(): x, y = make_data() split = int(len(x) * 0.8) x_tr, x_te = x[:split], x[split:] y_tr, y_te = y[:split], y[split:] model = make_mlp() train(model, x_tr, y_tr, steps=500, lr=0.05) acc_full = accuracy(model, x_te, y_te) masks = prune_by_magnitude(model, 0.7) acc_pruned = accuracy(model, x_te, y_te) train(model, x_tr, y_tr, steps=300, lr=0.01) apply_masks(model, masks) acc_ft = accuracy(model, x_te, y_te) print(f"原始模型 : 测试精度 {acc_full:.4f}") print(f"剪枝70%后 : 稀疏度 {sparsity(model):.2%}, 精度 {acc_pruned:.4f}") print(f"微调恢复后 : 稀疏度 {sparsity(model):.2%}, 精度 {acc_ft:.4f}") if __name__ == "__main__": main()
model = make_mlp()初始化一个 8→16→8→2 的四层神经网络,相当于种下一棵“枝繁叶茂”的小树。prune_by_magnitude(model, 0.7)调用幅值剪枝,把绝对值最小的 70% 权重置零,同时记录掩码,防止微调时零权重“复活”。np.percentile(np.abs(all_w), ratio * 100)把所有权重拼在一起,按绝对值排序取 70% 分位数作为剪枝阈值。layer["W"] *= mask用布尔掩码做逐元素相乘,小于阈值的权重全变成零,完成“锯枝”。train(model, x_tr, y_tr, steps=300, lr=0.01)用 0.01 的小学习率微调 300 步,这是剪枝后“浇水施肥”的温柔恢复过程。apply_masks(model, masks)微调结束后再次套用掩码,保证最终的稀疏度依然是 70%,模型保持“苗条”体形。sparsity(model)统计模型中零权重占比,验证剪枝效果是否达标。
常见误区
误区剪枝率越高模型越小越快,那我直接把 95% 的参数都剪掉,岂不是最优解?
正解剪枝率不是越高越好。每棵树的冗余是有限的,剪到一定程度就会伤及“主干”——那些承载核心特征的参数。一次性剪掉 95% 的参数,模型精度往往直接崩盘,即使微调也难以挽回。实际工程中剪枝率通常在 30%~80% 之间,需要通过实验绘制“剪枝率-精度”曲线,找到精度还能接受的最高剪枝率。
为何常见:人很容易被“免费午餐”诱惑——看到剪枝能压缩模型就以为力度越大赚得越多,忽略了模型的冗余是有上限的。
误区剪枝只是去掉一些不重要的参数,剩下的参数还在,精度应该不会掉,所以不需要再训练。
正解剪枝会破坏参数之间原有的协同关系。打个比方,一座桥抽掉几根钢索,剩下的钢索受力会突然变大,必须重新调整受力分布。被剪枝影响的模型必须通过微调,让剩余权重重新适配,才能把精度恢复到可接受的水平。不微调直接部署,精度损失通常会放大好几倍。
为何常见:初学者看到“不重要的参数”这个说法,会误以为它们从头到尾都可有可无,没意识到它们其实参与着整体协作。
误区剪枝就是让权重变稀疏,稀疏了计算量就少了,所以任何设备上都会变快。
正解非结构化剪枝产生的是不规则的稀疏矩阵,普通 CPU/GPU 的矩阵乘库是为稠密矩阵优化的,不会自动跳过零元素。只有用了支持稀疏张量运算的专用库(如 NVIDIA 的 cuSPARSE、Intel 的稀疏加速指令)或专用 NPU,才能真正吃到加速红利。在普通硬件上,非结构化剪枝可能只见体积压缩、不见速度提升。
为何常见:人们习惯把“计算量”和“运行时间”直接画等号,忽略了硬件对计算模式的支持才是决定实际速度的关键。
误区模型压缩手段太多了,既然剪枝已经能把模型减小,那量化就没必要了,两个一起用会很复杂。
正解剪枝和量化其实是正交的,一个管参数数量,一个管参数位宽。先剪枝把数量砍下来,再量化把位宽降下去,两者叠加能达到单用任何一种手段无法企及的压缩效果。工程上“剪枝 + INT8 量化”已成为端侧部署的标准流水线,工具链(如 PyTorch → ONNX → TensorRT)已经天然支持这种组合。
为何常见:入门者往往把各种技术看成互斥的方案,没有意识到它们针对的是不同的资源瓶颈,可以像组合技一样叠加使用。
面试题
Q1. 模型剪枝的核心目标是什么?
- A.增加参数量以提升表达力
- B.去掉不重要参数压缩模型← 正确答案
- C.用更多数据增强泛化能力
- D.换用更大的损失函数权重
答案:B。剪枝的核心是删掉对输出贡献小、不重要的参数,从而减小模型体积、降低计算量。A 方向正好相反;C 属于数据增强;D 是调整训练超参,都与剪枝无关。
Q2. 幅值剪枝挑选删除对象的主要依据是?
- A.权重绝对值的大小← 正确答案
- B.权重本身的正负号
- C.权重所在的网络层数
- D.随机抽取任意权重
答案:A。幅值剪枝认为绝对值小的权重对输出影响小,按绝对值从小到大删除,就像园丁先剪细弱枝条。正负号只代表激励或抑制方向,层数和随机抽取都不是幅值剪枝的依据。
Q3. 非结构化剪枝在硬件加速上最大的短板是什么?
- A.模型体积反而会变大很多
- B.稀疏矩阵不规则难以加速← 正确答案
- C.训练时间会显著不断增加
- D.完全无法部署到任何设备
答案:B。非结构化剪枝把零散权重置零,产生不规则的稀疏矩阵,普通矩阵运算库无法高效跳过零元素,需要专用稀疏加速支持。体积只会变小,训练时间通常也不受剪枝影响,说“完全无法部署”过于绝对。
Q4. 剪枝后微调通常采用什么样的学习率?
- A.比训练时更大的学习率
- B.比训练时更小的学习率← 正确答案
- C.与训练时完全相同的学习率
- D.每轮随机变化的学习率
答案:B。剪枝后的模型已有较好的知识,用大学习率猛更新会破坏原有参数,就像给刚剪完枝的树浇开水。通常用原始学习率的 1/10 甚至更小,让权重温柔地重新适配,恢复精度。
Q5. 结构化剪枝相比非结构化剪枝的最大优势是什么?
- A.单个权重删除更灵活更精细
- B.剪后形状规整便于硬件加速← 正确答案
- C.完全不需要任何恢复性训练
- D.能保证精度比原来更高一些
答案:B。结构化剪枝按通道或滤波器整块删除,剪完的矩阵形状规整,CPU/GPU/NPU 都能高效执行。非结构化剪枝才是更精细灵活的,但代价是稀疏矩阵不规则;两类剪枝都需要微调,都不保证精度提升。
Q6. 敏感度分析在剪枝中的主要用途是什么?
- A.计算损失函数对输入数据的梯度
- B.找出各层可承受剪枝率的差异← 正确答案
- C.测量模型在 GPU 上的推理耗时
- D.决定训练时的批量大小和学习率
答案:B。不同层对剪枝的容忍度不同,有的层剪一点精度就崩,有的层剪一半都没事。敏感度分析逐层实验,画出“剪枝率-精度”曲线,帮工程师为每层定制剪枝率,这正是老园丁逐枝试探的工程版。
Q7. 迭代式剪枝相比一次性大幅剪枝的优势是什么?
- A.完全没有精度损失且实现简单
- B.边剪边恢复避免精度骤降← 正确答案
- C.不需要任何训练数据即可完成
- D.只能用于极小型的神经网络
答案:B。迭代剪枝每轮只剪一小部分,然后微调恢复,再进入下一轮,精度曲线平缓下滑,不容易崩盘。它仍然需要训练数据,也会有一定精度损失,并不仅限于小型网络,所以 A、C、D 都不成立。
Q8. 下列哪些属于权重重要性评估方法?
- A.权重幅值大小排序评估← 正确答案
- B.逐层敏感度的分析测试← 正确答案
- C.梯度与权重乘积估计← 正确答案
- D.数据增强扩充训练样本
答案:ABC。幅值(看绝对值大小)、敏感度(逐层测试剪枝率容忍度)、梯度信号(梯度×权重估计损失变化)都用于判断哪些参数该剪。数据增强是提升泛化能力的训练技巧,与重要性评估无关。
Q9. 关于剪枝与量化配合使用,下列说法正确的是?
- A.两者可以串联组合使用← 正确答案
- B.剪枝减少参数数量的规模← 正确答案
- C.量化降低每个参数位宽← 正确答案
- D.二者互斥只能二选其一
答案:ABC。剪枝管数量、量化管位宽,两者正交互补,可以“先剪枝后量化”串联使用,分别从参数个数和存储精度两个维度压缩模型,压缩比相乘。D 的说法是错误的,两者并不互斥。
Q10. 剪枝给端侧部署带来的主要收益有哪些?
- A.减少模型的存储体积← 正确答案
- B.降低推理的计算开销← 正确答案
- C.提升端侧推理的速度← 正确答案
- D.一定提高模型精确度
答案:ABC。剪枝让模型文件变小、计算量下降、推理变快,这些都是端侧部署最关心的收益。但剪枝不一定提高精度,恰恰相反,它通常会带来小幅精度损失,需要通过微调找回,所以 D 不选。