手动计算:
先上公式。
p
a
r
a
m
c
o
n
v
=
(
k
w
∗
k
h
∗
c
i
n
)
∗
c
o
u
t
+
c
o
u
t
param_{conv}=(k_w * k_h * c_{in}) * c_{out} +c_{out}
paramconv=(kw∗kh∗cin)∗cout+cout
F
L
O
P
s
c
o
n
v
=
[
(
k
w
∗
k
h
∗
c
i
n
)
∗
c
o
u
t
+
c
o
u
t
]
∗
H
∗
W
FLOPs_{conv}=[(k_w * k_h * c_{in}) * c_{out} +c_{out}] * H * W
FLOPsconv=[(kw∗kh∗cin)∗cout+cout]∗H∗W
p
a
r
a
m
f
c
=
(
n
i
n
∗
n
o
u
t
)
+
n
o
u
t
param_{fc}=(n_{in} * n_{out}) + n_{out}
paramfc=(nin∗nout)+nout
F
L
O
P
s
f
c
=
(
n
i
n
∗
n
o
u
t
)
+
n
o
u
t
FLOPs_{fc}=(n_{in} * n_{out}) + n_{out}
FLOPsfc=(nin∗nout)+nout
parameter的计算
卷积层的parameter: 记卷积核的宽为 k w k_w kw,卷积核的高为 k h k_h kh,输入这一层的通道数是 c i n c_{in} cin,这一层输出的通道数是c_out,则这个卷积层的参数量是 ( k w ∗ k h ∗ c i n ) ∗ c o u t + c o u t (k_w * k_h * c_{in}) * c_{out} +c_{out} (kw∗kh∗cin)∗cout+cout。其中, ( k w ∗ k h ∗ c i n ) ∗ c o u t (k_w * k_h * c_{in}) * c_{out} (kw∗kh∗cin)∗cout是权重的数量,最后加的 c o u t c_out cout是偏置的数量。可以看出,卷积层的参数量只与卷积核的大小和输入输出的通道数有关。
全连接层的parameter: 因为全连接层中,会把输入先拉伸成一个flat的一维向量,原本feature map中的每个像素都变成一个结点,然后这一层的每个结点都会融合前面所有结点的信息,然后加上偏置。假设这一层的输入拉伸成flat向量之后结点数为 n i n n_{in} nin,这一层的输出结点数为 n o u t n_{out} nout,则这个全连接层的参数量是 ( n i n ∗ n o u t ) + n o u t (n_{in} * n_{out}) + n_{out} (nin∗nout)+nout。可以看出,全连接层参数量只与输入输出结点数有关。
FLOPs的计算
FLOPs是floating points of operations,是浮点运算次数,用来衡量模型的计算复杂度。计算FLOPs实际上是计算模型中乘法运算和加法运算的次数。(FLOPS与FLOPs的不同)
卷积层的FLOPs计算方法:卷积层所得到的每个feature map都是卷积核经过 ( k w ∗ k h ∗ c i n ) ∗ c o u t + c o u t (k_w * k_h * c_{in}) * c_{out} +c_{out} (kw∗kh∗cin)∗cout+cout次运算得到的,(其中乘法运算次数为 ( k w ∗ k h ∗ c i n ) ∗ c o u t (k_w * k_h * c_{in}) * c_{out} (kw∗kh∗cin)∗cout,加法运算次数为 c o u t c_{out} cout)。假设这一层输出的feature map是 H ∗ W H*W H∗W的,那这一层的浮点运算次数是 [ ( k w ∗ k h ∗ c i n ) ∗ c o u t + c o u t ] ∗ H ∗ W [(k_w * k_h * c_{in}) * c_{out} +c_{out}] * H * W [(kw∗kh∗cin)∗cout+cout]∗H∗W。观察可以发现,其实就是 n u m p a r a m ∗ H ∗ W num_{param} * H * W numparam∗H∗W。可以看出来,浮点运算次数不仅取决于卷积核的大小和输入输出通道数,还取决于特征图的大小。
全连接层的FLOPs计算方法:全连接层的输出是经过 ( n i n ∗ n o u t ) + n o u t (n_{in} * n_{out}) + n_{out} (nin∗nout)+nout次计算得到的,所以全连接层的FLOPs和参数量是相同的。
举个栗子~
在AlexNet中,以第一个卷积层和第二个全连接层的计算为例。第一个卷积层卷积核是11* 11 * 3 * 96的,如果在实现的时候加了偏置,那这一层的parameter为11* 11 * 3 * 96 + 96 =34944,FLOPs为34944 * 55 * 55 =105705600。如果在实现的时候加了批量正则化而不使用偏置,则parameter为11* 11 * 3 * 96=34848,FLOPs为34848 * 55 * 55=105415200。
第二个卷积层输入的结点数是2048,输出结点数也是2048,所以使用偏置时的parameter是20482048+2048=4196352,FLOPs同为4196352,不使用偏置时的参数量时20482048=4194304,FLOPs同为4194304。
通过代码自动计算:
g=tf.Graph() #实例化一个类,用于 tensorflow 计算和表示用的数据流图
with g.as_default():
model = ResNet('resnet164',27, 10, 1) #建一个模型
flops=tf.profiler.profile(g, options = tf.profiler.ProfileOptionBuilder.float_operation()) #计算浮点运算次数
params = tf.profiler.profile(g, options=tf.profiler.ProfileOptionBuilder.trainable_variables_parameter()) #计算参数量
print('original flops:',flops.total_float_ops)
print('original params:',params.total_parameters)