深度学习算法优化系列十 | 二值神经网络(Binary Neural Network,BNN)

2020-02-21 11:54:32 浏览数 (1)

前言

昨天介绍的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, 在这里你将看到独家的深度学习分享,坚持原创,每天分享我们学习到的新鲜知识。( • ̀ω•́ )✧

0 人点赞