前言: 最近在研究FBN的时候看到了BNN这个概念,论文中有很多的概念都和BNN相关,这里记录一下对于BNN的理解
BNN全称Binarized Neural Networks中文译作二值化神经网络。其核心的思想就算把权重矩阵中权重值和各个激活函数的函数值同时二值化得到的神经网络.我们通过有两个二值化函数可以用来完成这个过程。
第一个是Sign函数
x b = Sign ( x ) = { + 1 if x ≥ 0 − 1 otherwise x^{b}=\operatorname{Sign}(x)=\left\{\begin{array}{ll} +1 & \text { if } x \geq 0 \\ -1 & \text { otherwise } \end{array}\right. xb=Sign(x)={+1−1 if x≥0 otherwise
其中x是真实变量值,Sign(x)是符号函数
第二个是随机式的:
x b = { + 1 with probability p = σ ( x ) − 1 with probability 1 − p σ ( x ) = clip ( x + 1 2 , 0 , 1 ) = max ( 0 , min ( 1 , x + 1 2 ) ) \begin{aligned} &x^{b}=\left\{\begin{array}{ll} +1 & \text { with probability } p=\sigma(x) \\ -1 & \text { with probability } 1-p \end{array}\right.\\ &\sigma(x)=\operatorname{clip}\left(\frac{x+1}{2}, 0,1\right)=\max \left(0, \min \left(1, \frac{x+1}{2}\right)\right) \end{aligned} xb={+1−1 with probability p=σ(x) with probability 1−pσ(x)=clip(2x+1,0,1)=max(0,min(1,2x+1))
随机式的二值化符号函数看起来要稍微复杂一点,也真是因为它在思想过程中比较困难,在实际运用的过程中也是第一种用的要多一些
通过将权重矩阵二值化,一个权重只占用一个比特,相当于单精度浮点型权重矩阵,网络模型内存消耗理论上能减少32倍。简单来说就是:模型速度更快,所需内存更小,这也是我们进行模型压缩的优化的主要目的
虽然BNN在训练的过程中使用的是二值化的权重和激活值,但是梯度是不可用二值化存储的,原因在于:
而且在计算参数的梯度时,二值化相当于给权重和激活添加了噪声,这类似于正则化的操作让模型的泛化性能更好,我们训练BNN的方法可以看作是Dropout的一种变体,只是计算参数梯度时的Dropout是把激活值设置为0,而二值化网络是对权重和参数进行二值化。
综上所述,我们不能对梯度进行二值化。
在BNN中使用了离散化的梯度传播,在反向传播的过程中要用到Sign函数的导数,然而Sign函数的导数几乎处处为0,这点是不客气的。我们需要对Sign函数就行一定的变形,这就得到了Htanh函数
Htanh ( x ) = Clip ( x , − 1 , 1 ) = max ( − 1 , min ( 1 , x ) ) \operatorname{Htanh}(x)=\operatorname{Clip}(x,-1,1)=\max (-1, \min (1, x)) Htanh(x)=Clip(x,−1,1)=max(−1,min(1,x))
二值化操作函数为:
q = sign ( r ) q=\operatorname{sign}(r) q=sign(r)
假设损失函数为C,C对q的导数已知,那么C对r的导数为:
g r = g q 1 ∣ r ∣ ≤ 1 g_{r}=g_{q} 1_{|r| \leq 1} gr=gq1∣r∣≤1
这就算Htanh函数
在具体的算法应用时,对于隐藏层单元:
我们利用符号函数的非线性获得激活值,即直接使用Sign(a)获得二值化后的激活值。
对于权重,Htanh和Sign两种函数都有用到:
在对参数进行更新时,对权重使用Htanh函数进行裁减,使得权重永远在[-1, 1]之间;
量化权重时,使用Sign(w)直接得到二值化的权重值;