• 全连接层及其注意力attention的参数量和计算量分析


    🎀个人主页: https://zhangxiaoshu.blog.csdn.net
    📢欢迎大家:关注🔍+点赞👍+评论📝+收藏⭐️,如有错误敬请指正!
    💕未来很长,值得我们全力奔赴更美好的生活!

    前言

    上一篇文章中讲述了常见的卷积算子参数量和计算量的计算方法,主要包括普通卷积深度可分离卷积分组卷积,以及对自动计算模型参数量和计算量的工具库ptflops进行简单介绍。在用于计算机视觉任务的深度神经网络模型中,还有两种结构被经常使用,即liner层和使用Multi-Head Attention机制的Transformer,本篇文章对linerMulti-Head Attention以及其他常见结构的参数量和计算量进行分析,以及对自动计算模型参数量和计算量的工具库ptflops进行简单介绍。

    有关卷积算子参数量和计算量的分析,可以参考之前写的这篇文章:深度神经网络算子参数量和计算量分析—卷积篇



    1. Liner

    在这里插入图片描述
    Liner层也叫神经网络的全连接层(Fully Connected Layer),也称为密集层(Dense Layer),是神经网络中最常见的一种层类型之一。

    如上图所示,全连接层的每个神经元都与前一层的所有神经元相连接,每个连接都有一个权重。这意味着全连接层中的每个神经元都接收来自前一层所有神经元的输入,并通过权重进行加权求和。然后,通过激活函数对这个加权和进行非线性变换,得到该神经元的输出。

    全连接层的作用是将输入数据进行高维特征表示和转换。它可以学习输入数据的复杂非线性关系,并将这些特征传递给后续的层进行进一步处理。全连接层通常用于神经网络的中间层,可以有多个全连接层堆叠在一起,以构建更深层次的网络结构。

    我们假设liner层的输入神经元个数 I I I输出神经元个数 O O O

    (1) Params

    对于liner层的参数量计算,从输出神经元的角度来看,每个输出神经元都有 I I I个输入神经元和它相连接,也就是说每一个输出神经元共有 I I I个权重,之后每一个输出神经元有一个输出,需要加一个偏置。故,对于每一个输出神经元来说,其参数量为:

    P a r a m s 每一个输出神经元 = I + 1 Params_{每一个输出神经元}=I + 1 Params每一个输出神经元=I+1

    共有 O O O个输出神经元,故liner层的总参数量

    P a r a m s = ( I + 1 ) × O   I × O + O Params=(I + 1)\times O \\\ I \times O + O Params=(I+1)×O I×O+O

    (2) FLOPs

    对于liner层的计算量,我们同样从输出神经元的角度来看,每一个输出神经元都与前一层的所有神经元相连接,每个连接都有一个权重。即每个神经元都接收来自前一层所有神经元的输入,并通过权重进行加权求和后添加偏置后输出,因此,每一个输出神经元的计算量为

    F L O P s 每一个输出神经元 = I + ( I − 1 ) + 1 FLOPs_{每一个输出神经元}=I + (I - 1) + 1 FLOPs每一个输出神经元=I+(I1)+1

    其中, I I I是每一个输出神经元和来自前一层所有神经元的输入进行加权求和所需要的乘法次数, I − 1 I-1 I1是每一个输出神经元和来自前一层所有神经元的输入进行加权求和所需要的加法次数, + 1 +1 +1是加偏置运算的加法次数(每一个输出特征像素需要一次加偏置操作)。

    共有 O O O个输出神经元,故liner层的总计算量为

    F L O P s = [ I + ( I − 1 ) + 1 ] × O   ( 2 × I ) × O FLOPs=[I + (I - 1) + 1] \times O \\\ (2 \times I)\times O FLOPs=[I+(I1)+1]×O (2×I)×O

    2. Multi-Head Attention

    在这里插入图片描述
    多头注意力机制(Multi-head Attention)是一种在自注意力机制(Self-Attention)基础上的扩展,常用于序列建模任务,如机器翻译和语言生成。如今在计算机视觉任务上也表现优异,多头注意力机制通过并行地学习多个注意力头,可以同时关注不同的语义信息,从而提高模型的表示能力和泛化能力。Multi-Head Attention流程如上图所示,有关Multi-Head Attention的相关原理较为繁琐,这里不做详细介绍。

    (1) Params

    多头注意力机制的参数量主要取决于注意力头的数量、输入序列的维度和每个注意力头的维度。

    假设输入序列的维度 d m o d e l d_{model} dmodel注意力头的数量 h h h每个注意力头的维度 d h e a d d_{head} dhead。在多头注意力机制中,每个注意力头都有自己的查询、键和值的权重矩阵,以及最后的线性变换权重矩阵。

    查询、键和值的权重矩阵:每个注意力头都有一个查询权重矩阵 W q W_q Wq)、一个键权重矩阵 W k W_k Wk)和一个值权重矩阵 W v W_v Wv)。这些权重矩阵的形状分别为 ( d m o d e l d_{model} dmodel, d h e a d d_{head} dhead),因此每个注意力头的参数量为:

    P a r a m s 每个注意力头 = 3 × d m o d e l × d h e a d Params_{每个注意力头}=3 \times d_{model}\times d_{head} Params每个注意力头=3×dmodel×dhead

    共有 h h h个头,故,所有的注意力头的参数量为:

    P a r a m s 每个注意力头 = 3 × d m o d e l × d h e a d × h Params_{每个注意力头}=3 \times d_{model}\times d_{head} \times h Params每个注意力头=3×dmodel×dhead×h

    最后的线性变换权重矩阵:在多头注意力机制中,将多个注意力头的输出进行拼接或加权求和后,需要进行最后的线性变换。这个线性变换的权重矩阵的形状为 ( h × d h e a d h \times d_{head} h×dhead, d m o d e l d_{model} dmodel),因此最后的线性变换的参数量为

    P a r a m s 线性变化 = h × d m o d e l × d h e a d Params_{线性变化}=h \times d_{model}\times d_{head} Params线性变化=h×dmodel×dhead

    综上所述,多头注意力机制的总参数量为:

    P a r a m s 每个注意力头 = 3 × d m o d e l × d h e a d × h + h × d m o d e l × d h e a d Params_{每个注意力头}=3 \times d_{model}\times d_{head} \times h + h \times d_{model}\times d_{head} Params每个注意力头=3×dmodel×dhead×h+h×dmodel×dhead

    多头注意力机制的参数量相对较大,特别是当注意力头的数量和维度较大时。为了减少参数量,可以通过减小注意力头的数量、降低输入序列的维度或使用一些参数共享的技术来进行优化。

    (2) FLOPs

    多头注意力机制的计算量主要取决于注意力头的数量输入序列的长度

    同样假设输入序列的维度为 d m o d e l d_{model} dmodel,注意力头的数量为 h h h,每个注意力头的维度为 d h e a d d_{head} dhead

    在多头注意力机制中,每个注意力头都需要进行注意力计算和加权求和操作。注意力计算的复杂度为:

    O ( d m o d e l 2 × d h e a d ) O(d_{model}^2 \times d_{head} ) O(dmodel2×dhead)

    其中 d m o d e l 2 d_{model}^2 dmodel2是由于需要计算每个位置与其他位置的注意力权重, d h e a d d_{head} dhead是每个位置的表示维度。

    因此,对于 h h h个注意力头,注意力计算的总复杂度为:

    O ( d m o d e l 2 × d h e a d × h ) O(d_{model}^2 \times d_{head} \times h) O(dmodel2×dhead×h)

    在加权求和操作中,需要将注意力权重与线性变换后的表示进行加权求和。线性变换的复杂度为:

    O ( d m o d e l × d h e a d × h ) O(d_{model} \times d_{head} \times h) O(dmodel×dhead×h)

    其中 h h h是注意力头的数量, d m o d e l d_{model} dmodel是输入序列的长度, d h e a d d_{head} dhead是每个位置的表示维度。

    综上所述,多头注意力机制的总计算量为:

    O ( d m o d e l 2 × d h e a d × h ) + O ( d m o d e l × d h e a d × h ) O(d_{model}^2 \times d_{head} \times h)+O(d_{model} \times d_{head} \times h) O(dmodel2×dhead×h)+O(dmodel×dhead×h)

    3. 其他常见结构分析

    (1) 激活层

    激活层的参数量和计算量取决于所使用的激活函数类型输入的维度

    对于常见的激活函数(如ReLU、Sigmoid、Tanh等),它们通常没有可训练的参数,因此参数量为零,即

    P a r a m s 激活层 = 0 Params_{激活层}=0 Params激活层=0

    而计算量则取决于输入的维度激活函数的计算复杂度

    以ReLU激活函数为例,它的计算复杂度与输入的维度成正比。对于每个输入元素,ReLU函数只需进行一次比较和一次乘法运算。因此,对于输入维度为 n n n的激活层,ReLU激活函数的计算量

    O ( n ) O(n) O(n)

    对于其他激活函数,如Sigmoid和Tanh,它们的计算复杂度也与输入的维度成正比,但相对于ReLU函数而言,它们的计算量会更大一些。激活层的参数量和计算量通常较小,相对于模型中的其他层(如卷积层或全连接层)来说,它们的参数量贡献较小。

    (2) 池化层

    池化层的参数量和计算量取决于池化操作的类型池化窗口的大小输入的维度

    对于常见的池化操作(如最大池化和平均池化),它们通常没有可训练的参数,因此参数量为零,即

    P a r a m s 池化层 = 0 Params_{池化层}=0 Params池化层=0

    而计算量则取决于输入的维度池化窗口的大小池化操作的计算复杂度

    以最大池化为例,它的计算复杂度与输入的维度和池化窗口的大小成正比。对于每个池化窗口,最大池化操作只需进行一次最大值的比较。因此,对于输入维度为 n n n的池化层和池化窗口大小为 k k k最大池化操作,计算量为:

    O ( n × k ) O(n\times k) O(n×k)

    对于平均池化,它的计算复杂度与最大池化类似,也与输入的维度和池化窗口的大小成正比。对于每个池化窗口,平均池化操作只需进行一次求和和除法运算。

    因此,对于输入维度为 n 的池化层和池化窗口大小为 k 的平均池化操作,计算量为。

    O ( n × k ) O(n\times k) O(n×k)

    同样的,池化层的参数量和计算量通常较小,相对于模型中的其他层来说,它们的参数量贡献较小。
    归一化层(Normalization Layer)的参数量和计算量取决于所使用的归一化方法和输入的维度。

    (3) 归一化层

    归一化层(Normalization Layer)的参数量和计算量取决于所使用的归一化方法和输入的维度。

    批归一化(Batch Normalization)层归一化(Layer Normalization)是常用的归一化方法,用于加速深度神经网络的训练和提高模型的泛化能力。

    批归一化是在每个批次的数据上进行归一化操作,它的主要思想是将每个特征通道的输入进行均值和方差的归一化,使得输入的分布更加稳定。

    具体而言,批归一化通过以下步骤来实现:

    1. 对于每个批次的输入数据,计算该批次数据在每个特征通道上的均值和方差。
    2. 使用这些均值和方差来对该批次的数据进行归一化,即将每个特征通道的输入减去均值并除以方差。
    3. 引入可训练的缩放因子和偏移因子,用于恢复归一化后的数据的表示能力。

    故,对于批归一化,每个特征通道的输入都有一个缩放因子和一个偏移因子,总的参数量为:

    P a r a m s 批归一化 = 2 × 特征通道维数 Params_{批归一化}=2 \times 特征通道维数 Params批归一化=2×特征通道维数

    层归一化是在每个样本的特征维度上进行归一化操作,它的主要思想是将每个样本的特征维度进行均值和方差的归一化,使得输入的分布更加稳定。

    具体而言,层归一化通过以下步骤来实现:

    1. 对于每个样本的特征维度,计算该样本在所有特征维度上的均值和方差。
    2. 使用这些均值和方差来对该样本的特征维度进行归一化,即将每个特征维度的输入减去均值并除以方差。
    3. 引入可训练的缩放因子和偏移因子,用于恢复归一化后的数据的表示能力。

    故,对于批归一化,每个样本的特征维度都有一个缩放因子和一个偏移因子,总的参数量为:

    P a r a m s 层归一化 = 2 × 样本数 Params_{层归一化}=2 \times 样本数 Params层归一化=2×样本数

    4. ptflops

    ptflops 是一个自动计算模型参数量和计算量的库,可以通过pip/conda直接下载,即

    pip install ptflops
    
    • 1

    速度过慢时可以使用-i参数指定源,即

    pip install ptflops -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    • 1

    使用举例:

    import torch
    from torchvision.models import resnet18
    from ptflops import get_model_complexity_info
      
    model = resnet50()
    macs, params = get_model_complexity_info(model, (3, 224, 224), as_strings=True,print_per_layer_stat=True, verbose=True)
                                               
    print("MACs=", str(macs / 1e9) + '{}'.format("G"))
    print("MACs=", str(macs / 1e6) + '{}'.format("M"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    虽然它可以自己计算模型的参数量和计算量,但是对一些自定义的层或算子不支持,并且不支持带有批量的计算。

    总结

    以上就是深度神经网络模型中常见结构的计算量和参数量分析,以及自动计算模型参数量和计算量的工具库ptflops的简单使用。希望对你能有帮助,如有问题,欢迎指出🤗

  • 相关阅读:
    经典卷积神经网络模型 - ResNet
    栈溢出漏洞
    Java将获取的参数,图片以及pdf文件放入到word文档指定位置
    uniapp路由跳转的方式
    LayUI之CRUD
    odoo 开发入门教程系列-一些用户界面
    【Wayland】QtWayland框架分析
    Informer论文思维导图
    HIve数仓新零售项目DWS层的构建(Full join)模型
    基于JSP动漫论坛的设计与实现
  • 原文地址:https://blog.csdn.net/qq_46009046/article/details/134417286