CNN卷积神经网络模型的参数量、计算量计算方法(概念版)

一、参考资料

神经网络参数量、计算量(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 DKDKM,一共有N个卷积核,所以标准卷积的参数量为:

如果考虑bias偏置项,则参数量为: D K ∗ D K ∗ M ∗ N + N D_K * D_K * M * N + N DKDKMN+N

如果不考虑bias偏置项,则参数量为: D K ∗ D K ∗ M ∗ N D_K * D_K * M * N DKDKMN

1.2 计算量

对于卷积层来说,我们得到的特征图都是进行一系列的乘加运算得到的。

假设,每个卷积核的尺寸是 D K ∗ D K ∗ M D_K * D_K * M DKDKM,一共有N个卷积核,输出的特征图尺寸是 D F ∗ D F D_F * D_F DFDF

一次卷积乘法运算次数为: D K ∗ D K ∗ M D_K * D_K * M DKDKM

一次卷积加法运算次数为: D K ∗ D K ∗ M − 1 ( 27 个数相加,做 26 次加法运算 ) D_K * D_K * M-1 \quad \textcolor{red}{(27个数相加,做26次加法运算)} DKDKM1(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)} DFDFN 次卷积运算(输出feature map大小为DFDFN)

乘加运算总次数: ( 2 ∗ D K ∗ D K ∗ M − 1 ) ∗ ( D F ∗ D F ∗ N ) (2*D_K * D_K * M-1)*(D_F * D_F*N) (2DKDKM1)(DFDFN)

通常,标准卷积的计算量只考虑乘法运算: D K ∗ D K ∗ M ∗ N ∗ D F ∗ D F D_K * D_K * M * N * D_F * D_F DKDKMNDFDF

1.3 内存访问量MAC

输入 D K ∗ D K ∗ M D_K * D_K * M DKDKM

输出 D F ∗ D F ∗ N D_F * D_F * N DFDFN

权重 D K ∗ D K ∗ M ∗ N D_K * D_K * M * N DKDKMN

那么,上述三项之和为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 DKDKM+DFDFN+DKDKMN

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 CiCo+Co

如果不考虑bias偏置项,则参数量为: C i ∗ C o C_i * C_o CiCo

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 (2Ci1)Co

2.3 内存访问量MAC

输入: C i C_i Ci

输出: C o C_o Co

权重: C i ∗ C o C_i*C_o CiCo

那么,上述三项之和为MAC: C i + C o + C i ∗ C o C_i+C_o+C_i*C_o Ci+Co+CiCo

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)} 2Ci(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 DKDKMN=77364
  • 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 2Ci=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 CiCo+Co=2048512+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

猜你喜欢

转载自blog.csdn.net/m0_37605642/article/details/134127563