DoReFa-Net 低比特量化训练笔记

DoReFa-Net 这篇论文的核心思路是:对卷积神经网络的权值、激活值和梯度分别做低比特量化,从而把训练和推理中绝大多数的计算都压缩到低比特的位运算层面。下面按照论文的脉络整理一下各个模块的做法。

位运算与点乘的关系

论文的出发点是:两个整数之间的点乘可以用位运算来表示。

将这个思路推广到向量之间的点乘,两个向量中整数的表示位数也可以不同,这就为权值和激活值使用不同的比特宽度奠定了基础。

直通估计器(STE)

量化操作本身(取整/截断)不可导,反向传播需要近似处理。论文在梯度近似上使用了 STE(Straight-Through Estimator),本质上就是自定义 forward 和 backward 函数:forward 做量化,backward 把梯度直接透传。

本文中的 STE 对应的是圆整函数,也就是 quantize_k,具体算法参见代码实现。

权值量化

量化权值时通常会引入缩放因子。XNOR-NET 使用的是随输入变化的缩放因子,DoReFa-Net 则使用固定的缩放因子,实现更简洁。

当比特数大于 1 时,权值量化采用以下方式,其中的 quantize_k 就是上面介绍的 STE 实现。当 k=1 时,具体的表达形式与多比特情形略有不同,但实验表明两者的效果差别不大。

激活值量化

激活值的量化方式如下。

梯度量化

梯度的量化相比权值和激活值要更复杂一些,主要原因是梯度的数值范围更大,且没有明确的边界,因此论文对梯度采用随机量化。

所谓随机量化,就是在量化时额外叠加一个噪声项。

实验表明这个噪声项比较关键,去掉后效果会明显下降。

需要注意的是,梯度的量化只在反向传播过程中进行。

整体算法流程

将上述三部分合在一起,整体算法如下。

其中所有的复杂操作——包括 forward、backward_input 和 backward_weight——都是低比特运算,这是论文声称能显著降低训练开销的核心所在。

关于首层和末层的特殊处理:

  • 第一层卷积因为直接与网络输入相连,权值不做量化,但卷积后的激活值仍然需要量化。
  • 最后一层全连接层在类别数较小的情况下也不做量化,但从 FC 层传出的梯度是要量化的。

推理阶段的融合优化

在具体实现上,可以将算法中的第 3、4、6 步骤进行融合,从而减少推理时的内存和时间开销(相当于省掉了 h() 这一中间步骤)。融合后可以通过对比的方式直接得到结果。