激活值的数据特性:分布规律、稀疏性与冗余度分析

做激活压缩,第一步不是急着选算法。你得先搞清楚——激活值到底是什么样的数据?

我见过不少团队,一上来就套量化工具,结果精度掉得一塌糊涂。为什么?因为他们根本不了解自己手里激活值的脾气。说白了,激活值不是随机噪声,它有非常强的统计规律。摸清这些规律,压缩才能有的放矢。

2.1 激活值的分布规律

先聊分布。你想想看,神经网络每一层输出的激活值,它的数值范围、集中趋势、离散程度,其实都藏着信息。

我个人习惯,拿到一个模型后,第一件事就是跑一遍推理,把每层激活值 dump 出来,画直方图。你会发现几个典型模式:

  • ReLU 系列激活:输出非负,大量值集中在 0 附近,尾部拖一个长尾。分布近似指数衰减或半高斯。
  • tanh / sigmoid:输出有界,集中在 0 附近,两端饱和区值很少。
  • GELU / Swish:近似正态分布,但略有偏斜,负值区域也有少量激活。

关键发现:绝大多数激活值集中在很小的动态范围内。比如 ResNet-50 的中间层,90% 以上的激活值值小于 6。这意味着什么?意味着你用 8-bit 甚至 4-bit 去表示,信息损失其实很小。

我在项目中遇到过一件事:某团队做 MobileNet 量化,直接按全局最大最小值定标,结果精度掉了 3 个点。后来我让他们逐层看分布,发现有一层激活值范围特别大(因为前面有 BN 融合没做好),但实际 99% 的值都在小范围内。改用 percentile-based 定标后,精度只掉了 0.3%。

2.2 稀疏性:天然存在的压缩机会

稀疏性,说白了就是激活值里有多少个 0。ReLU 会把负值全部置 0,所以越深的网络,激活稀疏度越高。

我测过一些典型模型:

模型 平均激活稀疏度 最高层稀疏度
ResNet-50 ~52% ~78%
MobileNetV2 ~45% ~70%
BERT-base (GELU) ~15% ~30%
ViT-B/16 (GELU) ~18% ~35%

你看,CNN 的稀疏度普遍很高,Transformer 相对低一些。但即使 15% 的稀疏度,也意味着每 100 个激活值里有 15 个是 0——这些 0 完全不需要存储和计算。

我的建议:不要只看平均稀疏度。逐层看,有些层稀疏度超过 70%,这些层是压缩的「金矿」。我曾经在某个检测模型里,对稀疏度 >60% 的层直接用了稀疏感知量化,存储节省了 40%,计算延迟降了 25%。

2.3 冗余度:激活值之间的相关性

冗余度,衡量的是激活值之间有多「像」。如果两个通道的激活值几乎一模一样,那保留一个就够了。

怎么分析?我常用两个指标:

  1. 通道间 Pearson 相关系数:计算每对通道激活值的相关性。系数 >0.9 的通道对,说明冗余很高。
  2. 奇异值分解 (SVD) 能量比:对激活矩阵做 SVD,看前 k 个奇异值占总能量的比例。比例越高,冗余越大。

举个例子,我在分析 ResNet-50 的 layer3 时发现:

  • 通道间平均相关系数 0.67
  • 前 50% 的奇异值贡献了 92% 的能量

这意味着什么?意味着你可以把 256 个通道压缩到 128 个,信息损失不到 8%。这就是激活压缩的理论依据。

注意避坑:我曾经在某个 NLP 模型上直接按 SVD 能量比做通道剪枝,结果精度崩了。为什么?因为 NLP 的激活值冗余度虽然高,但那些「低能量」的奇异向量对应的是句法细节信息,对最终任务很重要。所以冗余度分析必须结合任务敏感性,不能只看统计数字。

2.4 知识体系总览

下面这张图,把激活值的数据特性梳理清楚了。你可以把它当作本章的「思维导图」:

激活值数据特性分析框架 激活值数据特性 分布规律 稀疏性 冗余度 ReLU / GELU / tanh 直方图 / 范围 Percentile 定标 ReLU 天然稀疏 逐层稀疏度 稀疏感知量化 通道相关性 SVD 能量比 通道剪枝 分析激活值特性 → 指导压缩策略选择 分布决定定标方式,稀疏决定跳过策略,冗余决定剪枝力度

2.5 实战:如何快速分析你的激活值

光说不练假把式。我分享一个我常用的分析流程:

  1. 收集数据:用验证集跑一次推理,把每层激活值保存下来(注意内存,可以只存一个 batch)。
  2. 画分布图:对每层做直方图,看范围、看集中区域、看是否有异常离群点。
  3. 算稀疏度:统计每层激活值中 0 的占比。对 CNN,重点关注 ReLU 后的层。
  4. 算冗余度:随机选 100 个通道,算两两相关系数。或者直接做 SVD,看能量集中度。
  5. 标记「压缩友好层」:把稀疏度 >50% 或冗余度 >80% 的层标记出来,这些是压缩的重点对象。

一个小工具:我写过一个 Python 脚本,用 PyTorch hook 自动收集激活值,然后输出一份「激活值健康报告」。报告里会列出每层的 min/max/mean/std、稀疏度、以及前 10 个奇异值的能量占比。有了这份报告,压缩方案基本就心里有数了。