二值化神经网络(BNN)综述

共 10864字,需浏览 22分钟

 ·

2020-11-06 09:05

【GiantPandaCV导语】二值化神经网络BNN由于可以实现极高的压缩比和加速效果,所以它是推动以深度神经网络为代表的人工智能模型在资源受限和功耗受限的移动端设备,嵌入式设备上落地应用的一门非常有潜力的技术。虽然目前的BNN仍然存在着很多不足,如模型精度仍然比全精度低了不少,无法有效地泛化到更复杂的任务上,依赖于特定的硬件架构和软件框架......,但我们同时也能看到BNN从最初的2015年ImageNet上只有27%的Top-1准确率发展到2020年ReActNet-C的71.4%的进步,这五年时间众多研究人员在这条道路上不断推动着BNN朝着更准更快更稳的方向发展,所以我们有理由相信,BNN未来可期!

英文原文 : Simons T, Lee D J. A review of binarized neural networks[J]. Electronics, 2019, 8(6): 661.

下载链接:

A review of binarized neural networks(https://www.mdpi.com/2079-9292/8/6/661/pdfwww.mdpi.com)

**注:**本文主要是对上述英文综述论文的部分中文翻译和一些对BNN的个人理解,这篇综述的发表日期是2019年6月份,个人感觉这篇综述写的很好,语言简洁,内容详实。后续2020年3月北航发表了一篇更新的二值化综述,但因为已经有人翻译过了,所以不再重复造轮子,原文链接贴在下面,中文翻译知乎随便一搜就能找到。

Binary Neural Networks: A Survey(https://arxiv.org/pdf/2004.03333)

闲扯淡

自大四毕业进入课题组以来,在模型压缩与优化加速领域的学习也有一年多了。过去的一年虽然主要是做的模型8-bit量化方面的工程实践(给硬件组当狗),但是同时也看了很多论文,陆陆续续也对整个领域其他方面如剪枝,知识蒸馏,矩阵低秩分解等,和一些基本的轻量级网络如SqueezeNet, ShuffleNet系列,MobileNet系列,EfficientNet系列的结构设计有了一定的了解。其中,二值化神经网络(BNN)尤为引起我的兴趣,因为它有着最为极端的压缩率和极低的计算量。虽然BNN仍受限于复杂数据集/任务上很不理想的准确率和对特定硬件架构或软件框架的依赖,而模型压缩领域真正能应用于实处且算得上通用的技术仍然限于通道剪枝,8bit量化和轻量级网络设计(如果可以归类为模型压缩领域的话),但是我仍然认为BNN是模型压缩领域皇冠上的明珠,因为大道至简。

开始正文

二值化神经网络(BNN)指的是仅使用+1和-1两个值来表示weights和activations的神经网络,相比于全精度的神经网络,它可以用XNOR+popcount这样极简单的组合代替float32的乘累加来实现卷积操作,从而节省了大量的内存和计算,大大方便了模型在资源受限设备上的部署。但同时,由于二值所能表达的信息量有限,所以BNN在模型精度方面一直都是远低于全精度模型,虽然最近的研究如MeliusNet,IRNet和ReActNet已经努力地将BNNs在ImageNet数据集上的Top-1拉到了0.70以上,与相应的全精度模型差距拉到3个点左右,但他们同时也增加了不少计算量,并且暂时还难以有效地推广到目标检测,语义分割等复杂任务上,所以BNN的升级打怪之路仍然道阻且长。目前有关BNN的研究从大的方面来说就是两个:如何提升BNN的精度和如何有效地部署在低功耗且资源受限的平台上。

本篇综述主要从以下几个方面进行的阐述:

  • 二值化神经网络的基本介绍;
  • 二值化神经网络的主要发展;
  • 提升二值化神经网络精度和推理速度的技巧;
  • 二值化神经网络在不同数据集上的精度表现;
  • 二值化神经网络的硬件实现;

特意说明,因为本篇综述是2019年6月发表的,所以这个时间点之后的相关论文的贡献并没有被总结在内,而我发现这段时间出现了不少优秀的论文,如Bi-real Net, MeliusNet,IRNet, ReActNet等等,他们提出了很多巧妙的技术来解决目前二值化神经网络中存在的问题,所以我会将自己对这些论文的一些总结穿插在接下来的阐述中,其中势必有一些理解不正确的地方,希望能够指出,我们共同进步!

基本介绍

二值化神经网络的idea最初源于2016年深度学习三巨头之一Yoshua Bengio的论文《BinaryNet: Training Deep Neural Networks with Weights and Activations Constrained to +1 or -1.》,它首次提出一种方法,可以用随机梯度下降的方式训练同时使用二值化的weights和activations的神经网络。为了解决二值化weights中梯度的传递问题,作者提出在训练过程中保持一个实值(float32)的weights,然后使用信号函数sign来获得二值化的weights

并且针对sign函数在0处不可导,其他地方导数为0无法有效进行梯度传递的问题,设计了直通估计器STE (straight through estimator),即当梯度传递遇到sign函数时,直接跳过这个函数,或者说默认sign函数输出对输入的梯度为1,即:

前向和反向计算的流程如下图所示

img

STE的可视化

使用了STE之后,实值的weights就可以使用如SGD和Adam这样常见的优化器来进行更新了,同时考虑到这个实值weights是没有设置边界的,这样它就有可能会一直累加到特别大的值,从而与二值化的weights之间的量化误差越来越大,积重难返,所以作者对实值的weights还单独加了一个截断函数clip(x,-1,1),将其限制在-1和+1之间,这样使得实值weights和二值化weights的距离更近。对于activations的二值化和weights是相似的,并且在实验中作者发现,当sign函数的输入的绝对值大于1的时候,将梯度置0可以得到更好的实验结果,即:

简单总结一下,我们可以看到作者在训练过程中对weights和activations做了不同的设置,两个在梯度更新上都是遵照STE的原则,直接将sign函数跳过,而实值weights在更新之后会裁剪到[-1,1]之间,从而减小实值weights和二值化weights之间的距离,而activations的梯度在更新的时候,当实值activations的绝对值大于1时会将梯度置0,避免特别大的梯度向下传递使得训练时候出现震荡。

花这么大的力气来训练这个BNN,然而最后实验结果看起来与全精度相比也没有什么任何优势,肯定是这个模型存在什么惊喜?我来翻译翻译,作者设计BNN的初衷还是为了加速模型的前向推理,这里面最大的功劳就是用1bit数的XNOR和popcount代替了传统卷积的float32乘累加操作,用脚想也能理解这个在理论上不仅能减少32倍的参数存储,还能跑的比曹操快。虽然在BNN各个数据集上的实验都是强差人意,但快不快就完事了。同时也有些亟待毕业的博士研究发现BNN在对抗攻击方面有很强的鲁棒性,除了快,还稳,好家伙,直呼BNN牛逼。

img

主要发展

Yoshua Bengio作为BNN的开山祖师,不仅给众多人指明了山的方向 —— 更快更准更泛化,还在一路上留下了数不清的果实让后来者去慢慢摘 —— STE的优化,二值友好结构的设计,更细致的training tricks......,于是这个领域开始了轰轰烈烈的刷榜竞赛,以下将介绍一些在BNN发展道路上带来创新的模型,其中综述中谈到的DeReFa-Net,个人认为它主要是为低比特量化及训练设计的,将乘法用多个bitwise+shift的操作代替,梯度也可以用低比特数来表示,但如果把它的W/A的位宽设置为1/1,并没有看出很多结构上的创新,故在此处不阐述。

  • XNOR-Net

在第一篇BNN发表不久,XNOR-Net横空出世,这篇论文其实提出了两个模型,一个是BWN(Binary Weight Networks),另一个才是XNOR-Net,BWN只使用了二值化的weights,而activation仍然采取的float32全精度,按照BNN的定义其实BWN不能算在二值化网络的范畴,但它的效果那是杠杠的,跟全精度相差不大,看来神经网络对weights的二值化还挺不敏感的。而该文的主角XNOR-Net是正儿八经不掺水的二值化神经网络,weights和activations都采取的二值化。它主要是在原始BNN基础上考虑了量化误差,并且提出了对实值weights每个输出通道方向上提取出一个scaling factor,用于恢复二值化weights的信息,同时对activation在HW方向上每个pixel上提取一个scaling factor,用于恢复二值化activations的信息,这两种scaling factor都无需学习,直接计算相应的L-1范数就能得到,且不影响二值化高效的卷积计算过程。最后的实验也比原始的BNN要好不少,并且首次展示了BNN在ImageNet这种大型数据集上的实验结果,还声称在卷积计算上可以达到58倍的加速效果,节省32倍的内存。

img

本文是BNN领域一个非常重要的工作,用scaling factor恢复量化误差来提升精度的思想一直被沿用至今,在各个论文中都能看到。但同时该文也有一些诟病的地方,如计算结果无法复现(我翻译的这篇英文综述说的,不是我说的),没有真正部署在硬件上实测加速效果,只是阐述了一个理论值,毕竟在前向推理过程中每层activation在HW方向每个pixel上计算scaling factor的操作是非常耗时的。

  • ABC-Net

这是大疆创新被NIPS2017收录的论文,论文中主要针对值化数据表达信息太弱的问题,提出使用多个二值化weights和activations线性加权求和的方式来近似表示全精度的weights和activations,如下面的公式所示。为了得到不同的二值化的bases,作者通过在sign函数中加入变量u,结合weights的均值和方差,通过改变u的值就可以获得不同的二值化tensor。而对于activations来说,使用相同的二值化操作会和XNOR-Net一样在前向推理过程中为了计算均值方差增加大量计算,所以这里选择在sign函数中使用N个可学习的变量u来进行二值化。其实可以看出,这篇论文的思想和DoReFa-Net还是挺相似的,只不过DoReFa-Net是低比特量化,而ABC-Net使用的更巧妙一些,本质还是BNN,但我们一眼也能看出,这个ABC-Net比之前的BNN在计算量上增加了很多,相当于是用时间和空间换取精度。论文说用5个bases可以达到非常好的实验效果,但实际上消耗的资源比W/A=2/2还多了。

  • MeliusNet

这是一篇BNN结构设计的论文,作者从两大经典的网络结构ResNet和DenseNet获得启发,针对在此之前的二值化feature map信息表达很弱的问题提出了两个概念:Quality(质量)和Capacity(数量),即ResNet的shortcut可以增强了每个通道的feature map的信息表达,DenseNet中的concat可以增加feature map的通道数,从而增强整体的信息表达。其实这两个想法在前作Bi-real Net和BinaryDenseNet中也分别提到了,本来打算单独讲这两篇,但是考虑到和MeliusNet思想的重合,就只单独把这一篇拎出来讲一下,但实际上述两篇论文的BNN结构上个人觉得更加的简洁,有兴趣的可以下下来看一下。

Bi-Real Net

BinaryDenseNet

话题转回来,MeliusNet根据用shotcut和concat增强Quality和Capacity的指导思想设计了两个二值友好的模块,如下图所示,一个是Dense Block,另一个是Improvement Block,这两个模块在网络中每次都是交错出现,在整个信息流中不断地增强二值化feature map的信息表达,从而提升精度。这篇论文除了这个核心思想之外,还提出了一个我觉得比较有意思的思路,那就是二值化网络应该有一套自己的网络结构,这种二值化友好结构的效果要优于相似FLOPs下全精度模型二值化后的结构,并且做了相应的实验进行验证,通俗地来讲就是倡导大家要走二值化特色社会主义道路。

img
  • IR-Net

这是一篇很有意思,我非常喜欢的一篇论文,它的作者就是最开始我提到另一篇综述的作者,2020年上半年也有机会在商汤的泰坦公开课中聆听了主创们对这篇论文的解读。这篇论文主要针对的是二值化在前向计算和反向梯度传播中带来的信息损失问题,作者分别提出了两个技术,一个是 Libra-PB(Libra Parameter Binarization),用于在前向计算中同时最小化weights的量化损失和信息熵损失,另一个是EDE(Error Decay Estimator),通过渐进近似sign函数来最小化反向传播过程中梯度的信息损失。Libra-PB简单来说就是在weights被二值化之前,先对它做归一化处理,即减均值除方差,这样的话在二值化之前,就大概有一半的weights是大于0,一半的weights小于0,从而使得二值化之后的weights信息熵损失最小。

img

而EDE则是利用k×tanh(t×x)在不同训练阶段渐进近似sign函数,并用其梯度来代替sign函数的梯度进行反向传播,从而使得整个训练过程可以更加的平滑,从而减少信息损失。

img

之所以喜欢这篇论文,是因为它提出的两个技术非常的简洁有效,一下子就能让人理解,一点都不花里胡哨,然后得到的结果也非常的好。

  • ReActNet

这篇论文的一座和Bi-Real Net是同一个人——刘泽春,作者之前还在知乎上和另一个未经作者允许就直接发表了Bi-Real Net V2的研究人员发生了争辩,快来一起吃瓜呀!

ICLR 2021 有什么值得关注的投稿?

并且从这个争论中才了解到ReActNet这篇论文,于是赶忙去下载下来,焚香沐浴,仔细拜读了大佬的作品。这篇论文是延续Bi-Real Net的一篇二值化神经网络研究的工作,作者首先利用Bi-Real Net的思路,即在原始网络中增加shortcut层来改造了MobileNetV1,然后通过大量的实验发现BNN的性能对activations的分布变化特别敏感,即对Activations进行平移/缩放对BNN的性能影响很明显,那么作者思考的是肯定每一层的Activations都各自有一个最适合的偏移值和缩放值使得整个模型的性能最优,于是作者提出了对sign函数和PReLU函数进行改造,加入可学习的参数变量,让模型自动去学每一层最佳的偏移值和缩放值,命名为ReAct-Sign(简称RSign)和ReAct-PReLU(简称RPReLU),另外需要说明的是这些参数都是channel-wise的,计算量其实还是有些的哈,但是因为选的模型是MobileNetV1,参数量较小,所以相比其他的BNN模型在整个计算量上还是少了很多,且精度还高了不少。

img

另外基于之前的观测结果,作者将最后一层输出经过softmax的结果与label的cross entropy 换成了与全精度模型的最后一层输出经过softmax的cross entropy,以此来学习全精度模型最后一层输出的数据分布,称之为distributional loss,有知识蒸馏那味了,并且作者强调相比于之前一些论文将二值化模型每一层输出都与全精度模型对应层输出进行匹配的做法,这个distributional loss更加简洁,且效果非也很好。

img

以上就是个人结合本篇英文综述和自己看过的一些论文总结的二值化神经网络发展史上一些重要进展的论文。因为本人水平有限,势必不够完整,如有遗漏请多多见谅!

提升性能的技术总结

现在来总结一下自最初的BNNs论文出来之后,为了提升性能用到的技术总结:

  1. Gain term 增益项

这个主要指的是一些为了减少数据二值化损失而增加的一些额外的项,如XNOR-Net首次提出的在weights二值化之前计算一个channel-wise的scaling factors(一般是每个通道权重的均值)用于恢复量化损失,这个思想被沿用至今简单有效。还有各种在activations上增加的可学习的参数,如ReActNet提到的RSign和RPReLU,这些增益项虽然增加一点点的计算,但对模型精度却有大幅度的提升。另外要说明的XNOR-Net里面对activations在HW方向上每个pixel计算一个scale,这个虽然可以减少二值化的信息损失,但是在前向过程中对推理速度的影响很严重,所以暂不列入其中,这也说明了一点,weights上的增益项无论是可学习的还是在线计算的都不会对推理速度有较大影响,因为训练结束之后可以得到固定的系数。而activations的增益项最好是用可学习的,因为在前向推理过程中,每次输入数据不同,在线计算的增益项都需要重新计算,这个对推理速度影响很大。

2.  多个二值化base

这个特指ABC-Net的做法,用多个二值化的base线性加权近似全精度的weights和activations,性能不错,典型的以时间和空间换取精度的做法。

3.  二值友好的结构设计

Bi-Real Net,BinaryDenseNet和MeliusNet三篇论文验证了在BNNs网络结构中加入shortcut和concat操作能够大大增强模型的Quality和Capacity,从而大大提升性能。

4. 关键层的设计

神经网络中关键层一般指的第一层,下采样层和最后一层,这些层相对于其他普通层对模型性能影响更大,所以需要额外注意。

  • 第一层

第一层的输入是原始数据,且卷积核的参数量较少,如果第一层出现了巨大的信息损失,那么后面层基本上也学不到啥了,原始BNN论文没有对输入直接二值化,因为输入的图像数据是UINT8类型,范围[0,255],二值化基本都是1了,信息损失殆尽,所以作者直接输入原始的数据与二值weights进行卷积计算。为了提升计算效率,作者将输入按比特位切片出来,用移位和XNOR代替乘法,如下图所示。

img

但这个做法不太妥当的是,输入数据虽然没有丢失信息,但是没有做数据的归一化。在主流的模型训练中我们可以知道,数据的normalize对结果影响还蛮大的,所以目前主流的BNNs基本上第一层都是使用全精度的卷积层,输入数据正常归一化处理后输入网络,因为通常认为这块计算量不大。但是MeliusNet在实验中发现目前很多BNNs计算中,浮点计算占了60%以上,第一层很多人使用的7×7的卷积核,计算量还是蛮大的,所以MeliusNet用三个3×3的卷积进行了代替,节省了一半的计算。

输入数据需要做normalize和二值化结构真的就无缘了吗?在FBNA论文中我们发现,可以使用如下技巧,输入数据正常归一化之后,缩放到[-128,128]的范围并取整,然后每个pixel的值用一个长度为256的一维二值化向量表示,两者关系是这个二值化向量累加求和之后的结果除以2等于这个整数值,如下所示:

img

下图中(a,b,c)以2Bit的数据为例再次展示了上述分解过程。输入数据假设为CIFAR10,分辨率是(32,32,3),那么经过分解之后就会变成(32,32,256,3),这个时候我们会发现输入数据巨大无比,第一层计算量指数级增加,于是作者将原图像8bit数据的高位截掉,在分解向量中的体现就是直接去掉右侧的正负1的数,如下图所示,我们可以发现pruning之后的图像其实仍然保留了大多数的信息,且可以大大降低计算量,整个过程如下图(d)所示。

img
  • 下采样层

下采样层的特点是图像分辨率会直接减少一半,这个过程是一个不可逆的信息损失的过程。早期的BNNs都倾向于使用MaxPooling来进行下采样操作,但是存在一个问题是,如果在每一层activations二值化之后进行MaxPooling,会导致梯度反传到这块的时候将梯度均匀的分给多个+1或者多个-1,然而实际上只有real-value最大的那个值真正起了作用,这样的分配是不公平的,所以比较好的做法是遇到MaxPooling操作的时候,将activations的二值化延后,对实值的weights进行下采样,这样可以得到更好的效果。但目前的网络设计人员通常认为MaxPooling是不可学习的算子,倾向于使用stride=2的卷积层来进行下采样,这样可以保留更多的信息,所以在目前的BNNs当中,这块通常也是使用全精度的卷积来计算,避免造成较大精度损失,同时可以利用组卷积+channel shuffle的方式来进一步降低浮点的计算量。

  • 输出层

这一层在分类任务中通常是全连接的结构,输出最后的预测结果,为了避免二值化的影响,通常也是采取全精度的计算,本来想提一下很多人对FC做的random pruning能降低计算,但又仔细想了想,这中任意剪枝方式在硬件上实现尤为麻烦,估计很难加速。

5. 渐进式地学习

如IR-Net中的EDE,用其他可微的函数来代替sign函数,并且在训练过程中不断地逼近真正的sign,使得整个训练过程梯度传递更加的平滑。还有一些论文在训练的时候渐进地对weights和activations进行二值化,根据一些原则,一开始的时候二值化部分数据,然后在训练过程中渐渐增大二值化的比例,最后将整个模型二值化,这个过程也是相对平滑的,比直接二值化更有效,这让我想起了老本行模型量化中的INQ。

6. padding策略

在实值卷积神经网络中,我们通常在输入四周padding的0,但是在BNN当中并没有0这种数的存在,所以大家大多数选择全-1或者全+1。有研究者发现这种padding策略对结果是有影响的,毕竟使得整个输入数据朝着1或者-1发生了偏移,上述的ReActNet也说过activations的发生偏移对结果影响还是很明显的,所以有人提出了Odd-Even padding的方式,即奇偶填充,1和-1间隔填充,如下图所示,并且发现这种填充方式可以达到填充0的效果。

img

7. 其他训练技巧

  • 使用全精度模型在数据集上训练好的参数作为对应BNN的初始化参数;
  • Batch Normlization 和输入数据的normalize是必要操作;
  • 损失函数增加正则项,如下图中的L-1 norm和L-2 norm,将α设为1,可以使得weights在训练过程中绝对值更加趋近于1,有利于减少量化误差;
img
  • 使用较小的学习率,然后累计梯度,间隔更新的方式;

8. 前向加速

  • 用INT4/INT8/FP16的卷积代替全精度卷积计算的部分;
  • 将Batch Normalization和sign函数合并起来,将浮点计算变成符号判断和数值大小比较;
img

不同数据集上的精度表现

由于BNN的模型实在是太多,而每一篇论文的实验结果也非常丰富,故我从两篇综述中截取出CIFAR10,ImageNet,PASCAL VOC2007和MS COCO2017最好的一些结果,如下所示:(注意:其中MS COCO2017的结果我似乎没有在论文原文中找到依据,所以大家就图个乐,不要较真)

img

硬件实现

由于我不是搞硬件的,所以这块只能简述一下。由于BNN的主要加速原因就是用XNOR+bitcount操作来代替了传统卷积中昂贵的乘累加操作,而我们使用的x86计算架构基本上都是对float32类型数据的计算做了很大程度的优化,所以直接将BNN部署在现有的x86计算平台上是很吃亏的,有可能不仅没有加速效果,甚至比同等的全精度模型跑的还慢。在我的调研中,硬件部署实现有如下两种方式:

  1. ARM CPU,可以部署在手机端
  • BMXNet框架,来自于德国的Hasso Plattner Institute,MeliusNet的作者,支持ios和Android的部署;
  • daBNN框架,来自京东AI研究院,目前仅支持Android手机上的部署;

2. FPGA和ASIC

相比于传统的CPU,FPGA在硬件架构设计方面很灵活,可以支持bitswise的高效运算,而且功耗很低,其对应的终极版的专用集成电路ASIC更是如此,可以比FPGA运算更高效,更节能。目前用FPGA设计AI加速器基本都是以Xilinx的器件和开发工具为主,而他们也为二值化神经网络专门设计了一款架构FINN,开发者可以利用高层次综合工具(HLS),用C语言进行开发,直接将二值化模型部署到FPGA上,下图是一些对比结果。而Intel的Accelerator Architecture Lab也为BNN设计了一款layer accelerator的ASIC,不过并没有找到很多的相关数据,就不赘述。

img
img

最后的总结

二值化神经网络BNN由于可以实现极高的压缩比和加速效果,所以它是推动以深度神经网络为代表的人工智能模型在资源受限和功耗受限的移动端设备,嵌入式设备上落地应用的一门非常有潜力的技术。虽然目前的BNN仍然存在着很多不足,如模型精度仍然比全精度低了不少,无法有效地泛化到更复杂的任务上,依赖于特定的硬件架构和软件框架......,但我们同时也能看到BNN从最初的2015年ImageNet上只有27%的Top-1准确率发展到2020年ReActNet-C的71.4%的进步,这五年时间众多研究人员在这条道路上不断推动着BNN朝着更准更快更稳的方向发展,所以我们有理由相信,BNN未来可期!


欢迎关注GiantPandaCV, 在这里你将看到独家的深度学习分享,坚持原创,每天分享我们学习到的新鲜知识。( • ̀ω•́ )✧

有对文章相关的问题,或者想要加入交流群,欢迎添加BBuf微信:

二维码

为了方便读者获取资料以及我们公众号的作者发布一些Github工程的更新,我们成立了一个QQ群,二维码如下,感兴趣可以加入。

公众号QQ交流群


浏览 87
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报