前言
在用于计算机视觉任务的深度神经网络模型中,卷积算子作为一种重要的特征提取方式被广泛应用,本文针对常见的卷积算子参数量和计算量的计算方法进行分析,主要包括
普通卷积、深度可分离卷积、分组卷积
,以及自动计算模型参数量和计算量的工具库ptflops
进行简单介绍。
文章目录
- 前言
- 1. 普通卷积
- (1) Params
- (2) FLOPs
- 2. 深度可分离卷积
- (1) Params
- (2) FLOPs
- 3.分组卷积
- (1) Params
- (1) FLOPs
- 4. ptflops
1. 普通卷积
对于普通的卷积算子,也就是让卷积核在特征图上按照既定规则进行滑动,并在每一个位置对应元素相乘后累加得到输出特征图的一个像素点。
我们假设输入特征图维度(宽、高、通道数
)为
W
i
×
H
i
×
C
i
W_{i} \times H_{i} \times C_{i}
Wi×Hi×Ci,卷积核的维度(宽、高、卷积核个数
)为
K
w
×
K
h
×
C
i
K_{w} \times K_{h} \times C_{i}
Kw×Kh×Ci,输出特征图的维度(宽、高、通道数
)为
W
o
×
H
o
×
C
o
W_{o} \times H_{o} \times C_{o}
Wo×Ho×Co。
(1) Params
单个卷积核权重参数共有
K
w
×
K
h
×
C
i
K_{w} \times K_{h} \times C_{i}
Kw×Kh×Ci,偏置参数共有1个
,共有
C
o
C_{o}
Co个卷积核,因此,普通卷积算子的参数量为:
P a r a m s = ( K w × K h × C i + 1 ) × C o Params=(K_{w} \times K_{h} \times C_{i} +1) \times C_{o} Params=(Kw×Kh×Ci+1)×Co
(2) FLOPs
对于普通的卷积算子,卷积核在特征图上每滑动一次,将对应元素相乘后累加
得到输出特征图中的一个像素点,因此,输出特征图中的一个像素点的计算量为:
( K w × K h × C i ) × ( K w × K h × C i − 1 ) + 1 (K_{w} \times K_{h}\times C_{i}) \times (K_{w} \times K_{h}\times C_{i}-1)+1 (Kw×Kh×Ci)×(Kw×Kh×Ci−1)+1
其中
K
w
×
K
h
×
C
i
K_{w} \times K_{h}\times C_{i}
Kw×Kh×Ci是做乘法运算的次数,
K
w
×
K
h
×
C
i
−
1
K_{w} \times K_{h}\times C_{i}-1
Kw×Kh×Ci−1是做加法运算的次数,
+
1
+1
+1是加偏置运算的加法次数(每次滑动需要一次加偏置操作,或者理解为每一个输出特征像素需要一次加偏置操作
)。
输出特征图的维度大小是 W o × H o × C o W_{o} \times H_{o} \times C_{o} Wo×Ho×Co,故对于普通的卷积算子总的计算量为:
F L O P s = [ ( K w × K h × C i ) × ( K w × K h × C i − 1 ) + 1 ] × W o × H o × C o = 2 × K w × K h × C i × W o × H o × C o FLOPs=[(K_{w} \times K_{h}\times C_{i}) \times (K_{w} \times K_{h}\times C_{i}-1)+1]\times W_{o} \times H_{o} \times C_{o}\\ = 2\times K_{w} \times K_{h} \times C_{i} \times W_{o} \times H_{o} \times C_{o} FLOPs=[(Kw×Kh×Ci)×(Kw×Kh×Ci−1)+1]×Wo×Ho×Co=2×Kw×Kh×Ci×Wo×Ho×Co
2. 深度可分离卷积
对于深度可分离卷积算子,其主要由两部分操作组成,即深度卷积
(上图Depthwise Convolution)和点卷积
(上图Pointwise Convolution),深度卷积也叫逐通道卷积,具体实现为:对于输入特征图的每一个通道,都有一个对应的卷积核去和它做卷积运算,最后得到的特征图通道数和输入特征图通道数相同。点卷积即使用
1
×
1
1\times1
1×1大小的卷积核对特征图做普通卷积。
我们假设输入特征图的维度(宽、高、通道数
)为
W
i
×
H
i
×
C
i
W_{i} \times H_{i}\times C_{i}
Wi×Hi×Ci,深度可分离卷积中的深度卷积维度(宽、高、卷积核个数
)为
K
w
×
K
h
×
C
i
K_{w} \times K_{h}\times C_{i}
Kw×Kh×Ci,经过深度卷积后的维度(宽、高、通道数
)为
W
m
×
H
m
×
C
i
W_{m} \times H_{m} \times C_{i}
Wm×Hm×Ci,深度可分离卷积中的点卷积维度(宽、高、卷积核通道数
、卷积核个数
)为
1
×
1
×
C
i
×
C
o
1 \times 1 \times C_{i} \times C_{o}
1×1×Ci×Co,输出特征图的维度(宽、高、通道数
)为
W
o
×
H
o
×
C
o
W_{o} \times H_{o}\times C_{o}
Wo×Ho×Co。
我们再对照着上面的假设理解一次深度可分离卷积的过程,首先对于 W i × H i × C i W_{i} \times H_{i}\times C_{i} Wi×Hi×Ci输入特征图进行深度卷积,即逐通道 W i × H i W_{i} \times H_{i} Wi×Hi和深度卷积核 K w × K h K_{w} \times K_{h} Kw×Kh进行卷积运算然后生成一张特征图,输入特征图的通道数和深度卷积核的个数都为于 C i C_{i} Ci,故深度卷积共有 C i C_{i} Ci张输出特征图,然后对深度卷积得到的 C i C_{i} Ci张输出特征图进行点卷积(普通卷积),即每一个点卷积核 1 × 1 × C i 1 \times 1 \times C_{i} 1×1×Ci和深度卷积得到的 C i C_{i} Ci张输出特征图进行普通卷积得到一张 W o × H o W_{o} \times H_{o} Wo×Ho的特征图,而点卷积的个数共有 C o C_{o} Co 个,故输出特征图维度为 W o × H o × C o W_{o} \times H_{o}\times C_{o} Wo×Ho×Co。
理解其过程后,下面我们分析深度可分离卷积算子的参数量和计算量
(1) Params
对于深度卷积
,单个卷积核的维度大小(宽、高、卷积核通道
)为
K
w
×
K
h
×
1
K_{w} \times K_{h}\times 1
Kw×Kh×1,偏置参数共有1个
, 共有
C
i
C_{i}
Ci个深度卷积核,故其参数量为:
P a r a m s 深度卷积 = ( K w × K h × 1 + 1 ) × C i Params_{深度卷积} = (K_{w} \times K_{h} \times1+1) \times C_{i} Params深度卷积=(Kw×Kh×1+1)×Ci
对于点卷积
,单个卷积核的维度大小(宽、高、卷积核通道
)为
1
×
1
×
C
i
1 \times 1 \times C_{i}
1×1×Ci,偏置参数共有1个
, 共有
C
o
C_{o}
Co个深度卷积核,故其参数量为:
P a r a m s 点卷积 = ( 1 × 1 × C i + 1 ) × C o Params_{点卷积} = (1 \times 1 \times C_{i}+1) \times C_{o} Params点卷积=(1×1×Ci+1)×Co
故,对于深度可分离卷积
来说,其总的参数量为:
P a r a m s = P a r a m s 深度卷积 + P a r a m s 点卷积 = [ ( K w × K h + 1 ) × C i ] + [ ( 1 × 1 × C i + 1 ) × C o ] Params=Params_{深度卷积}+Params_{点卷积} =[(K_{w} \times K_{h}+1) \times C_{i}] + [(1 \times 1 \times C_{i}+1) \times C_{o}] Params=Params深度卷积+Params点卷积=[(Kw×Kh+1)×Ci]+[(1×1×Ci+1)×Co]
(2) FLOPs
对于深度卷积
,同样的深度卷积核在特征图上每滑动一次,将对应元素相乘后累加得到输出特征图中的一个像素点,因此,输出特征图中的一个像素点的计算量为:
( K w × K h × 1 ) × ( K w × K h × 1 − 1 ) + 1 (K_{w} \times K_{h} \times1) \times (K_{w} \times K_{h} \times 1-1)+1 (Kw×Kh×1)×(Kw×Kh×1−1)+1
其中
K
w
×
K
h
×
1
K_{w} \times K_{h} \times1
Kw×Kh×1是做乘法运算的次数,
K
w
×
K
h
×
1
−
1
K_{w} \times K_{h} \times1-1
Kw×Kh×1−1是做加法运算的次数,
+
1
+1
+1是加偏置运算的加法次数(每次滑动需要一次加偏置操作,或者理解为每一个输出特征像素需要一次加偏置操作
)。
注意:
这里的
×
1
\times 1
×1表示卷积核通道数,因为是逐通道卷积,也就是通道数为1的卷积运算。
深度卷积输出特征图的维度大小是 W m × H m × C i W_{m} \times H_{m}\times C_{i} Wm×Hm×Ci,故对于深度卷积算子总的计算量为:
F L O P s 深度卷积 = [ ( K w × K h ) × ( K w × K h − 1 ) + 1 ] × W m × H m × C i = 2 ⋅ ( K w × K h ) × W m × H m × C i FLOPs_{深度卷积} =[(K_{w} \times K_{h}) \times (K_{w} \times K_{h}-1)+1]\times W_{m} \times H_{m}\times C_{i}\\=2\cdot (K_{w} \times K_{h})\times W_{m} \times H_{m}\times C_{i} FLOPs深度卷积=[(Kw×Kh)×(Kw×Kh−1)+1]×Wm×Hm×Ci=2⋅(Kw×Kh)×Wm×Hm×Ci
对于点卷积
,同样的点卷积核在特征图上每滑动一次,将对应元素相乘后累加得到输出特征图中的一个像素点,因此,输出特征图中的一个像素点的计算量为:
( 1 × 1 × C i ) × ( 1 × 1 × C i − 1 ) + 1 (1 \times 1 \times C_{i}) \times (1 \times 1 \times C_{i}-1)+1 (1×1×Ci)×(1×1×Ci−1)+1
其中
1
×
1
×
C
i
1 \times 1 \times C_{i}
1×1×Ci是做乘法运算的次数,
1
×
1
×
C
i
−
1
1 \times 1 \times C_{i}-1
1×1×Ci−1是做加法运算的次数,
+
1
+1
+1是加偏置运算的加法次数(每次滑动需要一次加偏置操作,或者理解为每一个输出特征像素需要一次加偏置操作
)。
点卷积输出特征图的维度大小是 W o × H o × C o W_{o} \times H_{o}\times C_{o} Wo×Ho×Co,故对于点卷积算子总的计算量为:
F L O P s 点卷积 = [ ( 1 × 1 × C i ) × ( 1 × 1 × C i − 1 ) + 1 ] × W o × H o × C o = 2 ⋅ C i × W o × H o × C o FLOPs_{点卷积} =[(1 \times 1 \times C_{i}) \times (1 \times 1 \times C_{i}-1)+1] \times W_{o} \times H_{o}\times C_{o}\\ =2\cdot C_{i}\times W_{o} \times H_{o}\times C_{o} FLOPs点卷积=[(1×1×Ci)×(1×1×Ci−1)+1]×Wo×Ho×Co=2⋅Ci×Wo×Ho×Co
故对于深度可分离卷积
来说,其总的计算量为:
F L O P s = F L O P s 深度卷积 + F L O P s 点卷积 = [ 2 ⋅ ( K w × K h ) × W m × H m × C i ] + [ 2 ⋅ C i × W o × H o × C o ] FLOPs=FLOPs_{深度卷积}+FLOPs_{点卷积} =[2\cdot (K_{w} \times K_{h})\times W_{m} \times H_{m}\times C_{i}] + [2\cdot C_{i}\times W_{o} \times H_{o}\times C_{o}] FLOPs=FLOPs深度卷积+FLOPs点卷积=[2⋅(Kw×Kh)×Wm×Hm×Ci]+[2⋅Ci×Wo×Ho×Co]
3.分组卷积
分组卷积是卷积神经网络中常用的一种卷积操作,它将输入的特征图分成若干组,每组特征图分别与对应的卷积核进行卷积操作,然后将各组的卷积结果拼接在一起形成最终的输出特征图。上图左边是普通卷积的示意图,右图是分组卷积的示意图,下面大概介绍一下分组卷积的基本流程:
- 输入特征图分组:将输入特征图按照通道数分成若干组,每组包含相等数量的通道。
- 分组卷积核:为每个分组准备对应的卷积核,每个卷积核组的数量与输入特征图的分组数量相同。
- 分组卷积操作:对每个分组的输入特征图分别使用对应的分组卷积核进行卷积操作,得到各组的卷积结果。
- 输出特征图拼接:将各组的卷积结果按照通道顺序进行拼接,形成最终的输出特征图。
分组卷积的主要优势在于可以减少参数量和计算量,同时提高模型的并行性,特别适用于计算资源有限的场景。这种技术在一些轻量级的神经网络结构中得到了广泛的应用。
我们假设分组卷积的分组数为
g
g
g组,输入特征图的维度(宽、高、通道数
)为
W
i
×
H
i
×
C
i
W_{i} \times H_{i}\times C_{i}
Wi×Hi×Ci,那么每一组输入特征图的维度(宽、高、通道数
)为
W
i
×
H
i
×
C
i
g
W_{i} \times H_{i} \times \frac{C_{i}}{g}
Wi×Hi×gCi,共有
g
g
g组输入特征图;
卷积算子分组数同样为
g
g
g组,其维度(宽、高、通道数
、卷积核个数
)为
K
w
×
K
h
×
C
i
g
×
C
o
g
K_{w} \times K_{h} \times \frac{C_{i}}{g} \times \frac{C_{o}}{g}
Kw×Kh×gCi×gCo;
每一组中输入特征图和分组卷积核做卷积得到每一组的输出特征图维度为 W o × H o × C o g W_{o} \times H_{o} \times \frac{C_{o}}{g} Wo×Ho×gCo,g个组的输出特征图拼接在一起就是 W o × H o × C o W_{o} \times H_{o} \times C_{o} Wo×Ho×Co;
理解其过程后,下面我们分析深度可分离卷积算子的参数量和计算量
(1) Params
对于单个分组卷积算子来说,其维度(宽、高、通道数
)为
K
w
×
K
h
×
C
i
g
K_{w} \times K_{h} \times \frac{C_{i}}{g}
Kw×Kh×gCi,偏置参数共有1个
,单个分组的卷积核个数为
C
o
g
\frac{C_{o}}{g}
gCo,共有
g
g
g个分组卷积,故其参数量为:
P a r a m s = ( K w × K h × C i g + 1 ) × C o g × g Params=(K_{w} \times K_{h} \times \frac{C_{i}}{g}+1) \times \frac{C_{o}}{g}\times g Params=(Kw×Kh×gCi+1)×gCo×g
(1) FLOPs
对于分组卷积算子来说,同样的单个分组的卷积核在特征图上每滑动一次,将对应元素相乘后累加得到输出特征图中的一个像素点,因此,输出特征图中的一个像素点的计算量为:
( K w × K h × C i g ) + ( K w × K h × C i g − 1 ) + 1 (K_{w} \times K_{h} \times \frac{C_{i}}{g})+(K_{w} \times K_{h} \times \frac{C_{i}}{g}-1)+1 (Kw×Kh×gCi)+(Kw×Kh×gCi−1)+1
其中
K
w
×
K
h
×
C
i
g
K_{w} \times K_{h} \times \frac{C_{i}}{g}
Kw×Kh×gCi是做乘法运算的次数,
K
w
×
K
h
×
C
i
g
−
1
K_{w} \times K_{h} \times \frac{C_{i}}{g}-1
Kw×Kh×gCi−1是做加法运算的次数,
+
1
+1
+1是加偏置运算的加法次数(每次滑动需要一次加偏置操作,或者理解为每一个输出特征像素需要一次加偏置操作
)。
单个分组的卷积输出特征图维度为 W o × H o × C o g W_{o} \times H_{o} \times \frac{C_{o}}{g} Wo×Ho×gCo,故对于单个分组卷积算子总的计算量为:
F L O P s 单个分组 = [ ( K w × K h × C i g ) + ( K w × K h × C i g − 1 ) + 1 ] × W o × H o × C o g FLOPs_{单个分组}=[(K_{w} \times K_{h} \times \frac{C_{i}}{g})+(K_{w} \times K_{h} \times \frac{C_{i}}{g}-1)+1]\times W_{o} \times H_{o} \times \frac{C_{o}}{g} FLOPs单个分组=[(Kw×Kh×gCi)+(Kw×Kh×gCi−1)+1]×Wo×Ho×gCo
又因为共有 g g g组操作,故其总的计算量为
F L O P s = [ ( K w × K h × C i g ) + ( K w × K h × C i g − 1 ) + 1 ] × W o × H o × C o g × g = 2 × K w × K h × C i g × W o × H o × C o FLOPs=[(K_{w} \times K_{h} \times \frac{C_{i}}{g})+(K_{w} \times K_{h} \times \frac{C_{i}}{g}-1)+1] \times W_{o} \times H_{o} \times \frac{C_{o}}{g}\times g\\ = 2\times K_{w} \times K_{h} \times \frac{C_{i}}{g} \times W_{o} \times H_{o} \times C_{o} FLOPs=[(Kw×Kh×gCi)+(Kw×Kh×gCi−1)+1]×Wo×Ho×gCo×g=2×Kw×Kh×gCi×Wo×Ho×Co
回顾一下普通卷积的参数量核计算量,可以发现分组卷积的参数量和计算量都是普通卷积的 1 g \frac{1}{g} g1倍。
4. ptflops
ptflops 是一个自动计算模型参数量和计算量的库,可以通过pip/conda直接下载,即
pip install ptflops
速度过慢时可以使用-i参数指定源,即
pip install ptflops -i https://pypi.tuna.tsinghua.edu.cn/simple
使用举例:
import torch
from torchvision.models import resnet18
from ptflops import get_model_complexity_info
model = resnet50()
macs, params = get_model_complexity_info(model, (3, 224, 224), as_strings=True,print_per_layer_stat=True, verbose=True)
print("MACs=", str(macs / 1e9) + '{}'.format("G"))
print("MACs=", str(macs / 1e6) + '{}'.format("M"))
虽然它可以自己计算模型的参数量和计算量,但是对一些自定义的层或算子不支持,并且不支持带有批量的计算。
参考:
全连接-普通卷积-深度可分离卷积-分组卷积-计算量和参数量
普通卷积、分组卷积和深度分离卷积概念以及参数量计算