想象你有一个塞得满满当当的衣柜:100 件上衣、40 条裤子,但每天真正穿到的不过二三十件。那些常年不动的旧 T 恤、过时的牛仔裤,实实在在占着柜子空间,让你找衣服又慢又烦。整理衣柜的第一步,就是把不常穿的衣服挑出来捐掉——柜子空了,找衣服快了,生活轻松了。 神经网络里的情形几乎一模一样。一个大型模型动辄上亿参数,但大量权重的数值接近零,对预测结果几乎没有任何贡献。它们像衣柜深处那件起球的毛衣,放着占地方,丢了也不心疼。把“不重要的权重”置为零,模型依然能正常工作,但体积更小、推理更快——这就是模型稀疏化(Sparse)。 本文要讲清楚稀疏化的完整路线图:什么是稀疏率、非结构化与结构化稀疏怎么选、剪枝策略与阈值设定、稀疏矩阵如何存储和加速,以及稀疏化与量化这对“黄金搭档”怎么组合。全程用“整理衣柜”这个生活场景作比喻,让你像收拾衣柜一样,把模型的减肥手术看得明明白白。
掌握稀疏化设计方法,是 AI 从业者做模型压缩、边缘部署和推理降本的看家本领。学完你能独立制定剪枝方案、评估精度损失、落地真实加速,让大模型在消费级硬件上跑起来。
可视化演示
展示非结构化与结构化稀疏模式、稀疏率对精度的影响以及稀疏推理加速效果,理解模型压缩的核心技术。
本节配有交互动效(进入视口后自动加载,约 3KB)。
稀疏模式对比 非结构化:随机置零,稀疏率高但难加速 结构化:按通道/块置零,硬件友好可加速 Sparsity = Zeros / Total 稀疏率定义
稀疏化基础概念
整理衣柜的第一步,不是动手扔,而是搞清楚哪些衣服值得留。你翻出 100 件上衣,真正常穿的可能只有 20 件——剩下 80 件一直在占地方。神经网络里的情形几乎一样:一个全连接层动辄上百万元素,其中大量权重数值接近 0,对输出的贡献微乎其微。
把这些“接近没用”的权重置为 0,模型依旧能正常预测,但存储和计算都轻松不少。这种把密集矩阵变成稀疏矩阵的操作,就叫模型稀疏化(Sparse)。稀疏化的第一步,是量化“到底有多稀疏”。
假设权重矩阵 \(W\) 有 \(m\) 行 \(n\) 列。\(\|W\|_0\) 表示矩阵里非零权重的个数,叫作 L0 范数。用 1 减去非零占比,就得到稀疏率 \(S\),它直接反映了压缩潜力。
当你回答“衣柜只留 20% 的衣服”时,你已经说清了空间的占用情况。稀疏率就是模型的“留衣比例”,它是一个起点指标,后面所有剪枝决策都会围绕它展开。
- 权重矩阵形状设全连接层的权重矩阵为 \(W \in \mathbb{R}^{m \times n}\),它共有 \(m \times n\) 个可训练参数。
- 统计非零个数\(\|W\|_0\) 统计矩阵中非零元素的总个数,这是 L0 范数的定义。
- 计算非零密度非零元素个数除以总元素数,得到模型中仍然保留的比例。
- 得到稀疏率用 1 减去密度,就是被剪枝置零的比例,\(S\) 越大模型越“瘦”。
非结构化稀疏
整理衣柜时,如果只是东一件西一件地抽走旧 T 恤、褪色牛仔裤,清掉的位置零散、没有规律,这就是“非结构化”整理。模型里对应的是逐参数独立剪枝——剪枝单位小到单个权重。
对每个权重单独打分:绝对值大说明它对结果影响不小,保留;绝对值很小说明它可有可无,置零。实现上用一个掩码矩阵 \(M\) 来记录决定,\(M\) 中为 1 的位置保留权重,为 0 的位置清零。
非结构化稀疏的优点是“精准打击”:同样稀疏率下,它挑走的都是最没用的参数,精度损失通常最小。缺点是零散分布:权重像散落一地的豆子,硬件读取时要在内存里跳来跳去,难以直接加速。
东一件西一件地扔完衣服,衣柜确实多出几处空隙,但没法合并成可用的整块空间。这就是非结构化稀疏的真实写照——省了存储,却难换加速。
- 掩码矩阵\(M\) 与 \(W\) 形状完全相同,每个位置只取 0 或 1。
- 阈值判断权重绝对值超过 \(\tau\) 被认为重要,掩码记为 1,否则为 0。
- 逐元素乘法\(\odot\) 运算让 \(W\) 与 \(M\) 同位相乘,掩码为 0 的权重直接变成 0。
结构化稀疏
另一种更利落的整理法:干脆清空整格抽屉,把某个区域的所有衣服全部捐掉。空间立刻变成整齐的一块。这就是结构化稀疏——不零散挑,成大块地删。
在卷积网络里,“一格”的最小单位往往是一个输出通道,也就是一个卷积核。判断它是否值得留,可以把该卷积核覆盖的所有权重绝对值相加,得到一个“重要分数”。分数太低,说明这个卷积核几乎不响应任何输入。
结构化稀疏产生的零是“成块”的。CPU、NPU 可以直接跳过这些零块;若按通道剪,还能把整个通道从计算图中摘除,FLOPs 真正下降,不需要特殊存储格式。
一个格一个格地清空,柜子立刻变得井井有条。AI 加速器最喜欢的正是这种“一眼就看得出空在哪”的结构化稀疏,因为它能实实在在地把稀疏变成推理速度。
- 四维权重索引卷积核权重 \(W_{c,c',k_1,k_2}\) 由输出通道 \(c\)、输入通道 \(c'\)、卷积核高宽 \((k_1, k_2)\) 四个维度索引。
- 通道重要性打分把第 \(c\) 个卷积核的全部权重绝对值相加,得到该通道的重要分数。
- 整通道置零分数低于阈值,该通道的掩码置 0,对应权重全部清零。
剪枝策略
确定了“剪哪里”的粒度,还要决定“怎么剪”。整理衣柜时你面临两种思路:每个抽屉单独判断扔什么,还是站在全局打量整套衣柜再统一动手。剪枝对应着局部与全局两条路线。
局部剪枝逐层设阈值,各层独立决策,实现简单。全局剪枝把整个模型的所有权重绝对值拉成一条长序列,统一取分位数作为阈值,把稀疏预算“补贴”给冗余最大的层。
工程上还流行“迭代剪枝”:训练 → 剪掉一小部分 → 微调恢复精度 → 再剪,多轮循环把稀疏率稳定抬到 90% 以上。每轮只剪一点点,模型不至于“伤筋动骨”,最终精度远好于一次性下狠手。
衣柜整理也可以分几轮:先扔最不喜欢的,观察一星期,再扔一批。迭代剪枝正是这种“渐进式断舍离”,让稀疏化的每一步都温和可控。
- 跨层权重集合把每一层的权重 \(W^{(l)}\) 全部取出,组成一个绝对值序列。
- 取全局分位数对该序列取 \(1-S\) 分位数,得到全局阈值 \(\tau_g\)。
- 指示函数设掩码权重绝对值达到阈值就保留,否则丢弃。
稀疏率设定
稀疏率到底设多少?问法一如“衣柜到底扔多少衣服”:扔太少省不了空间,扔太多冬天没有厚外套穿。设定稀疏率的本质,是寻找精度与收益的最佳平衡点。
实践中最直接的方法是做稀疏率扫描:分别试 50%、70%、80%、90%、95%,记录验证集精度,画出一条“精度-稀疏率”曲线。曲线上通常存在一个明显拐点。
经验规则有三:第一,大模型冗余多、更耐受高稀疏率;第二,小模型每剪一点都有明显代价;第三,更稳妥的做法是由部署预算倒推——先定存储和时延红线,再选满足精度要求的最稀疏方案。
衣柜也有“拐点”:过了某个数量,每天早上都会面临“没衣服穿”的崩溃。设定稀疏率,就是选在崩溃到来前还能承受的那条线。
- 精度损失\(\Delta \text{Acc}\) 是稀疏后相对原始模型的精度下降值。
- 稀疏密度比\(S/(1-S)\) 随 \(S\) 增大而加速增长,是刻画“剪过头”的核心指标。
- 指数放大\(\gamma>1\) 使得高稀疏区间的损失增长更加陡峭。
存储计算加速
衣服是扔掉了,但如果衣柜隔板保持原样,空间依然被旧布局占着。真要把压缩比落到实处,得换一种收纳方式——用“压缩存储”直接按保留清单收纳。
最经典的稀疏矩阵存储格式是 CSR(Compressed Sparse Row,压缩稀疏行)。它用三个一维数组取代完整矩阵:values 顺序存放非零元素、col_idx 记录每个非零元素的列号、row_ptr 记录每一行第一个非零元素在 values 中的位置。
计算加速围绕“跳过零”展开:稀疏矩阵乘法只对非零项做乘累加;块级稀疏(如 \(4 \times 4\) 块)还会整块跳过全零块,配合 SIMD 或张量核心实现真正的倍数级加速。
CSR 就像衣柜的“索引标签”:不再把每件衣服摊开,只记下“哪一格有什么”。找衣服时查索引直接命中,省时省力——这正是稀疏推理的日常。
- 非零元素数\(NZ\) 表示矩阵中非零元素的个数。
- values 数组按行优先顺序存放所有权重非零值。
- 列索引数组col_idx 与 values 一一对应,记录每个非零值原在第几列。
- 行偏移数组row_ptr 记录每行起始下标,最后补一个总长度哨兵。
协同优化
整理的最高境界是组合拳:既把不重要的衣服捐掉(稀疏化),又把留下的衣服叠成小方块(量化)。稀疏解决“哪些位置不存”,量化解决“每个值占多少 bit”,两者相乘叠加。
假设权重矩阵有 \(m \times n\) 个参数,每个权重用 \(b\) bit 存储。先稀疏到 \(S\),只有 \(1-S\) 比例非零;再对非零值做低比特量化,总存储公式如下。
工业落地常用“量化 + 稀疏”组合,例如对 7B 大模型做 50% 稀疏 + 8bit 量化,显存占用大幅下降。训练阶段还会使用量化感知或稀疏感知训练(如 STE 直通估计器),让模型在压缩后的结构上重新对齐权重。
衣柜的最终形态:空间是叠出来的,东西是按清单存放的。模型也一样——该扔的扔(稀疏)、该叠的叠(量化),这一对黄金搭档,是边缘 AI 部署中最实在的降本方案。
- 原始占用每个权重占 \(b\) bit,共 \(m \times n\) 个,除以 8 得到字节数。
- 稀疏折扣只有 \(1-S\) 比例的参数非零、需要保存。
- 量化折扣\(b\) 从 16 降到 8,存储再减半。
AI 应用场景
大模型推理降本
阶段:推理部署与优化
解决的问题:大模型参数量大、显存占用高,传统方案需要多张显卡才能部署。采用 50% 稀疏 + 8bit 量化后,非零参数减半、位宽减半,显存理论下降约 75%,单卡即可完成推理。
具体案例:某团队将 7B 对话模型从 FP16(约 14GB)压缩为 8bit + 50% 稀疏(约 3.5GB),部署到单张消费级显卡,服务成本下降近一半,响应时延同步降低。
边缘端视觉模型加速
阶段:模型压缩与边缘部署
解决的问题:手机和嵌入式设备算力有限,直接跑 YOLO 等检测模型帧率不足。结构化通道剪枝把冗余卷积核整块删除,FLOPs 真实下降,帧率显著提升。
具体案例:在安防摄像头芯片上,对 YOLOv5s 做通道级结构化稀疏,精度仅下降 0.8%,推理时延从 35ms 降到 22ms,功耗同步降低。
推荐系统模型瘦身
阶段:在线推理与存储优化
解决的问题:CTR 预估模型 embedding 层巨大但高度稀疏。利用非结构化稀疏 + CSR 存储,把权重矩阵压缩数倍,线上内存占用和响应时间均明显下降。
具体案例:某电商推荐模型从 500MB 压缩到约 120MB,单机 QPS 提升 2 倍,AUC 基本持平。
Python 演示
import numpy as np def prune_by_threshold(W, rate): # 非结构化剪枝: 按绝对值阈值, 把小于阈值的权重置 0 threshold = np.percentile(np.abs(W), rate * 100) mask = np.abs(W) >= threshold return W * mask def prune_by_row(W, rate): # 结构化剪枝: 按行重要性排序, 直接剪掉整行 score = np.sum(np.abs(W), axis=1) k = int(rate * len(score)) drop_idx = np.argsort(score)[:k] Wp = W.copy() Wp[drop_idx, :] = 0.0 return Wp def sparsity_ratio(W): # 返回稀疏率: 被置为 0 的参数占比 total = W.size nz = np.count_nonzero(W) return 1.0 - nz / total def csr_compress_ratio(W): # 估算 CSR 格式相比全矩阵存储的压缩比 n, m = W.shape nz = max(np.count_nonzero(W), 1) return n * m / (2 * nz + n + 1) def main(): np.random.seed(0) W = np.random.randn(64, 64) * 0.5 print("=== 非结构化剪枝 ===") for rate in [0.3, 0.5, 0.7, 0.9]: Wp = prune_by_threshold(W, rate) print(f"rate={rate:.0%}: sparse={sparsity_ratio(Wp):.0%}, " f"compress={csr_compress_ratio(Wp):.1f}x") print("=== 结构化剪枝(按行) ===") Wp = prune_by_row(W, 0.5) print(f"rate=50%: sparse={sparsity_ratio(Wp):.0%}, " f"compress={csr_compress_ratio(Wp):.1f}x") if __name__ == "__main__": main()
threshold = np.percentile(np.abs(W), rate * 100)取绝对值第 rate 百分位数当作剪枝阈值,低于它的权重将被清零mask = np.abs(W) >= threshold构造 0/1 掩码,保留绝对值大于等于阈值的位置return W * mask掩码与权重逐元素相乘,实现“不重要位置置零”score = np.sum(np.abs(W), axis=1)按行求绝对值之和,作为每行的“重要分数”drop_idx = np.argsort(score)[:k]找出分数最低的那 k 行,即最不重要的行Wp[drop_idx, :] = 0.0把选中行全部清零,完成结构化剪枝np.count_nonzero(W)统计非零元素个数,用来计算稀疏率
常见误区
误区稀疏率当然是越高越好,95% 以上能省最多的存储和算力,模型又小跑得又快,何乐而不为?
正解稀疏率一味拉高,精度会在拐点后急速滑坡。精度-稀疏率曲线通常在 80%-90% 区间还是缓坡,越过某个阈值立刻变陡。正确做法是把验证集精度当作硬约束,在既定精度预算内选择最高稀疏率。就像衣柜不是扔得越空越好,你得保证明天有衣服穿。
为何常见:省存储的收益是直白的数字游戏,很容易让人忽略“精度-稀疏率”之间的非线性关系。
误区非结构化稀疏和结构化稀疏只是剪枝粒度的视觉差异,最终精度和部署效果应该差不多。
正解两者在精度和加速上差异巨大。非结构化稀疏保留的权重位置零散,普通硬件无法跳块计算,通常只能省存储;结构化稀疏按通道、行、列成块删除,能真正减少 FLOPs,是硬件加速的前提。
为何常见:论文里的稀疏率数字一样,读者容易忽略“硬件是否能利用稀疏”这一层关键差异。
误区权重剪完模型就算压缩完成了,直接拿去部署就行,微调纯属多余步骤。
正解直接部署剪枝模型通常有明显精度损失。剪枝改变了权重分布和激活统计,需要通过微调让剩余权重适应新结构。“训练—剪枝—微调”循环是标准流程。就像整理完衣柜后,你得重新规划挂衣顺序才能高效使用。
为何常见:整理东西给人的直觉是“扔完收工”,忘了模型是一个需要重新训练适应的系统。
误区稀疏化都已经省了那么多存储,再量化就是多此一举。
正解稀疏化只砍“数量”,量化砍“单位体积”。非零值若仍用 16bit 存,存储依然可观。稀疏 80% + 8bit 量化后,体积是原来的 10%,两类收益近似相乘。
为何常见:只看到稀疏矩阵“很多格是空的”,没意识到留下来的格子仍然占据体积。
误区只要模型变稀疏了,在什么硬件上推理都会自动变快。
正解稀疏模型要快,依赖硬件和算子库的配合:比如支持跳零的稀疏卷积、结构化稀疏对应的张量核心算子。普通稠密算子跑稀疏模型,计算量没有减少,速度自然不变。
为何常见:“模型小等于计算快”是日常直觉,但实际速度取决于底层算子是否感知稀疏。
面试题
Q1. 模型稀疏化的核心思想是什么?
- A.把不重要的权重置为 0← 正确答案
- B.把所有权重变成更小
- C.增加更多的参数
- D.降低训练的批大小
答案:A。稀疏化的核心是识别不重要权重并置零,减少存储与计算。B 描述的是量化而非稀疏化;C 与目标相反;D 与训练设置无关。
Q2. L0 范数的含义是什么?
- A.所有权重平方和的平方根
- B.权重矩阵里非零元素的个数← 正确答案
- C.矩阵中最大值与最小值之差
- D.所有权重绝对值的平均值
答案:B。L0 范数统计矩阵中非零元素个数。A 是 L2 范数,D 是 L1 平均,C 是取值范围,均与 L0 无关。
Q3. 剪枝后通常需要做什么来恢复精度?
- A.增大学习率重新训练
- B.微调(fine-tune)模型← 正确答案
- C.往模型里加回权重
- D.把验证集换成更大比例
答案:B。剪枝改变了权重分布,需要通过微调让剩余权重适应稀疏结构。A 盲目增大学习率会破坏已有权重;C 等于撤销剪枝;D 与精度恢复无关。
Q4. 非结构化稀疏的主要短板是什么?
- A.稀疏率无法设置的很高
- B.权重零散,硬件加速困难← 正确答案
- C.会破坏所有卷积的计算
- D.精度一定比结构化更差
答案:B。非结构化稀疏的权重零散分布,硬件内存访问不连续,难以跳块加速。A 不正确,它可以做到很高稀疏率;C 夸大其词;D 恰恰相反,非结构化通常精度损失更小。
Q5. 结构化稀疏通常如何判断一个卷积通道是否需要剪掉?
- A.该通道输出特征图尺寸大小
- B.该通道权重绝对值之和打分← 正确答案
- C.该通道前后层数的多少
- D.该通道在模型中的位置顺序
答案:B。结构化的常见做法是把某个卷积核覆盖的所有权重绝对值求和,分数低于阈值就整通道剪除。A、C、D 都与通道权重本身的重要性无关。
Q6. 下列哪些属于结构化稀疏的形式?
- A.整行整列权重置零← 正确答案
- B.按通道把滤波器剪掉← 正确答案
- C.单个权重独立置零
- D.剪掉整个卷积核块← 正确答案
答案:ABD。结构化稀疏指按行、列、通道或块为单位成组剪除,A、B、D 都符合。C 是逐参数判断,属于非结构化稀疏。
Q7. CSR 稀疏存储相比原始稠密矩阵主要省了什么?
- A.省去所有零元素的存储← 正确答案
- B.省去非零元素的索引
- C.将权重从浮点变成整数
- D.减少模型的层数深度
答案:A。CSR 只存非零值以及必要的列索引、行指针,零元素不再占空间。B 说反了,CSR 反而要额外存索引;C 是量化;D 与存储格式无关。
Q8. 关于稀疏化与量化协同优化,哪些说法正确?
- A.稀疏决定哪些位置不存← 正确答案
- B.量化决定每个值占多少位← 正确答案
- C.两者的收益可以近似相乘← 正确答案
- D.二者不能同时用于一个模型
答案:ABC。稀疏化砍“数量”,量化砍“单位体积”,两者作用维度不同、可以同时使用,存储收益近似相乘。D 说法错误。
Q9. 全局剪枝相比局部剪枝的优势通常是?
- A.每层阈值完全一致,实现简单
- B.把剪枝预算分配给冗余层← 正确答案
- C.不需要任何验证数据集
- D.能减少模型的层数总量
答案:B。全局剪枝在同一分位数下统一决策,冗余大的层被剪更多,预算分配更合理。A 描述的是局部剪枝的简单性;C 仍需验证集评估;D 剪枝不减少层数。
Q10. 关于稀疏率设定,哪些经验说法正确?
- A.大模型冗余多更耐受高稀疏率← 正确答案
- B.精度曲线拐点后急剧下降← 正确答案
- C.稀疏率应越低越好永不超过10%
- D.由存储和时延预算倒推选择← 正确答案
答案:ABD。大模型参数量大、冗余多,能承受更高稀疏率;精度-稀疏率曲线通常存在拐点,超过后损失陡增;实践中先定部署预算再选稀疏率。C 过于绝对,稀疏率太低就失去压缩意义。