AdderNet是由华为、北大和悉尼大学共同提出的一个网络层结构。主要思想是用加法代替卷积层特征计算的乘法,从而实现减少深度网络的计算。
1、卷积计算
在深度卷积神经网络中,设F∈Rd×d×cin×coutF\in R^{d\times d\times c_{in}\times c_{out}}F∈Rd×d×cin×cout是一个卷积核,输入的特征图是X∈RH×W×cinX\in R^{H\times W\times c_{in}}X∈RH×W×cin,则它们的卷积计算如下:
Y(m,n,t)=∑i=0d∑j=0d∑k=0cinX(m+i,n+j,k)∗F(i,j,k,t)(1)Y(m,n,t)=\sum_{i=0}^d\sum_{j=0}^d\sum_{k=0}^{c_{in}}{X(m+i, n+j, k)*F(i,j,k,t)} \tag{1}Y(m,n,t)=i=0∑dj=0∑dk=0∑cinX(m+i,n+j,k)∗F(i,j,k,t)(1)
把卷积核拉平成一个向量,对应的特征图区域也拉平成一个向量,单层特征图卷积可写成如下形式:
Y′=∑i=0d2−1X(i)⋅F(i)(2)Y'=\sum_{i=0}^{d^2-1}{X(i) \cdot F(i)} \tag{2}Y′=i=0∑d2−1X(i)⋅F(i)(2)
卷积描述和向量的内积是一样的,也就是说卷积描述的是两个向量的相似程度,而描述向量相似程度的还有其他的形式,比如说L2L_2L2距离和L1L_1L1距离。
在这篇文章中,采用L1L_1L1 距离代替卷积,这样就把乘法用加法替换了。
2、特征的加法计算
用L1L_1L1距离替换卷积计算,公式(1)(1)(1)就可写成如下形式:
Y(m,n,t)=−∑i=0d∑j=0d∑k=0cin∣X(m+i,n+j,k)−F(i,j,k,t)∣(3)Y(m,n,t)=-\sum_{i=0}^{d}\sum_{j=0}^{d}\sum_{k=0}^{c_{in}}{|X(m+i,n+j,k)-F(i,j,k,t)|}\tag{3}Y(m,n,t)=−i=0∑dj=0∑dk=0∑cin∣X(m+i,n+j,k)−F(i,j,k,t)∣(3)
用公式(3)(3)(3)计算的特征都是负数,因此在特征计算后,采用BN层来归一化,之后再用激活函数提高特征非线性。
3、优化
反向传播计算加法层对参数的偏导是一个符号函数:
∂Y(m,n,t)∂F(i,j,k,t)=sgn(X(m+i,n+j,k)−F(i,j,k,t))(4)\frac{\partial{Y(m,n,t)}}{\partial{F(i,j,k,t)}}=sgn(X(m+i,n+j,k)-F(i,j,k,t))\tag{4}∂F(i,j,k,t)∂Y(m,n,t)=sgn(X(m+i,n+j,k)−F(i,j,k,t))(4)
由公式(4)(4)(4)可知,加法层计算的梯度只是三个数−1,0,1-1, 0,1−1,0,1中的一个。但是其梯度并不是梯度下降最快的方向,而且随着维度的增加,其指向性更差。因此公式(4)(4)(4)并不适合用于优化含有大量参数的神经网络。作者用公式(5)(5)(5)来更新AdderNet的梯度:
∂Y(m,n,t)∂F(i,j,k,t)=X(m+i,n+j,k)−F(i,j,k,t)(5)\frac{\partial{Y(m,n,t)}}{\partial{F(i,j,k,t)}}=X(m+i,n+j,k)-F(i,j,k,t)\tag{5}∂F(i,j,k,t)∂Y(m,n,t)=X(m+i,n+j,k)−F(i,j,k,t)(5)
作者还发现输入特征XXX的梯度对参数的更新也很有用。为了避免XXX的梯度绝对值大于1而造成的梯度爆炸,对其进行了限制:
∂Y(m,n,t)∂X(m+i,n+j,k)=HT(F(i,j,k,t)−X(m+i,n+j,k))(6)\frac{\partial{Y(m,n,t)}}{\partial{X(m+i,n+j,k)}}=HT(F(i,j,k,t)-X(m+i,n+j,k))\tag{6}∂X(m+i,n+j,k)∂Y(m,n,t)=HT(F(i,j,k,t)−X(m+i,n+j,k))(6)
其中
HT(x)={xif−1<x<11x>1−1x<−1HT(x)=\begin{cases}
x & if -1<x<1\\
1 & x > 1\\
-1 & x < -1
\end{cases}HT(x)=⎩⎪⎨⎪⎧x1−1if−1<x<1x>1x<−1
梯度计算也好了,似乎一切都好了,但是还是有个问题:加法层的方差会很大。
4、自适应可学习尺度
假设权重和输入特征是独立同分布的正态分布,用卷积计算的输出方差是:
Var[YCNN]=∑i=0d∑j=0d∑k=0cinVar[X×F]=d2cinVar[X]Var[F](7)Var[Y_{CNN}]=\sum_{i=0}^d\sum_{j=0}^d\sum_{k=0}^{c_{in}}Var[X\times F]=d^2c_{in}Var[X]Var[F]\tag{7}Var[YCNN]=i=0∑dj=0∑dk=0∑cinVar[X×F]=d2cinVar[X]Var[F](7)
而对于加法层的输出方差是:
Var[YAdder]=∑i=0d∑j=0d∑k=0cinVar[∣X−F∣]=(1−2π)d2cin(Var[X]+Var[F])(8)Var[Y_{Adder}]=\sum_{i=0}^d\sum^d_{j=0}\sum_{k=0}^{c_{in}}{Var[|X-F|]}=(1-\frac{2}{\pi})d^2c_{in}(Var[X]+Var[F])\tag{8}Var[YAdder]=i=0∑dj=0∑dk=0∑cinVar[∣X−F∣]=(1−π2)d2cin(Var[X]+Var[F])(8)
在BN层的损失函数lll对xxx的偏导是和方差有关的:
∂l∂xi=∑j=1mγm2σB{∂l∂yi−∂l∂yj[1+(xi−xj)(xj−μB)σB]}(9)\frac{\partial{l}}{\partial{x_i}}=\sum_{j=1}^{m}{\frac{\gamma}{m^2\sigma_B}\{\frac{\partial{l}}{\partial{y_i}}-\frac{\partial{l}}{\partial{y_j}}[1+\frac{(x_i-x_j)(x_j-\mu_B)}{\sigma_B}]\}}\tag{9}∂xi∂l=j=1∑mm2σBγ{∂yi∂l−∂yj∂l[1+σB(xi−xj)(xj−μB)]}(9)
其中σB\sigma_BσB是输入特征的方差。
CNN权重的方差都很小的,一般的数量级在10−310^{-3}10−3或者10−410^{-4}10−4。因此用一个很小的数乘以Var[X]Var[X]Var[X]比两者相加要小很多,因此公式(9)(9)(9)中的梯度就会小很多,这就会使得参数更新变得很慢,甚至会停在鞍点上。
虽然可以采用大的学习率来提升学习过程效果,但是从上图可以看出不同层其权重梯度变化很大,这表明每一层的参数需要不同。因此作者给每一层设计了不同学习率:
ΔFl=γ×αl×Δ(Fl)(10)\Delta F_l=\gamma\times \alpha_l\times \Delta(F_l)\tag{10}ΔFl=γ×αl×Δ(Fl)(10)
这里的γ\gammaγ是全局学习率,Δ(Fl)\Delta(F_l)Δ(Fl)是卷积核的梯度,αl\alpha_lαl是对应的局部学习率。输入是经过BN的,也就是说在AdderNet中,filters的值也是经过了归一化,因此将局部学习率定义为如下形式:
αl=ηk∣∣Δ(Fl)∣∣2(11)\alpha_l=\frac{\eta \sqrt{k}}{||\Delta(F_l)||_2}\tag{11}αl=∣∣Δ(Fl)∣∣2ηk(11)
这里的η\etaη是一个控制加法filter学习率的超参数,kkk是FlF_lFl中参数的个数。
5、训练流程及实验结果
训练流程如下:
实验结果
5.1、特征的分布
5.2、在CIFAR-10和CIFAR-100测试结果
5.2、在ImageNet测试结果
从测试结果看,效果不错,但是没有给出前向结构的运行时间,感觉可能是时间也还是个瓶颈。虽然单个加法运算所需要的时间比乘法的要少,但是从公式(3)(3)(3)可以看出在计算特征时需要判断计算值的符号,并且这个判断是在大量的循环内的,这需要消耗大量的时间,很可能比卷积消耗的时间还要多。