神经网络量化:原理、方法与实践
立即解锁
发布时间: 2025-08-29 11:17:02 阅读量: 16 订阅数: 18 AIGC 

### 神经网络量化:原理、方法与实践
#### 1. 量化粒度
在神经网络量化中,量化粒度是一个重要的概念。目前,常见的量化方式是为每个张量定义一组量化参数(量化器),分别用于权重和激活值,这被称为逐张量量化。在公式 11.5 中可以看到这种量化方式的体现。
不过,我们也可以为张量的各个分段(例如权重张量的输出通道)定义单独的量化器,从而提高量化粒度。在神经网络量化里,逐张量量化因其硬件实现较为简单,是最常用的粒度选择。在公式 11.5 中,所有累加器都使用相同的比例因子 swsx。
然而,增加量化粒度可以提升性能。例如,对于权重张量,我们可以为每个输出通道指定不同的量化器,这就是逐通道量化。逐通道量化在某些情况下能显著提高量化的准确性,尤其是当权重在不同通道间的分布差异较大时。但需要注意的是,并非所有硬件都支持逐通道量化,所以在选择目标设备时,需要确认其支持情况。
还有一些研究尝试超越逐通道量化,为一组权重或激活值应用单独的量化器。虽然增加分组的粒度通常能提高准确性,但会带来一些额外的开销,因为累加器需要处理具有不同比例因子的值的总和。目前,大多数现有的定点加速器并不支持这种逻辑,但随着该领域研究的发展,未来有望看到更多硬件对这些方法的支持。
#### 2. 量化模拟
为了测试神经网络在量化设备上的运行效果,我们通常会在用于训练神经网络的通用硬件上模拟量化行为,这就是量化模拟。其目的是使用浮点硬件来近似定点运算。与在实际量化硬件上进行实验或使用量化内核相比,量化模拟的实现要简单得多。它允许用户高效地测试各种量化选项,并为量化感知训练提供 GPU 加速。
在模拟过程中,我们需要考虑实际设备推理和模拟推理的差异。在实际设备推理中,硬件的所有输入(偏置、权重和输入激活值)都是定点格式。但在使用常见的深度学习框架和通用硬件进行量化模拟时,这些量是浮点格式。因此,我们在计算图中引入量化器块来模拟量化效果。
例如,在卷积层的模拟中,我们在权重和卷积之间添加量化器块来模拟权重量化,在激活函数之后添加量化器块来模拟激活量化。偏置通常不进行量化,因为它以更高的精度存储。量化器块实现了公式 11.9 的量化函数,每个量化器由一组量化参数(比例因子、零点、位宽)定义。量化器的输入和输出都是浮点格式,但输出位于量化网格上。
#### 3. 批量归一化折叠
批量归一化层是大多数现代计算机视觉神经网络的标准组件。它在添加比例和偏移之前对线性层的输出进行归一化。在设备推理中,这些操作会被折叠到前一个或下一个线性层中,这一步骤称为批量归一化折叠。
批量归一化折叠可以完全从网络中移除批量归一化操作,因为计算被吸收到线性层中。这样做不仅减少了额外的缩放和偏移计算开销,还避免了额外的数据移动和层输出的量化。
假设一个权重矩阵 $W \in R^{n×m}$,对每个输出 $y_k$($k = {1, ..., n}$)应用批量归一化,我们可以将批量归一化操作与线性层融合,得到新的权重和偏置。具体公式如下:
- 批量归一化公式:$BatchNorm(x) = \gamma \left( \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} \right) + \beta$
- 融合后的公式:$y_k = \tilde{W}_{k,:} x + \tilde{b}_k$
其中,$\tilde{W}_{k,:} = \frac{\gamma_k W_{k,:}}{\sqrt{\sigma^2_k + \epsilon}}$,$\tilde{b}_k = \beta_k - \frac{\gamma_k \mu_k}{\sqrt{\sigma^2_k + \epsilon}}$
#### 4. 激活函数融合
在简单的量化加速器中,激活值的重新量化通常在矩阵乘法或卷积输出值计算之后进行。但在实际应用中,线性操作之后通常紧接着一个非线性操作。如果将线性层的激活值写入内存,然后再加载回计算核心以应用非线性操作,会造成资源浪费。
因此,许多硬件解决方案配备了一个硬件单元,在重新量化步骤之前应用非线性操作。在这种情况下,我们只需要模拟非线性操作之后的重新量化。例如,ReLU 非线性可以很容易地通过重新量化块来建模,只需将该激活量化的最小可表示值设置为 0。
然而,对于一些更复杂的激活函数,如 sigmoid 或 Swish 函数,需要更专门的支持。如果没有这种支持,我们需要在图中的非线性操作之前和之后添加量化步骤,这可能会对量化模拟的准确性产生很大影响。虽然像 Swish 函数这样的新激活函数在浮点运算中能提高准确性,但在定点硬件上部署可能会很困难且效率低下。
#### 5. 其他层的量化
神经网络中还有许多其他类型的层,它们的量化建模很大程度上取决于具体的硬件实现。有时,模拟量化和目标设备性能之间的不匹配是由于某些层没有被正确量化导致的。以下是一些常见层的量化模拟指导:
- **最大池化**:由于输入和输出值位于相同的量化网格上,因此不需要进行激活量化。
- **平均池化**:整数的平均值不一定是整数,所以在平均池化之后需要进行量化步骤。但由于量化范围不变,我们对输入和输出使用相同的量化器。
- **逐元素加法**:尽管这个操作看似简单,但准确模拟却很困难。在加法过程中,两个输入的量化范围必须完全匹配。如果范围不匹配,需要额外的处理来确保加法按预期工作。目前没有单一的公认解决方案,但添加重新量化步骤可以粗略地模拟添加的噪声。另一种方法是通过绑定输入的量化网格来优化网络,这可以避免重新量化步骤,但可能需要微调。
- **拼接**:被拼接的两个分支通常不共享相同的量化参数,这意味着它们的量化网格可能不重叠,因此需要进行重新量化步骤。与逐元素加法类似,也可以优化网络,使拼接的分支具有共享的量化参数。
#### 6. 实际考虑因素
在对多层神经网络进行量化时,我们面临着众多的量化选择,包括量化方案、粒度、位宽等。为了缩小搜索空间,我们需要考虑一些实际因素。
##### 6.1 对称与非对称量化
在每个权重和激活量化步骤中,我们需要选择量化方案。非对称量化由于有一个额外的偏移参数,表达能力更强,但可能会带来计算开销。例如,当非对称权重 $\tilde{W} = s_w(W_{int} - z_w)$ 与非对称激活 $\tilde{x} = s_x(x_{int} - z_x)$ 相乘时,会产生额外的计算项。
$\tilde{W}\tilde{x} = s_w s_x W_{int} x_{int} - s_w s_x z_w x_{int} - s_w s_x W_{int} z_x + s_w s_x z_w z_x$
其中,第一项与对称格式下的计算相同,第三项和第四项只取决于已知的比例、偏移和权重值,可以预先计算并添加到层的偏置项中,几乎不产生额外成本。但第二项取决于输入数据 $x$,这意味着在每次推理时,对于每一批数据都需要计算一个额外的项,这会导致显著的延迟和功耗开销,相当于添加了一个额外的通道。因此,常见的做法是对激活使用非对称量化,对权重使用对称量化。
##### 6.2 逐张量和逐通道量化
逐张量量化在一段时间内一直是权重和激活量化的标准方法,因为它得到了所有量化推理加速器的支持。但逐通道量化的权重可以提高准确性,特别是当权重在不同通道间的分布差异较大时。从公式 11.5 的量化 MAC 操作中可以看出,每个累加器可以应用单独的权重比例因子来实现逐通道权重量化。然而,激活的逐通道量化实现起来要困难得多,因为我们无法从求和中提取比例因子。
以下是不同量化范围设置方法在权重和激活量化上的比较表格:
| 方法 | ResNet18 (W8) | ResNet18 (W6) | ResNet18 (W4) | MobileNetV2 (W8) | MobileNetV2 (W6) | MobileNetV2 (W4) |
| --- | -
0
0
复制全文
相关推荐










