概念
网络中的参数量(param)对应与空间Space概念,及空间复杂度。
浮点计算量(FLOPs)对应与时间Time概念,对应于时间复杂度。
如何计算网络中的参数量(param)
网络中的参数量(param)的计算需要分为:卷积层,池化层,全连接层
卷积层
需要关注的参数为:卷积核大小(kernel_size=k*k)输入通道大小(in_channel)输出通道大小(out_channel)
计算公式:
完全版:conv_param=(k*k*in_channel+bias)*out_channel,默认bias=1,
out_channel是filter(代表卷积核个数),且每个卷积核都有对应的bias。
举个例子:
image_size = 5x5x3
kernel_size = 3x3
in_channel = 3 (图像channel)
out_channel = 2 (卷积核数目\filter数目)
则该卷积层的参数个数为:
conv_param = ( kernel_size * in _channel + bias ) * out_channel = (5*3+1)*2 =152
池化层
池化层不需要参数。例如 max_pooling:直接最大化池化就可以,无需参数。
全连接层
全连接层有两种情况,一种是卷积层到全连接层,一种是全连接层到全连接层,因此需要分情况来讨论:
卷积层–全连接层
Conv_FC_param = feturemap_size * in_channel * out_neural
feturemap_size : 前一层特征图尺寸
in_channel : 前一层卷积核个数
out_neural : 全连接层神经元个数
全连接层–全连接层
FC_FC_param = in_neura * out_neural − bias
bias = out_neural,每个神经元都有一个bias。一般可忽略bias。
如何计算网络中的计算量
FLOPS:注意全大写,是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度。是一个衡量硬件性能的指标。
FLOPs:注意s小写,是floating point operations的缩写(s表复数),意指浮点运算数,理解为计算量。可以用来衡量算法/模型的复杂度。
链接:https://www.zhihu.com/question/65305385/answer/451060549
我们知道,通常我们去评价一个模型时,首先看的应该是它的精确度,当你精确度不行的时候,你和别人说我的模型预测的多么多么的快,部署的时候占的内存多么多么的小,都是白搭。但当你模型达到一定的精确度之后,就需要更进一步的评价指标来评价你模型:1)前向传播时所需的计算力,它反应了对硬件如GPU性能要求的高低;2)参数个数,它反应所占内存大小。为什么要加上这两个指标呢?因为这事关你模型算法的落地。比如你要在手机和汽车上部署深度学习模型,对模型大小和计算力就有严格要求。模型参数想必大家都知道是什么怎么算了,而前向传播时所需的计算力可能还会带有一点点疑问。所以这里总计一下前向传播时所需的计算力。它正是由FLOPs体现,那么FLOPs该怎么计算呢?
假设卷积核的大小为 k*k, 输入channel为M,输出channel为N,输出feature的宽为W,高为H。
bias为True时:
则计算量为:Flops = [2×(k×k×M) ] ×N×H×W
其中 k×k×M 为卷积中的乘法操作,k×k×M-1为卷积中的加法操作, + 1 为有bias。
bias为False时:
则参数数量为:Flops = (2×k×k×M-1) ×N×H×W
当使用BN时,还有两个可学习的参数α和β,参数量均为N
则参数数量为:Para = Flops = [(2×k×k×M-1) + 3 ] ×N×H×W
全连接层的计算量计算
假设 输入神经元数为M,输出神经元数为N,则
bias为True时:
则计算量为:FLOPs = [M+(M-1)+1]×N = 2 × M × N
bias为False时:
则参数数量为:Para = [M+(M-1)]×N = (2M-1)×N
实例计算_以lenet为例
简化计算,次Lenet中不适用激活函数ReLU函数
手动计算
代码
import torch
from torch import nn
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Sequential( # input shape (1, 28, 28)
nn.Conv2d(
in_channels=1, # input height gray just have one level
out_channels=20, # n_filters
kernel_size=5, # filter size
stride=1, # filter movement/step
padding=0
), # output shape (20, 24, 24)
#nn.ReLU(), # activation
nn.MaxPool2d(kernel_size=1,stride=2,padding=0), # choose max value in 2x2 area, output shape (16, 14, 14)
)
self.conv2 = nn.Sequential( # input shape (16, 14, 14)
nn.Conv2d(20, 50, 5, 1, 0), # output shape (32, 14, 14)
#nn.ReLU(), # activation
nn.MaxPool2d(1,stride=2), # output shape (32, 7, 7)
)
# flatten
# fc unit
self.fc1 = nn.Sequential(
nn.Linear(50*4*4,500),
#nn.ReLU()
)
self.fc2 = nn.Sequential(
nn.Linear(500,10),
#nn.ReLU()
)
def forward(self, x):
batchsz = x.size(0)
x = self.conv1(x)
x = self.conv2(x)
x = x.view(batchsz, 50*4*4)
x= self.fc1(x)
logits = self.fc2(x)
# # [b, 10]
# pred = F.softmax(logits, dim=1)
# loss = self.criteon(logits, y)
return logits
构建一个CNN网络,如下图所示
使用开源工具 torchstat
from torchstat import stat
from main import CNN
# 导入模型,输入一张输入图片的尺寸
cnn=CNN()
print(cnn)
stat(cnn,(1, 28,28))
输出结果
可直接使用 torchinfo 模块统计参数量
from torchinfo import summary
from main import CNN
# 导入模型,输入一张输入图片的尺寸
cnn=CNN()
batch_size = 1
summary(cnn, input_size=(batch_size, 1, 28, 28))
输出结果,如下图所示
使用开源工具 pytorch-OpCounter (推荐)
from main import CNN
import torch
# 导入模型,输入一张输入图片的尺寸
cnn=CNN()
from thop import profile
input = torch.randn(1, 1, 28, 28)
macs, params = profile(cnn, inputs=(input, ))
print('Total macc:{}, Total params: {}'.format(macs, params))
"""
Total macc:2307720.0, Total params: 431080.0
"""