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() 这一中间步骤)。融合后可以通过对比的方式直接得到结果。