前言
昨天介绍的BinaryConnect提出将浮点权重量化到1bit,提出了完整的量化权重训练/测试流程,并且从带噪声权重的角度来解释了量化权重。但这种方法还有一个缺点,即并没有对激活函数进行量化,所以Bengio大神在2016年发表了这篇Binary Neural Network,论文原文和代码链接见附录。
BNN算法
二值化的方法
二值化方法主要有两种,确定式二值化和随机式二值化。二值化将float类型权重转换为两个值,一个非常简单直接的二值化操作基于符号函数:
其中是二值化权重,是实值权重。这是一个确定式的二值化操作,另外一种方案是随机二值化,即以一定的概率更新值:
其中
第二种方法比第一种方法更合理,但在实现时,每次生成随机数会非常耗时,所以一般使用第一种方法。
梯度计算和累加
虽然BNN的参数和激活值被二值化了,但因为下面两个原因,导致梯度不得不用较高精度的实数而不是二值进行存储,原因如下:
- 梯度的量级很小。
- 梯度具有累加效果,即梯度都带有一定的噪音,而噪音一般认为是服从正态分布的,所以,多次累加梯度才能把噪音平均消耗掉。
另一方面,二值化相当于给权重和激活值添加了噪声,而这样的噪声具有正则化的作用,可以防止模型过拟合。因此,二值化可以被看作是Dropout的一种变形,Dropout一般是将激活值变成0,从而造成一定的稀疏性,而二值化则是将激活值变成1或者-1。
离散化梯度传播
直接对确定式的二值化函数求导的话,那么求导之后的值都是0。因此,只能采用一种折中的方法,将sign(x)
进行松弛。这样函数就可以求导了。公式如下:
然后,假设损失函数为,二值化操作函数如下:
如果对的导数已经得到了,那么对的求导公式计算如下:
后面的就是Htanh
函数。
在具体使用时,对于隐藏层单元,直接使用使用确定式二值化函数得到二值化的激活值。然后,对于权重,在进行参数更新时要时刻将超出[-1,1]的部分裁掉,即权重参数始终是[-1,1]之间的实数。最后,在使用参数时,要将参数二值化。
BNN的训练
前面已经解决了求导问题,二值化模型就可以直接训练了,具体过程如Algorithm1,这里用了BN层。
可以看到整个流程就是前向传播,反向传播,参数更新。
Shift Based Batch Normalization
Batch Normalization,简称BN,即批量归一化。所谓的BN是指在数据经过一层进入下一层之前,需要对数据进行归一化,使之均值为0,方差为1。这样可以使得各层的参数量级上没有太大的差别。BN有三个优点:
- 加速训练。
- 减小权重的值的尺度的影响。
- 归一化带来的噪声也有模型正则化的作用。
我们来看一下BN的计算公式:
可以发现BN在训练时存在大量的矩阵乘法,导致训练比较长。因为二值化这一特点,所以这里可以对BN进行优化,我们可以在不使用乘法的情况下近似计算BN,这即是Shift Based Batch Normalization,如Algorithm2所示:
Shift Based BN
Shift Based AdaMax
同样也是为了加速二值网络的训练,改进了AdaMax优化器。具体算法如Algorithm3所示。
Shift Based AdaMax
First Layer
虽然所有层的激活值和参数都是二值的,但第一层(输入层)的值是连续的,因为是原始图片。如果要整个网络都是二值化的,只需要对输入层做一个变换即可。一般使用8位的值来表示一个像素,输入可以表达为一个的张量,而权重参数可以表达为的全向量。因此,第一层的计算操作如下:
这个函数就把像素值还原回来了,表示每个数的第位。
综上,最后BNN的计算过程如Algorithm5所示。
BNN的前向计算
测试推理阶段
如何前向推理,大致可以分为以下几种方法:
- 使用二值化weight。
- 使用浮点数weight。
- 从浮点权重和随机二值化可以采样出很多二值网络,将它们的预测输出平均一下作为输出。
这篇论文使用了第3种方法,训练过程中用随机二值权重,测试时用浮点权重可以提升性能,证明了论文前面认为的带噪声的权重具有一定的正则性。
实验结果
在MNIST,CIFAR-10,SVHN上使用前向推理介绍的方法3进行测试的结果
性能分析
论文提到训练时间可以减少60%,但具体怎么计算暂时不清楚,后面了解下源码再说,暂时就理解为计时函数然后比较吧。从下面Table2和Table3的测试结果来看内存访问的耗时比计算耗时要多,相对于32bit的DNN,BNN的内存需求量为原来的1/32,使得能源使用可以减少31/32。
此外,在BNN中,所有的计算都变成了位运算,一个32bit的乘法需要损耗200单位(FPGA上)的能量,而一个位操作只损耗1个单位的能量。这在嵌入式设备上式具有非常大优势的。
能力损耗对比
总结
这篇论文是在BinaryConnect的基础上,同时将权重和激活值量化到1bit,不仅从实验角度证明了量化算法的可行,还分析针对低bit如何进行更有效的计算,整理出了同时量化权重和激活值到1bit的算法流程,且针对内部的硬件计算,给出了具体实现,例如Shift-based Batch Normalization、XNOR-Count,最终训练能减少60%的时间,32倍的存储空间。最近是先读一下理论,后面我会去做Pytorch的代码解析,自己动手训练测试二值网络,请持续关注吧。
思考
可以看到BNN在MNIST,CIFAR10,SVHN上实现了和普通DNN类似的精度,那么BNN能否在更复杂的数据集如ImageNet上也实现和DNN类似的精度并保持效果上的优势呢?另外一点是从论文的BNN需要小的学习率,并且收敛速度比DNN慢很多,这也是一个值得探索的问题。。收敛慢的问题可以从Figure1看出。
可以看到BNN收敛慢很多
附录
- 论文原文:https://arxiv.org/pdf/1602.02830.pdf
- 代码:https://github.com/itayhubara/BinaryNet
欢迎关注GiantPandaCV, 在这里你将看到独家的深度学习分享,坚持原创,每天分享我们学习到的新鲜知识。( • ̀ω•́ )✧