一、参考资料
神经网络参数量、计算量(FLOPS)、内存访问量(MAC)计算详解
5种方法获取Torch网络模型参数量计算量等信息
卷积神经网络的参数计算
浅谈深度学习:如何计算模型以及中间变量的显存占用大小
二、参数量与计算量相关介绍
1. 为什么要统计模型参数量和计算量
- 好的网络模型不仅要求精度准,还要要求模型的参数量和计算量不大,才能有利于部署。
- 统计模型的参数量和计算量可以用于不同网络模型之间的对比分析。
- 有的模型虽然参数量相同,但是可能因为连接方式和结构等不同而导致计算量不同。
2. 计算量与参数量的概念
- 计算量是指网络模型需要计算的运算次数,参数量是指网络模型自带的参数数量多少。
- 计算量对应时间复杂度,参数量对应于空间复杂度。
- 计算量决定了网络执行时间的长短,参数量决定了占用显存的大小。
三、参数量的计算方法
下图中是一个32x32x3的输入,用一个5x5x3的卷积对其中某个位置的计算,这里计算的是一个点积,所以输出是一个单独的标量值。
因为卷积的操作是通过一个滑动窗口实现的,那么通过卷积操作,我们就得到了一个28x28x1的输出。
如果有6个filter,那么就会得到一个28x28x6的输出。
这就是一个最基础的卷积操作,那么这里用到的参数是多少呢?我们只需要把每个filter的参数累加起来,当然,不要忘了加上bias偏置:5x5x3x6 + 6 = 456。
另外,计算卷积以后的输出的大小,如下图所示,N是输入图像的size,F是filter的size,stride是滑动的步长。
然而,从上图中最后一个例子可以看到,stride大于1的时候不一定能整除,此时,需要在原图像上加上一层padding填充,然后再用前面的公式计算即可。
另外,还有一个maxpooling操作,该操作会改变输入输出,但不会有参数。所以使用和计算卷积一样的公式计算即可。
四、参数量、计算量的数学表达
1. 卷积层
1.1 参数量
Conv2d(Cin, Cout, K):参数量为 Cin × Cout × K × K
对于卷积层来说,参数量就是卷积核里所有参数的数量。
假设,每个卷积核的尺寸是 D K ∗ D K ∗ M D_K * D_K*M DK∗DK∗M,一共有N个卷积核,所以标准卷积的参数量为:
如果考虑bias偏置项,则参数量为: D K ∗ D K ∗ M ∗ N + N D_K * D_K * M * N + N DK∗DK∗M∗N+N
如果不考虑bias偏置项,则参数量为: D K ∗ D K ∗ M ∗ N D_K * D_K * M * N DK∗DK∗M∗N
1.2 计算量
对于卷积层来说,我们得到的特征图都是进行一系列的乘加运算得到的。
假设,每个卷积核的尺寸是 D K ∗ D K ∗ M D_K * D_K * M DK∗DK∗M,一共有N个卷积核,输出的特征图尺寸是 D F ∗ D F D_F * D_F DF∗DF。
一次卷积乘法运算次数为: D K ∗ D K ∗ M D_K * D_K * M DK∗DK∗M
一次卷积加法运算次数为: D K ∗ D K ∗ M − 1 ( 27 个数相加,做 26 次加法运算 ) D_K * D_K * M-1 \quad \textcolor{red}{(27个数相加,做26次加法运算)} DK∗DK∗M−1(27个数相加,做26次加法运算)
一共进行 D F ∗ D F ∗ N 次卷积运算 ( 输出 f e a t u r e m a p 大小为 D F ∗ D F ∗ N ) D_F * D_F*N \ 次卷积运算 \quad \textcolor{red}{(输出feature \ map大小为D_F * D_F*N)} DF∗DF∗N 次卷积运算(输出feature map大小为DF∗DF∗N)
乘加运算总次数: ( 2 ∗ D K ∗ D K ∗ M − 1 ) ∗ ( D F ∗ D F ∗ N ) (2*D_K * D_K * M-1)*(D_F * D_F*N) (2∗DK∗DK∗M−1)∗(DF∗DF∗N)
通常,标准卷积的计算量只考虑乘法运算: D K ∗ D K ∗ M ∗ N ∗ D F ∗ D F D_K * D_K * M * N * D_F * D_F DK∗DK∗M∗N∗DF∗DF。
1.3 内存访问量MAC
输入: D K ∗ D K ∗ M D_K * D_K * M DK∗DK∗M
输出: D F ∗ D F ∗ N D_F * D_F * N DF∗DF∗N
权重: D K ∗ D K ∗ M ∗ N D_K * D_K * M * N DK∗DK∗M∗N
那么,上述三项之和为MAC: D K ∗ D K ∗ M + D F ∗ D F ∗ N + D K ∗ D K ∗ M ∗ N D_K * D_K * M + D_F * D_F * N + D_K * D_K * M * N DK∗DK∗M+DF∗DF∗N+DK∗DK∗M∗N
2. 全连接层
2.1 参数量
Linear(M->N):参数量为M×N+N
假设,输入 C i C_i Ci 个神经元,输出 C o C_o Co 个神经元。
如果考虑bias偏置项,则参数量为: C i ∗ C o + C o C_i * C_o + C_o Ci∗Co+Co
如果不考虑bias偏置项,则参数量为: C i ∗ C o C_i * C_o Ci∗Co
2.2 计算量
假设,输入 C i C_i Ci 个神经元,输出 C o C_o Co 个神经元。
一个神经元乘法运算次数为: C i C_i Ci
一个神经元加法运算次数为: C o C_o Co
乘加运算总次数为: ( 2 ∗ C i − 1 ) ∗ C o (2*C_i - 1)*C_o (2∗Ci−1)∗Co
2.3 内存访问量MAC
输入: C i C_i Ci
输出: C o C_o Co
权重: C i ∗ C o C_i*C_o Ci∗Co
那么,上述三项之和为MAC: C i + C o + C i ∗ C o C_i+C_o+C_i*C_o Ci+Co+Ci∗Co
3. BN层
BatchNorm(N):参数量为 2N
参数量: 2 ∗ C i ( b n . w e i g h t + b n . b i a s ) 2*C_i \quad \textcolor{red}{(bn.weight + bn.bias)} 2∗Ci(bn.weight+bn.bias)
4. Embedding层
Embedding(N,W):参数量为 N × W
5. 代码示例
import torch
import torch.nn as nn
from torchvision import models
class MyModel(nn.Module):
def __init__(self, ): # input the dim of output fea-map of Resnet:
super(MyModel, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.gap = nn.AdaptiveAvgPool1d(1)
self.fc = nn.Linear(2048, 512)
def forward(self, input): # input is 2048!
x = self.conv1(input)
x = self.bn1(x)
x = self.relu(x)
x = self.gap(x)
x = self.fc(x)
return x
##############################
# 模型准备
model = MyModel()
blank = ' '
print('-----------------------------------------------')
print('| weight name | weight shape |')
print('-----------------------------------------------')
for index, (key, w_variable) in enumerate(model.named_parameters()):
if len(key)<=15: key = key + (15-len(key))*blank
w_variable_blank = ''
if len(w_variable.shape) == 1:
if w_variable.shape[0] >= 100: w_variable_blank = 8*blank
else: w_variable_blank = 9*blank
elif len(w_variable.shape) == 2:
if w_variable.shape[0] >= 100: w_variable_blank = 2*blank
else: w_variable_blank = 3*blank
print('| {} | {}{} |'.format(key, w_variable.shape, w_variable_blank))
key = 0
print('-----------------------------------------------')
输出:
-----------------------------------------------
| weight name | weight shape |
-----------------------------------------------
| conv1.weight | torch.Size([64, 3, 7, 7]) |
| bn1.weight | torch.Size([64]) |
| bn1.bias | torch.Size([64]) |
| fc.weight | torch.Size([512, 2048]) |
| fc.bias | torch.Size([512]) |
-----------------------------------------------
解释说明
- CNN卷积层参数量: D K ∗ D K ∗ M ∗ N = 7 ∗ 7 ∗ 3 ∗ 64 D_K * D_K * M * N=7*7*3*64 DK∗DK∗M∗N=7∗7∗3∗64;
- BN层参数量参数量: 2 ∗ C i = b n . w e i g h t + b n . b i a s = 64 + 64 2*C_i=bn.weight+bn.bias=64+64 2∗Ci=bn.weight+bn.bias=64+64;
- FC全连接层参数量: C i ∗ C o + C o = 2048 ∗ 512 + 512 C_i * C_o + C_o = 2048*512 + 512 Ci∗Co+Co=2048∗512+512。
五、常见网络模型的参数量
LeNet-5
LeNet-5, convolutional neural networks
Gradient-Based Learning Applied to DocumentRecognition
LeNet-5网络结构如下:
LeNet-5网络参数量如下:
网络层(操作) | 输入 | filter | stride | padding | 输出 | 计算公式 | 参数量 |
---|---|---|---|---|---|---|---|
Input | 32x32x1 | 32x32x1 | 0 | ||||
Conv1 | 32x32x1 | 5x5x1x6 | 1 | 0 | 28x28x6 | 5x5x1x6+6 | 156 |
MaxPool1 | 28x28x6 | 2x2 | 2 | 0 | 14x14x6 | 0 | |
Conv2 | 14x14x6 | 5x5x6x16 | 1 | 0 | 10x10x16 | 5x5x6x16+16 | 2416 |
MaxPool2 | 10x10x16 | 2x2 | 2 | 0 | 5x5x16 | 0 | |
FC1 | 5x5x16 | 120 | 5x5x16x120+120 | 48120 | |||
FC2 | 120 | 84 | 120x84+84 | 10164 | |||
FC3 | 84 | 10 | 84x10+10 | 850 |
参数总量: 61706
AlexNet
ImageNet Classification with Deep Convolutional Neural Networks
AlexNet网络结构如下:
AlexNet的结构图有些奇怪。但其实是因为要把网络拆分到两个GPU上,才画成了两层,两层的结构是一样的,下面计算的时候的结构相当于合并以后的网络。
AlexNet网络参数量如下:
网络层(操作) | 输入 | filter | stride | padding | 输出 | 计算公式 | 参数量 |
---|---|---|---|---|---|---|---|
Input | 224x224x3 | 224x224x3 | 0 | ||||
Conv1 | 224x224x3 | 11x11x3x96 | 4 | 0 | 55x55x96 | 11x11x3x96+96 | 34,944 |
MaxPool1 | 55x55x96 | 3x3 | 2 | 0 | 27x27x96 | 0 | |
Norm1 | 27x27x96 | 27x27x96 | 0 | ||||
Conv2 | 27x27x96 | 5x5x96x256 | 1 | 2 | 27x27x256 | 5x5x96x256+256 | 614,656 |
MaxPool2 | 27x27x256 | 3x3 | 2 | 0 | 13x13x256 | 0 | |
Norml2 | 13x13x256 | 13x13x256 | 0 | ||||
Conv3 | 13x13x256 | 3x3x256x384 | 1 | 1 | 13x13x384 | 3x3x256x384+384 | 885,120 |
Conv4 | 13x13x384 | 3x3x384x384 | 1 | 1 | 13x13x384 | 3x3x384x384+384 | 1,327,488 |
Conv5 | 13x13x384 | 3x3x384x256 | 1 | 1 | 13x13x256 | 3x3x384x256+256 | 884,992 |
MaxPool3 | 13x13x256 | 3x3 | 2 | 0 | 6x6x256 | 0 | |
FC6 | 6x6x256 | 4096 | 6x6x256x4096+4096 | 37,752,832 | |||
FC7 | 4096 | 4096 | 4096x4096+4096 | 16,781,312 | |||
FC8 | 4096 | 1000 | 4096x1000+1000 | 4,097,000 |
参数总量: 62,378,344
VGG-16
Very Deep Convolutional Networks for Large-Scale Image Recognition
VGG-16网络结构如下:
VGG-16网络参数量如下:
网络层(操作) | 输入 | filter | stride | padding | 输出 | 计算公式 | 参数量 |
---|---|---|---|---|---|---|---|
Input | 224x224x3 | 224x224x3 | 0 | ||||
Conv3-64 | 224x224x3 | 3x3x3x64 | 1 | 1 | 224x224x64 | 3x3x3x64 + 64 | 1,792 |
Conv3-64 | 224x224x64 | 3x3x64x64 | 1 | 1 | 224x224x64 | 3x3x64x64 + 64 | 36,928 |
MaxPool2 | 224x224x64 | 2x2 | 2 | 0 | 112x112x64 | 0 | |
Conv3-128 | 112x112x64 | 3x3x64x128 | 1 | 1 | 112x112x128 | 3x3x64x128 + 128 | 73,856 |
Conv3-128 | 112x112x128 | 3x3x128x128 | 1 | 1 | 112x112x128 | 3x3x128x128 + 128 | 147,584 |
MaxPool2 | 112x112x128 | 2x2 | 2 | 0 | 56x56x128 | 0 | |
Conv3-256 | 56x56x128 | 3x3x128x256 | 1 | 1 | 56x56x256 | 3x3x128x256 + 256 | 295,168 |
Conv3-256 | 56x56x256 | 3x3x256x256 | 1 | 1 | 56x56x256 | 3x3x256x256 + 256 | 590,080 |
Conv3-256 | 56x56x256 | 3x3x256x256 | 1 | 1 | 56x56x256 | 3x3x256x256 + 256 | 590,080 |
MaxPool2 | 56x56x256 | 2x2 | 2 | 0 | 28x28x256 | 0 | |
Conv3-512 | 28x28x256 | 3x3x256x512 | 1 | 1 | 28x28x512 | 3x3x256x512 + 512 | 1,180,160 |
Conv3-512 | 28x28x512 | 3x3x512x512 | 1 | 1 | 28x28x512 | 3x3x512x512 + 512 | 2,359,808 |
Conv3-512 | 28x28x512 | 3x3x512x512 | 1 | 1 | 28x28x512 | 3x3x512x512 + 512 | 2,359,808 |
MaxPool2 | 28x28x512 | 2x2 | 2 | 0 | 14x14x512 | 0 | |
Conv3-512 | 14x14x512 | 3x3x512x512 | 1 | 1 | 14x14x512 | 3x3x512x512 + 512 | 2,359,808 |
Conv3-512 | 14x14x512 | 3x3x512x512 | 1 | 1 | 14x14x512 | 3x3x512x512 + 512 | 2,359,808 |
Conv3-512 | 14x14x512 | 3x3x512x512 | 1 | 1 | 14x14x512 | 3x3x512x512 + 512 | 2,359,808 |
MaxPool2 | 14x14x512 | 2x2 | 2 | 0 | 7x7x512 | 0 | |
FC1 | 7x7x512 | 4096 | 7x7x512x4096 + 4096 | 102,764,544 | |||
FC2 | 4096 | 4096 | 4096*4096 + 4096 | 16,781,312 | |||
FC3 | 4096 | 1000 | 4096*1000 + 1000 | 4,097,000 |
参数总量: 138,357,544