卷积的实现原理
我前面的一篇文章中,卷积操作的计算量分析中,引用了矩阵相乘来概括卷积的计算量,这样做确实是有道理的,因为在卷积的实现中的确是通过矩阵相乘来加速卷积的计算。但是我在那篇文章只是简单的通过矩阵相乘来简单的分析了一下维度信息,事实上,各种框架的实现也并不一定符合我的分析,但是殊途同归。
本文将为大家耐心整理了一下具体的实现(吐槽一下干这件事确实花了我相当多的功夫,因为网上写的东西太乱了,很多人都搞错了框架和实现的对应。再或者是自己的分析和配图不符,或者是自己实现后一运行,单通道对了,多通道就错了。)
首先也是从最容易错的地方,通道这个概念说起,大体目前的框架实现卷积的时候,特征图格式分为两种,一种是 N ∗ C ∗ H ∗ W N*C*H*W N∗C∗H∗W,即N表示batchsize中特征图的数量,C表示通道数,H,W表示每个特征图的长宽。一种是 N ∗ H ∗ W ∗ C N*H*W*C N∗H∗W∗C,与第一种的区别在于通道的位置不一样。首先通道的位置决定了一个通道是否连续的问题,连续的利于访问局部性,可以提高速度。另一个差异决定了决定了矩阵乘法的结果形状转化有区别。
另外一处区别就在于,那就是矩阵乘法操作的特征图作为左元和右元的区别。这句话怎么理解,一个 4 ∗ 5 4*5 4∗5的矩阵,和一个 4 ∗ 3 4*3 4∗3的矩阵要想做矩阵乘法,显然要对其中一个矩阵做转置,谁转置了,谁就要放到乘号的右边这样才可以相乘,所以将其作为右元。右元做完乘法,保留了列数,左元保留了行数。如果我们的特征图是 N ∗ H ∗ W ∗ C N*H*W*C N∗H∗W∗C,我们需要保留特征图的数量N,直观上来想,特征图的数量N我们适合保留在最左边,所以把特征图放在乘法的左元比较合适。但实际上这里的区别不大,我们先讲解放在右边的情况。
特征图作为矩阵乘法的右元
如果我们把特征图作为右元,特征图的维度就是( N , C i n , H , W N,C_{in},H,W N,Cin,H,W),卷积之后的特征图维度是( N , C o u t