FLOPs

Floating Point Operations:
浮点运算次数,每一个加、减、乘、除操作都算1FLOPs操作,常用来衡量模型计算复杂度。
注意下FLOPS:注意全大写,是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度。是一个衡量硬件性能的指标,两者别弄混。。。

MACs

Multiply–Accumulate Operations:
乘加累积操作数,常常被人们与FLOPs概念混淆。实际上1MACs包含一个乘法操作与一个加法操作,大约包含2FLOPs。通常MACs与FLOPs存在一个2倍的关系

关系

为什么使用乘加运算指标(MACs)呢?因为神经网络运算中内积、乘加运算无处不在:
对于一个3*3滤波器在特征图上的一次运算可以表示为:
y = w 0 ∗ x 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + w 4 ∗ x 4 + w 5 ∗ x 5 + w 6 ∗ x 6 + w 7 ∗ x 7 + w 8 ∗ x 8 y=w_0*x_0+w_1*x_1+w_2*x_2+w_3*x_3+w_4*x_4+w_5*x_5+w_6*x_6+w_7*x_7+w_8*x_8 y=w0x0+w1x1+w2x2+w3x3+w4x4+w5x5+w6x6+w7x7+w8x8

对于上式,记 w 0 ∗ x 0 w_0*x_0 w0x0+… 为一次乘加,即1MACC。所以对于上式而言共有9次乘加,即9MACs(实际上,9次相乘、9-1次相加,但为了方便统计,将计算量近似记为9MACs,就像算法复杂度通常把 O(N+b)表示成O(N)一样,都只是一种近似,不需要纠结)

MACC vs FLOPs:对于上式而言,可以认为执行了9次乘法、9-1次加法,所以一共是9+(9-1)次FLOPs。所以近似来看1FLOPs ≈ 2MACC。(需要指出的是,现有很多硬件都将乘加运算作为一个单独的指令)。

使用

一般情况下ReLU层和Pooling层计算FLOPs,而conv层、FC层,计算MACC数
定义:
H i n H_{in} Hin W i n 、 C i n W_{in}、C_{in} WinCin表示输入特征图的长、宽、通道数
H o u t H_{out} Hout W o u t 、 C o u t W_{out}、C_{out} WoutCout表示输入特征图的长、宽、通道数

全连接层

  1. 我们令输入全连接层的是一个 I I I 维的列向量(也可以叫做 I × 1 I×1 I×1的矩阵),全连接层的参数是 J × I J×I J×I 维的参数矩阵。
  2. 那么全连接层在做的就是矩阵和向量做矩阵乘法,即 ( J × I ) × ( I × 1 ) = J × 1 (J×I)×(I×1)=J×1 (J×I)×(I×1)=J×1,就是参数矩阵的每一行都与输入的列向量做内积,所以共 I I I次计算。
  3. 然后一共有 J J J行,所以这个全连接层的计算量就是: MACs= J × I J×I J×I

卷积层

  1. 对于卷积层时,生成的单通道特征图中每个像素位置 i j ij ij都是经过了 K × K × C i n K × K × C_{in} K×K×Cin 次计算
  2. 而一个特征图的尺寸为 H o u t × W o u t H_{out} × W_{out} Hout×Wout所以单通道特征图的计算就为:
    K × K × C i n × H o u t × W o u t K × K × C_{in} × H_{out} × W_{out} K×K×Cin×Hout×Wout
  3. 生成的特征图共有 C o u t C_{out} Cout个通道,那么这个卷积层的计算量就为:
    MACs= K × K × C i n × C o u t × H o u t × W o u t K × K × C_{in} ×C_{out} × H_{out} × W_{out} K×K×Cin×Cout×Hout×Wout

深度分离卷积

深度分离卷积与常规卷积不同,它不组合输入通道,而是分别对每个通道执行卷积。对于具有 C i n C_{in} Cin 个通道的特征图,深度卷积创建一个也具有 C i n C_{in} Cin 个通道的输出特征图(就是说 C o u t = C i n C_{out}=C_{in} Cout=Cin)。每个通道都有自己的一组权重。
那么计算量就为:
MACs= K × K × C i n × H o u t × W o u t K × K × C_{in} × H_{out} × W_{out} K×K×Cin×Hout×Wout

注:因为考虑bias时,只是做加法,并没有做乘法,所以考虑bias并不会增加MACs 。

池化层

全局池化(常用):

针对输入所有值进行一次池化操作,不论是max、sum还是avg,都只需要对每个值都计算一次,所以:
FLOPs = H i n × W i n × C i n H_{in} × W_{in} ×C_{in} Hin×Win×Cin

一般池化(不常用):

对于输出的每一个值,都是一次池化操作,每次池化操作的计算量就是池化过滤器参数的数量。

FLOPs = H o u t × W o u t × C o u t × K × K H_{out} × W_{out} ×C_{out}× K × K Hout×Wout×Cout×K×K

激活层

ReLU/PReLU/ELU

对于输入的每一个值,都进行一个运算(例如:ReLU,对每个值 x x x 进行 m a x ( x , 0 ) max(x,0) max(x,0) 操作),所以总的计算量就是:
FLOPs = H i n × W i n × C i n H_{in} × W_{in} × C_{in} Hin×Win×Cin

Sigmoid

由公式: y = 1 1 + e x p ( − x ) \large y = \frac 1 { 1 + exp(-x)} y=1+exp(x)1 , 可以看到,对每个输入 x x x,要先取负数,然后取指数,再**+1**,再取倒数,即4个操作,所以总的计算量为:
FLOPs = H × W × C × 4 H × W ×C × 4 H×W×C×4

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐