深度学习 计算模型中每层参数的个数和FLOPs

本文介绍了如何使用PyTorch和Caffe等工具计算神经网络模型的速度及资源占用情况,包括参数数量、FLOPs和显存占用等,并探讨了Inception系列模型的优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的模型能跑多快——神经网络模型速度调研

浅谈深度学习:如何计算模型以及中间变量的显存占用大小

​​​​​​​pytorch: torchstat

from torchstat import stat
import torchvision.models as models

model = model.alexnet()
stat(model, (3, 224, 224))

flops-counter.pytorch

import torchvision.models as models
import torch
from ptflops import get_model_complexity_info

with torch.cuda.device(0):
  net = models.densenet161()
  flops, params = get_model_complexity_info(net, (3, 224, 224), as_strings=True, print_per_layer_stat=True)
  print('{:<30}  {:<8}'.format('Computational complexity: ', flops))
  print('{:<30}  {:<8}'.format('Number of parameters: ', params))

FLOPS:全大写,是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度。是一个衡量硬件性能的指标。

FLOPs:s小写,是floating point operations的缩写(s表复数),意指浮点运算数,理解为计算量。可以用来衡量算法/模型的复杂度。

对于普通卷积层来说:FLOPs=2HW(CinK^2+1)Cout

对于深度可分离卷积: FLOPs=2HW*Cin*(K^2+Cout)

可视化模型有很多方法,caffe的用netscope。而最方便的莫过于netron,几乎所有的格式都支持,但有个不好的地方就是没法打印输出的形状和计算量等比较关键的信息,中间格式ONNX(tutorials),还有微软的mmdnn,百度的X2Paddle.

 Inception 系列模型是如何优化复杂度的

  • V1使用1*1降维和GAP代替Flatten操作
  • V2使用两个3*3卷积代替5*5卷积
  • V3使用 N*1与  1*N卷积级联替代 N*N 卷积
  • Xception使用可分离卷积代替普通卷积

ShuffleNetV2中提出的实用的指导原则:

  • 同等通道大小最小化内存访问量, 1x1卷积进行平衡输入和输出的通道大小
  • 过量使用组卷积会增加MAC, 组卷积要谨慎使用, 注意分组数
  • 网络碎片化会降低并行度, 避免网络的碎片化
  • 不能忽略元素级操作, 减少元素级运算. 比如ReLU和Add,虽然它们的FLOPs较小,但是却需要较大的MAC

caffe:

import sys
import caffe
from numpy import prod, sum

def get_flops(deploy_file, show_detail=True,flop_layers = ['Convolution', 'DepthwiseConvolution', 'InnerProduct']):
    net=caffe.Net(deploy_file,caffe.TEST)
    params=0
    flops=0
    infos=[]
    print(deploy_file)
    maxnamelen = 8

    for item in net.params.items():
        name, layer = item
        layer_type = net.layer_dict[name].type
        if layer_type in flop_layers:
            maxnamelen =len(name) if len(name) > maxnamelen else maxnamelen
            param = layer[0].count# + layer[1].count
            #bm = net.blobs[net.bottom_names[name][0]]
            bt = net.blobs[net.top_names[name][0]]
            flop = param*bt.width*bt.height
            if show_detail:
                info={}
                info['name']=name
                info['filter_shape']=layer[0].data.shape
                info['out_shape']=bt.data.shape
                info['params']=param
                info['flops']=flop
                infos.append(info)
            params += param
            flops += flop
    if show_detail:
        print('layer name'.ljust(maxnamelen+1), 'Filter Shape'.ljust(16),'Output Size'.ljust(16), 'Params'.ljust(8), 'Flops'.ljust(12),"Ratio")
        for info in infos:
            ratio = round(info['flops']*100.0/flops,3)
            print(info['name'].ljust(maxnamelen+1),str(info['filter_shape']).ljust(16),
            str(info['out_shape']).ljust(16),str(info['params']).ljust(8),str(info['flops']).ljust(12),str(ratio))
    print ('Layers num: ' + str(len(net.params.items())))
    print("Total number of parameters: ",params)
    print("Total number of FLOPs: ",flops)
    return params, flops

if __name__ == '__main__':
    deploy_file="deploy.prototxt"
    if len(sys.argv) > 1:
        deploy_file = sys.argv[1]
    get_flops(deploy_file)

输出

deploy.prototxt
layer name Filter Shape     Output Size      Params   Flops        Ratio
conv1     (96, 3, 11, 11)  (1, 96, 55, 55)  34848    105415200    14.552
conv2     (256, 48, 5, 5)  (1, 256, 27, 27) 307200   223948800    30.915
conv3     (384, 256, 3, 3) (1, 384, 13, 13) 884736   149520384    20.64
conv4     (384, 192, 3, 3) (1, 384, 13, 13) 663552   112140288    15.48
conv5     (256, 192, 3, 3) (1, 256, 13, 13) 442368   74760192     10.32
fc6       (4096, 9216)     (1, 4096)        37748736 37748736     5.211
fc7       (4096, 4096)     (1, 4096)        16777216 16777216     2.316
fc8       (1000, 4096)     (1, 1000)        4096000  4096000      0.565
Layers num: 8
Total number of parameters:  60954656
Total number of FLOPs:  724406816

参考:

CNN中parameters和FLOPs计算

convnet-burden

深度学习中GPU和显存分析

### 计算深度学习模型参数数量 对于卷积神经网络(CNN),参数主要包括卷积核权重其他需要学习的权值。具体来说: - 卷积层中的每个滤波器(即卷积核)都有自己的权重矩阵,以及偏置项。 - 对于全连接层而言,则由输入节点到输出节点之间的连接权重构成。 以AlexNet的第一个卷积层(CONV1)为例,假设该层有96个大小为\(11 \times 11\)且通道数为3的过滤器,并带有bias,则CONV1的总参数量可表示为\[ (11\times11\times3+1)\times96=34944\]这里额外加上了1是因为每一个filter还有一个对应的bias term[^1]。 ### 浮点运算次数(FLOPs) FLOPs代表完成一次正向传播过程中涉及的所有浮点操作的数量。它通常用来评估算法效率硬件需求。针对特定类型的层,比如卷积层,可以按照如下方式估算: 给定一个尺寸为\(H_i\times W_i\)的特征图经过具有\(K_h\times K_w\)感受野、步幅stride s padding p 的卷积处理后得到的新特征图为 \(H_o\times W_o\) ,那么单次卷积操作产生的FLOP数目大约等于\[2\times C_{in}\times C_{out} \times H_k \times W_k \times H_o \times W_o\] 其中因子2来源于每次乘法都会伴随至少一次加法;而当涉及到批量归一化(Batch Normalization)等其他组件时还需进一步增加相应的计算开销[^2]。 回到之前提到的例子,在不考虑激活函数等因素的情况下,如果输入图像分辨率为\(227\times227\)像素,通过上述公式可知CONV1层总的FLOPs约为\[34944\times55\times55=108249600\]。 需要注意的是实际应用中往往还会考虑到更多细节因素来精确统计整个网络架构下的总体FLOPs数值。 ```python def calculate_flops(input_size, kernel_size, output_channels, stride=1, padding=0): """ Calculate the number of floating point operations for a convolutional layer. Args: input_size (tuple): Input feature map size as tuple (height, width). kernel_size (int or tuple): Kernel dimensions either single value or pair (height,width). output_channels (int): Number of filters/output channels. stride (int or tuple, optional): Stride length(s). Defaults to 1. padding (int or str, optional): Padding applied before convolution ('same', 'valid' or int values). Default is no padding. Returns: float: Estimated FLOPs count per forward pass through this conv layer. """ if isinstance(kernel_size,int): kh,kw = kernel_size,kernel_size elif isinstance(kernel_size,(list,tuple)): kh,kw = kernel_size hi,wi=input_size ho=int((hi-kh+(2*padding))/stride)+1 wo=int((wi-kw+(2*padding))/stride)+1 flops_per_conv=(kh*kw)*output_channels*(ho*wo)*2 # Multiply by two because each multiply has an associated add operation return flops_per_conv print(f"FLOPs for Conv Layer with given specs:{calculate_flops((227,227),(11,11),96)}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值