利用二进制算法提升神经网络的速度

NERVANA 已经加入了 英特尔

原始文章发布于  Nervana 网站: 利用二进制算法提升神经网络的速度. 请转至   Nervana 主页  获取关于 英特尔 Nervana 深度学习技术的更多信息。

Nervana 致力于改善算法和硬件以及加快神经网络的速度。低精度算法是令人倍感兴奋的一个研究领域。本文重点介绍了 二值化神经网络 (BNN)(一种低精度网络)和它的基本概念,还简要概述了 Neon CPU 和 GPU 实施。BNN 在多个数据集上实现了与标准神经网络不相上下的准确性。

BNN 在所有计算中使用了二进制权重和激活。浮点算法存在于所有深度学习计算中,包括计算梯度、应用参数更新 和计算激活。但是,32 位浮点乘法的成本非常高昂。在 BNN 中,浮点乘法被逐位 XNOR 所替代,留下了左右位移。从硬件的角度看,这点极具吸引力:以较低的成本实施二进制操作,同时提升计算效率。


来源:深度学习资源
图 1:BNN 使用二进制权重和激活,将 sign 函数用作激活函数,以确保二进制值激活。

相比训练,这些优势在推断中体现得更为明显。实际上,我们发现在训练中,每次迭代(向前传播、向后传播和参数更新)的速度提升了,但是为了达到相同的准确性,BNN 所需的迭代数量多于标准神经网络。对于推断而言,多数乘法降为二进制操作。Courbariaux 等人认为推断的速度高出了 7 倍,具有更高的能效性,且不会损失准确性。这些提升使部署于边缘的推断芯片更具吸引力,如自动驾驶汽车、无人机和智能手机中的芯片。

在 BNN 中,标准深度学习网络的常见组件被其二进制版本所替换。例如,基于位移的学习速度调度取代了典型的学习速度调度。其它的替换包括二进制线性层、sign 函数、基于位移的 batch norm、基于位移的 AdaMax 和 XNOR 点乘积。这些版本用高效二进制操作替代了浮点乘法,使用了三个基本概念:二值化、位打包、两种位移的大致性能。

二值化

二值化函数是 BNN 的原始操作,负责将权重和激活转换为 -1 和 +1s。这个函数分为两种类型:确定性与随机性。确定性函数基于 sign 确定权重或激活的阙值。

随机函数根据概率选择 -1 和 +1。由于该函数需要随机生成位,更加难以实施。

σ(x) 代表 hard sigmoid 函数。

二值化函数被用作激活函数,应用于所有的权重层。例如,在向前传播中

L 是总层数,Wk 和 θk 分别代表指定的 k 层中的权重和 batch norm 参数。二值化,尤其是随机二值化,可以被视为一种规整化形式。从概念上讲,它和 Dropout 相似,根据概率设置了更多值的阙值。

对于随机梯度下降 (SGD),许多噪音更新优于单个确切的更新。直观解释了为什么 BNN 效果显著:尽管二值化降低了更新的精度,噪音最终得到平衡,更新也逐渐回归正确的方向。

需要着重指出的是,只对权重和激活实施了二值化,实施对象不包括向后传播过程中更新参数的梯度。实值梯度是 SGD 正常运行所必需的。权重存储于实值累加器中,每次迭代中面向向前传播和梯度计算实施二值化。请访问该链接,了解如何在向后传播过程中减少计算。

位打包

在 BNN 中,需要乘以 -1 和 +1s 矩阵;例如,在向前传播过程中乘以激活和权重。GPU 不支持本地二进制操作。仅需 1 位的情况下,使用 32 位或 16 位造成了极大的浪费。

通过在单个 32 位整数中融合 32 位,模拟二进制算法,然后执行逐位 XNOR 操作,即在 32 个不同二进制操作内两个 32 位整数结果之间的逐位 XNOR。在 -1 到 1 的二进制范围内,XNOR 相当于乘法:如果操作数相同,结果为 1,如果操作数不同,结果为 -1。打包整数属于前期成本,但是每次操作的计算吞吐率提升了 32 倍。

这个概念可以用来实施 XNOR 点乘积,使用点乘积计算包含 -1s 和 +1s 的两个矩阵的乘法。在普通的矩阵乘法中,C = AB,A、B 和 C 是矩阵,结式矩阵 C 的每个元素都由 A 行和 B列之间的点乘积计算。在简单的 CUDA 内核实施中,我们可以看到特定行和列之间的以下关系

XNOR 点乘积在分别在 A 行中横向打包位,在 B 列中纵向打包位,然后利用逐位 XOR 和人口数量操作,如下所示

Ap 和 Bp 是副本的位打包版。-1s 由 0s 和 1s 表示,为了便于使用,由 1s 表示。累计值稍后在结式矩阵中解包。高效实施了积累、人口数量和 XOR。

两个位移的大致性能

在深度学习中,通常需要缩放值,如随着训练的进行而降低学习速度、计算规模和 batch norm 位移、在学习规则中更新的参数等。这些乘法可以替换为两个二进制位移的大致性能。例如,假如我们需要计算  7*5 的近似值。

AP2 是两个操作符的大致性能,<< 是一个左二进制位移。这个做法非常有吸引力,原因有以下两点:1) 支持极其高效地计算两个操作符的大致性能(请查看 bit twiddling hacks 获得灵感);2) 利用左二进制位移和右二进制位移便可轻松实施两个操作符性能的乘法。请查看面向 vanilla 的更新规则 AdaMax,了解如何在实践中应用

gt 和 θt 是步骤 t 中的梯度和参数,β1 和 β2 是面向 AdaMax 学习规则的超参数,α 是学习速度。

最后一行的乘法可以替换为两个位移的大致性能,以获得基于位移的 AdaMax 更新规则。

<<>> 是左二进制位移或右二进制位移(取决于 sign)。基于位移的 batch norm 和学习速度调度也不例外。

结论

使用二值化、两个位移的大致性能和位打包,可以将乘法替换为计算速度快、能效高的二进制操作。上述三个概念构成了 BNN 的基础。

Neon 提供了面向 CPU 和 GPU 的启动实施,请访问此处获取。非常欢迎您的反馈和参与,如果您有任何问题,请访问info@nervanasys.com
 

关于作者:

Sathish Nagappan 任职于 Nervana 公司的算法和云团队,他于不久前毕业于斯坦福大学,在大学期间,加入吴恩达的机器学习小组并从事研究。他具有强烈的创业精神、敏锐的设计感和丰富的经验,他从事的领域涵盖从硬件到软件的整个工程堆栈。他非常喜欢艺术、设计、人工智能、电影和 Baltimore Ravens 球队。

 

有关编译器优化的更完整信息,请参阅优化通知