论文阅读-Fast Algorithms for Convolutional Neural Networks

Title

Fast Algorithms for Convolutional Neural Networks

Abstract

现如今,人们花费数天的时间在GPU上来训练一个大型的卷积神经网络,在自动驾驶中,对行人检测的延迟要求非常高,手机等移动设备上的图像识别又受限于有限的计算资源,因此,从某种程度上来说,卷积神经网络能发展到什么程度和其运行速度息息相关。
一种基于FFT的卷积算法在较大的卷积核上收效甚好,但是现在主流趋势是用多层小卷积核来代替单层的大卷积核,而FFT在小卷积核上的效果则差强人意,基于此,作者提出用Winograd的minimal filtering algorithms来进行小卷积核的卷积计算,该方法适用于卷积核较小和batchsize较小的情况,并且极大的降低了计算复杂度。
最终,作者在GPU上实现了一个VGG网络,并观察了batchsize=1~64下该算法的表现。

Method

Convolutional Neural Networks

卷积神经网络中,卷积计算是指K个C通道的RxS卷积核和N个C通道的HxW输入特征进行计算,我们分别用 G k , c , u , v G_{k,c,u,v} Gk,c,u,v D i , c , x , y D_{i,c,x,y} Di,c,x,y来卷积核中的元素和输入特征图中的元素,那么卷积计算可以描述为
论文阅读-Fast Algorithms for Convolutional Neural Networks

Fast Algorithms

自从1980年以来,我们就知道,可以使用minimal
filtering algorithm来利用一个一维的长度为r的滤波器计算m个输出,
我们称此为F(m,r),它一共需要
论文阅读-Fast Algorithms for Convolutional Neural Networks
次乘法,受此启发,同样的,我们可以将F(m,r)和F(n,s)嵌套,从而得到一个2维的最小滤波器算法,它可以用一个rxs的卷积核计算mxn的输出,我们称之为F(mxn,rxs),一共需要
论文阅读-Fast Algorithms for Convolutional Neural Networks
次乘法。当然,我们可以继续进行嵌套,以计算更高维度的卷积。
有趣的是,最小滤波器算法所用的乘法次数恰好等于读取输入数据的次数,也就是说,对一维的F(m,r),我们需要读入m+r-1个数据,进行m+r-1次乘法,对二维的F(mxn,rxs),我们需要读入(m+r-1)x(n+s-1)个数据,同样进行(m+r-1)x(n+s-1)次乘法,因此可以认为,平均每个输入数据需要进行一次乘法运算。

1.F(2x2,3x3)

F(2,3)的标准版本(即不使用Winograd算法)需要2x3个乘法运算,而Winograd算法流程如下图所示:
论文阅读-Fast Algorithms for Convolutional Neural Networks
其中d是输入元素,共2+3-1等于4个,即d0,d1,d2,d3,而g则是相应的卷积核,计算得到2个输出。这里右边的m取值如下
论文阅读-Fast Algorithms for Convolutional Neural Networks
可以验证,左式和右式是相等的。该算法一共进行了4次乘法,4次加法(指d之间的加法),3次加法(指g之间的加法,g0+g2只需计算一次),2次和常数的乘法(同1/2相乘)以及4次加法(m之间的加法)。我们也可以写成如下形式:
论文阅读-Fast Algorithms for Convolutional Neural Networks
对于F(2,3),上述矩阵具有如下形式
论文阅读-Fast Algorithms for Convolutional Neural Networks
这里 ⨀ \bigodot 表示element-wise乘法。
同样,我们可以推广到二维的卷积,对 F ( m × m , r × r ) F(m\times m,r\times r) F(m×m,r×r)来说,有:
论文阅读-Fast Algorithms for Convolutional Neural Networks
其中g是一个 r × r r\times r r×r的卷积核,而d是一个 ( m + r − 1 ) × ( m + r − 1 ) (m+r-1)\times (m+r-1) (m+r1)×(m+r1)的输入特征图,当然,上述算法也适用于卷积核和输入特征图不是方形的情况(即m ≠ \neq =n,r ≠ \neq =s)。
我们以 F ( 2 × 2 , 3 × 3 ) F(2\times 2,3\times 3) F(2×2,3×3)为例,它一共进行了16次乘法,而标准的卷积则需要进行 2 × 2 × 3 × 3 = 36 2\times 2\times 3\times 3=36 2×2×3×3=36次乘法,乘法次数降低了2倍多。当然其代价是输入数据的转换使用了32次加法,卷积核的转换使用了28次浮点指令,最后的逆变换则使用了24次加法,不过相对乘法来说,加法的计算复杂度是有显著降低的。
更一般的,对于 F ( m × m , r × r ) F(m\times m,r\times r) F(m×m,r×r),每次需要读入 ( m + r − 1 ) ( m + r − 1 ) (m+r-1)(m+r-1) (m+r1)(m+r1)个输入数据,以及 r × r r\times r r×r个卷积核参数,计算得到 m × m m\times m m×m个输出,这个过程一共进行了(m+r-1)(m+r-1)次乘法。
因为每次计算 m × m m\times m m×m个输出,那么若设输出特征图尺寸为 H × W H\times W H×W,则整个输出特征图需分块计算 [ H / m ] [ W / m ] [H/m][W/m] [H/m][W/m]次,而且易知,相邻的输入tile会有r-1行或列的重叠。
若记 U = G g G T U=GgG^T U=GgGT, V = B T d B V=B^TdB V=BTdB,那么
Y = A T [ U ⨀ V ] A Y=A^T[U\bigodot V]A Y=AT[UV]A
我们用 ( x ~ , y ~ ) (\widetilde{x},\widetilde{y}) (x ,y )来标记每一个读入的 ( m + r − 1 ) ( m + r − 1 ) (m+r-1)(m+r-1) (m+r1)(m+r1)的tile,那么输出可以计算如下:
论文阅读-Fast Algorithms for Convolutional Neural Networks
这里的一个trick是,将 A T A^T AT A A A作用在 Σ \Sigma Σ以后的矩阵上,这主要得益于线性性质,通过此方法,可以使得本来需要进行C次的 A T ( . ) A A^T(.)A AT(.)A运算降低为只需进行1次。