欢迎光临
我们一直在努力

图解各种卷积层(一般卷积、逐深度卷积、逐点卷积、空洞卷积、不对称卷积、深度可分离卷积、分组卷积)

图解各种卷积层(一般卷积、逐深度卷积、逐点卷积、空洞卷积、不对称卷积、深度可分离卷积、分组卷积)

  • 回顾全连接网络
  • 1 一般卷积
    • 1.1 什么是卷积
    • 1.2 一般卷积的运算过程
    • 1.3 一般卷积的参数量与计算量
    • 1.4 一般卷积的局限
  • 2 逐深度卷积
    • 2.1 什么是逐深度卷积
    • 2.2 逐深度卷积的运算过程
    • 2.3 逐深度卷积的参数量与计算量
    • 2.4 逐深度卷积的局限
  • 3 逐点卷积
    • 3.1 什么是逐点卷积
    • 3.2 逐点卷积的运算过程
    • 3.3 逐点卷积的参数量与计算量
    • 3.4 逐点卷积的局限
  • 4深度可分离卷积
    • 4.1 什么是深度可分离卷积
    • 4.2 深度可分离卷积的运算过程
    • 4.3 深度可分离卷积的参数量与计算量
    • 4.4 深度可分离卷积的局限
  • 5空洞卷积
    • 5.1 什么是空洞卷积
    • 5.2 空洞卷积的运算过程
    • 5.3 空洞卷积的参数量与计算量
    • 5.4 空洞卷积的局限
  • 6不对称卷积
    • 6.1 什么是不对称卷积
    • 6.2 不对称卷积的运算过程
    • 6.3 不对称卷积的参数量与计算量
    • 6.4 不对称卷积的局限
  • 7分组卷积
    • 7.1 什么是分组卷积
    • 7.2 分组卷积的运算过程
    • 7.3 分组卷积的参数量与计算量
    • 7.4 分组卷积的局限

本篇讲解全连接神经网络和卷积神经网络之间的关系。 神经网络入门请参考之前的博文:神经网络一篇入门

回顾全连接网络

全连接网络是现代神经网络的最基本形式,其特征是由全连接层(以及激活函数)前后相接组成,其结构如下图所示: 全连接神经网络结构 可见,全连接层中,每一个神经元都会与其输入相连,在数学上表达为一个权重与输入相乘

y

j

=

w

i

j

x

i

y_j=w_{ij}·x_i

yj=wijxi,从整体来看就是一个矩阵乘法实现全连接:

y

=

w

x

+

b

y=w·x+b

y=wx+b。这就是全连接层的数学表达形式,它巧妙的利用了加权求和来表表示神经元与输入数据之间的“连接”关系。 但是显然,这种连接方式存在一些局限性。 首先,全连接的结构注定要求输入是一个一维向量,假设原始数据是2维甚至以上的数据(例如图像、音频、视频等),那么数据之间的空间关系就会被打破,这些信息就被“损失”掉了,对于后续的任务是不利的。 其次,全连接的计算量是比较大的。假设输入数据元素个数是m,输出数据元素个数是n,那么所需要要的权重数量(也就是矩阵的宽高)为n*m,当n和m都很大的时候,要就需要大量的存储空间,并且随之带来的计算量也会急剧上升。 为了改进上述缺点,卷积神经网络被提出。 下面,以2D卷积为主线,图解各种卷积,并给出Pytorch中的实现。

1 一般卷积

卷积神经网络(Convolutional Neural Network, CNN)的核心思想是局部连接与权值共享,而一般卷积(Standard Convolution)正是实现这一思想的基础操作。

1.1 什么是卷积

在数学上,卷积是一种对两个函数进行运算的操作。但在深度学习中,我们更关心它在图像处理上的直观含义:用一个小的滤波器(Filter / Kernel)在输入特征图上滑动,逐位置做加权求和,从而提取局部特征。

假设输入是一张单通道图像

X

X

X,尺寸为

H

×

W

H \\times W

H×W,卷积核

K

K

K 的尺寸为

k

×

k

k \\times k

k×k,则输出特征图

Y

Y

Y 上位置

(

i

,

j

)

(i,j)

(i,j) 的值可以表示为:

Y

(

i

,

j

)

=

m

=

0

k

1

n

=

0

k

1

X

(

i

+

m

,

j

+

n

)

K

(

m

,

n

)

+

b

Y(i,j) = \\sum_{m=0}^{k-1} \\sum_{n=0}^{k-1} X(i+m, j+n) \\cdot K(m,n) + b

Y(i,j)=m=0k1n=0k1X(i+m,j+n)K(m,n)+b

其中

b

b

b 为偏置项。可以看到,输出上的每一个点,只与输入上对应位置附近的一个

k

×

k

k \\times k

k×k 局部区域有关,这就是**局部感受野(Receptive Field)**的由来。

1.2 一般卷积的运算过程

一般卷积的完整过程可以拆解为以下几步:

  • 确定卷积核:设定卷积核尺寸(如

    3

    ×

    3

    3 \\times 3

    3×3

    5

    ×

    5

    5 \\times 5

    5×5)、步长(Stride)和填充(Padding)。

  • 滑动窗口:卷积核从输入左上角开始,按步长在输入上从左到右、从上到下滑动。
  • 加权求和:每滑动到一个位置,将卷积核与对应局部区域逐元素相乘后求和,再加上偏置,得到输出特征图上的一个值。
  • 多通道扩展:当输入有

    C

    i

    n

    C_{in}

    Cin 个通道时,每个通道使用一个独立的卷积核,将所有通道的结果相加,得到输出特征图的一个通道。

  • 下面是一般卷积的示意图:

    #mermaid-svg-aFke0wfNWRl7rgT2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aFke0wfNWRl7rgT2 .error-icon{fill:#552222;}#mermaid-svg-aFke0wfNWRl7rgT2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aFke0wfNWRl7rgT2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aFke0wfNWRl7rgT2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aFke0wfNWRl7rgT2 .marker.cross{stroke:#333333;}#mermaid-svg-aFke0wfNWRl7rgT2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aFke0wfNWRl7rgT2 p{margin:0;}#mermaid-svg-aFke0wfNWRl7rgT2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster-label text{fill:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster-label span{color:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster-label span p{background-color:transparent;}#mermaid-svg-aFke0wfNWRl7rgT2 .label text,#mermaid-svg-aFke0wfNWRl7rgT2 span{fill:#333;color:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 .node rect,#mermaid-svg-aFke0wfNWRl7rgT2 .node circle,#mermaid-svg-aFke0wfNWRl7rgT2 .node ellipse,#mermaid-svg-aFke0wfNWRl7rgT2 .node polygon,#mermaid-svg-aFke0wfNWRl7rgT2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aFke0wfNWRl7rgT2 .rough-node .label text,#mermaid-svg-aFke0wfNWRl7rgT2 .node .label text,#mermaid-svg-aFke0wfNWRl7rgT2 .image-shape .label,#mermaid-svg-aFke0wfNWRl7rgT2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-aFke0wfNWRl7rgT2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aFke0wfNWRl7rgT2 .rough-node .label,#mermaid-svg-aFke0wfNWRl7rgT2 .node .label,#mermaid-svg-aFke0wfNWRl7rgT2 .image-shape .label,#mermaid-svg-aFke0wfNWRl7rgT2 .icon-shape .label{text-align:center;}#mermaid-svg-aFke0wfNWRl7rgT2 .node.clickable{cursor:pointer;}#mermaid-svg-aFke0wfNWRl7rgT2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aFke0wfNWRl7rgT2 .arrowheadPath{fill:#333333;}#mermaid-svg-aFke0wfNWRl7rgT2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aFke0wfNWRl7rgT2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aFke0wfNWRl7rgT2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFke0wfNWRl7rgT2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aFke0wfNWRl7rgT2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFke0wfNWRl7rgT2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster text{fill:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 .cluster span{color:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aFke0wfNWRl7rgT2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aFke0wfNWRl7rgT2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-aFke0wfNWRl7rgT2 .icon-shape,#mermaid-svg-aFke0wfNWRl7rgT2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aFke0wfNWRl7rgT2 .icon-shape p,#mermaid-svg-aFke0wfNWRl7rgT2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aFke0wfNWRl7rgT2 .icon-shape .label rect,#mermaid-svg-aFke0wfNWRl7rgT2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aFke0wfNWRl7rgT2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aFke0wfNWRl7rgT2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aFke0wfNWRl7rgT2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    输入特征图 H×W×C_in

    卷积核 K×K×C_in

    滑动窗口加权求和

    输出特征图 H'×W'×C_out

    一般卷积示意图 我们可以注意到,实际上的一般卷积的卷积对象和卷积核本身是一个3维结构,有w、h和c三个维度,这是刚刚接触卷积网络的同学很容易误解的点。

    结论: 1、卷积输出的通道数:在一般卷积中,卷积核的通道数(c维度)必须等于输入数据的通道数,例如,输入是3通道彩色图像,那卷积核也必须是3通道的,卷积核的个数等于输出通道数。例如,你使用了16个卷积核,那么输出通道数就是16。 2、卷积输出的尺寸N,与卷积核大小K,步幅S以及填充P相关,公式如下:

    N

    =

    W

    F

    +

    2

    P

    S

    +

    1

    N=\\frac{W-F+2P}{S}+1

    N=SWF+2P+1 上式结果向下取整。 一般卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #测试不同卷积参数下的输出尺寸和通道数
    conv_layer1=Conv2d(in_channels=3,out_channels=16,kernel_size=3,stride=1,padding=0)
    conv_layer2=Conv2d(in_channels=3,out_channels=32,kernel_size=3,stride=1,padding=1)
    conv_layer3=Conv2d(in_channels=3,out_channels=16,kernel_size=3,stride=2,padding=1)
    conv_layer4=Conv2d(in_channels=3,out_channels=16,kernel_size=5,stride=1,padding=0)
    conv_layer5=Conv2d(in_channels=3,out_channels=16,kernel_size=5,stride=1,padding=2)
    y1=conv_layer1(image)
    y2=conv_layer2(image)
    y3=conv_layer3(image)
    y4=conv_layer4(image)
    y5=conv_layer5(image)
    y=[y1,y2,y3,y4,y5]
    for yy in y:
    print(yy.shape)
    #输出
    '''
    torch.Size([1, 16, 254, 254])
    torch.Size([1, 32, 256, 256])
    torch.Size([1, 16, 128, 128])
    torch.Size([1, 16, 252, 252])
    torch.Size([1, 16, 256, 256])
    '''

    大家可以使用公式验证一下输入与输出形状的关系。注意,当padding=0时,因为图像边缘的像素无法作为卷积中心,因此边缘的一圈像素在卷积后会被丢弃,输出变小。 例如,当输入为(256,256,3)时,经过3×3卷积,padding=0,stride=1,输出尺寸为254×254,因为图像上下左右各有一圈像素被舍弃。如果卷积核为5×5的,那么输出上下左右会有两圈像素被舍弃。 stride=2时,相当于输入尺寸2倍下采样,但是要注意配合合适的padding值。

    1.3 一般卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,则:

    • 参数量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      k \\times k \\times C_{in} \\times C_{out}

      k×k×Cin×Cout

    • 计算量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      k \\times k \\times C_{in} \\times C_{out} \\times H' \\times W'

      k×k×Cin×Cout×H×W

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。相比全连接层,一般卷积通过局部连接大幅减少了参数量,通过权值共享(同一个卷积核在整张图上滑动)进一步降低了存储和计算开销,这也是卷积神经网络能够高效处理图像等二维数据的关键原因。

    1.4 一般卷积的局限

    尽管一般卷积已经比全连接高效很多,但它仍然存在一些不足:

    • 当输入通道数

      C

      i

      n

      C_{in}

      Cin 和输出通道数

      C

      o

      u

      t

      C_{out}

      Cout 都较大时,参数量依然可观;

    • 卷积核只能覆盖局部区域,对远距离依赖的建模能力有限;
    • 标准卷积对所有通道一视同仁,无法区分通道间的相关性。

    正是为了应对这些局限,后续才发展出了逐深度卷积(Depthwise Convolution)、逐点卷积(Pointwise Convolution)、空洞卷积(Dilated Convolution)、不对称卷积(Asymmetric Convolution)、深度可分离卷积(Depthwise Separable Convolution)以及分组卷积(Grouped Convolution) 等变体,这些将在后续章节中逐一讲解。

    2 逐深度卷积

    逐深度卷积(Depthwise Convolution)是一般卷积的一种特殊形式,它的核心思想是对每个输入通道分别进行独立的卷积运算,即每个通道使用一个单独的卷积核,通道之间互不混合。

    2.1 什么是逐深度卷积

    在一般卷积中,卷积核的通道数必须等于输入通道数,卷积核会在所有通道上同时滑动并求和,从而将通道信息混合在一起。而逐深度卷积则完全不同:它把输入特征图的每个通道单独拿出来,用一个独立的

    k

    ×

    k

    k \\times k

    k×k 卷积核去卷积,得到对应通道的输出,通道之间不进行求和混合。

    假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,则逐深度卷积的输出特征图

    Y

    Y

    Y 上第

    c

    c

    c 个通道、位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    c

    (

    i

    ,

    j

    )

    =

    m

    =

    0

    k

    1

    n

    =

    0

    k

    1

    X

    c

    (

    i

    +

    m

    ,

    j

    +

    n

    )

    K

    c

    (

    m

    ,

    n

    )

    +

    b

    c

    Y_c(i,j) = \\sum_{m=0}^{k-1} \\sum_{n=0}^{k-1} X_c(i+m, j+n) \\cdot K_c(m,n) + b_c

    Yc(i,j)=m=0k1n=0k1Xc(i+m,j+n)Kc(m,n)+bc

    其中

    X

    c

    X_c

    Xc 为输入的第

    c

    c

    c 个通道,

    K

    c

    K_c

    Kc 为第

    c

    c

    c 个通道对应的卷积核,

    b

    c

    b_c

    bc 为第

    c

    c

    c 个通道的偏置项。可以看到,输出通道数等于输入通道数,且每个通道只与自己的卷积核做运算,通道之间互不干扰。逐深度卷积的示意图如下: 逐深度卷积示意图 可见,逐深度卷积的特点就是不会改变输入通道数,也就是输入通道数是多少,输出通道数就是多少。

    2.2 逐深度卷积的运算过程

    逐深度卷积的完整过程可以拆解为以下几步:

  • 确定卷积核:设定卷积核尺寸(如

    3

    ×

    3

    3 \\times 3

    3×3

    5

    ×

    5

    5 \\times 5

    5×5)、步长(Stride)和填充(Padding),卷积核个数等于输入通道数。

  • 逐通道滑动:对输入特征图的每一个通道,用对应的卷积核在该通道上从左到右、从上到下滑动。
  • 加权求和:每滑动到一个位置,将卷积核与该通道对应局部区域逐元素相乘后求和,再加上偏置,得到该通道输出特征图上的一个值。
  • 拼接输出:所有通道独立卷积完成后,将各通道的输出按原顺序拼接,得到最终的输出特征图。
  • 下面是一个直观的对比示意图:

    #mermaid-svg-gFmNgp3qrryVzB5n{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gFmNgp3qrryVzB5n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gFmNgp3qrryVzB5n .error-icon{fill:#552222;}#mermaid-svg-gFmNgp3qrryVzB5n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gFmNgp3qrryVzB5n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gFmNgp3qrryVzB5n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gFmNgp3qrryVzB5n .marker.cross{stroke:#333333;}#mermaid-svg-gFmNgp3qrryVzB5n svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gFmNgp3qrryVzB5n p{margin:0;}#mermaid-svg-gFmNgp3qrryVzB5n .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-gFmNgp3qrryVzB5n .cluster-label text{fill:#333;}#mermaid-svg-gFmNgp3qrryVzB5n .cluster-label span{color:#333;}#mermaid-svg-gFmNgp3qrryVzB5n .cluster-label span p{background-color:transparent;}#mermaid-svg-gFmNgp3qrryVzB5n .label text,#mermaid-svg-gFmNgp3qrryVzB5n span{fill:#333;color:#333;}#mermaid-svg-gFmNgp3qrryVzB5n .node rect,#mermaid-svg-gFmNgp3qrryVzB5n .node circle,#mermaid-svg-gFmNgp3qrryVzB5n .node ellipse,#mermaid-svg-gFmNgp3qrryVzB5n .node polygon,#mermaid-svg-gFmNgp3qrryVzB5n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gFmNgp3qrryVzB5n .rough-node .label text,#mermaid-svg-gFmNgp3qrryVzB5n .node .label text,#mermaid-svg-gFmNgp3qrryVzB5n .image-shape .label,#mermaid-svg-gFmNgp3qrryVzB5n .icon-shape .label{text-anchor:middle;}#mermaid-svg-gFmNgp3qrryVzB5n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gFmNgp3qrryVzB5n .rough-node .label,#mermaid-svg-gFmNgp3qrryVzB5n .node .label,#mermaid-svg-gFmNgp3qrryVzB5n .image-shape .label,#mermaid-svg-gFmNgp3qrryVzB5n .icon-shape .label{text-align:center;}#mermaid-svg-gFmNgp3qrryVzB5n .node.clickable{cursor:pointer;}#mermaid-svg-gFmNgp3qrryVzB5n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gFmNgp3qrryVzB5n .arrowheadPath{fill:#333333;}#mermaid-svg-gFmNgp3qrryVzB5n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gFmNgp3qrryVzB5n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gFmNgp3qrryVzB5n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gFmNgp3qrryVzB5n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gFmNgp3qrryVzB5n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gFmNgp3qrryVzB5n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gFmNgp3qrryVzB5n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gFmNgp3qrryVzB5n .cluster text{fill:#333;}#mermaid-svg-gFmNgp3qrryVzB5n .cluster span{color:#333;}#mermaid-svg-gFmNgp3qrryVzB5n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gFmNgp3qrryVzB5n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gFmNgp3qrryVzB5n rect.text{fill:none;stroke-width:0;}#mermaid-svg-gFmNgp3qrryVzB5n .icon-shape,#mermaid-svg-gFmNgp3qrryVzB5n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gFmNgp3qrryVzB5n .icon-shape p,#mermaid-svg-gFmNgp3qrryVzB5n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gFmNgp3qrryVzB5n .icon-shape .label rect,#mermaid-svg-gFmNgp3qrryVzB5n .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gFmNgp3qrryVzB5n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gFmNgp3qrryVzB5n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gFmNgp3qrryVzB5n :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    逐深度卷积

    输入 C_in 个通道

    每个通道独立卷积核 K×K×1

    通道间不混合

    输出 C_in 个通道

    一般卷积

    输入 C_in 个通道

    卷积核 K×K×C_in

    所有通道求和混合

    输出 C_out 个通道

    逐深度卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #测试不同卷积参数下的输出尺寸和通道数
    dw_conv1=Conv2d(in_channels=3,out_channels=3,kernel_size=3,stride=1,padding=0,groups=3)
    dw_conv2=Conv2d(in_channels=3,out_channels=18,kernel_size=5,stride=1,padding=2,groups=3)
    y1=dw_conv1(image)
    y2=dw_conv2(image)
    y=[y1,y2]
    for yy in y:
    print(yy.shape)
    #输出
    '''
    torch.Size([1, 3, 254, 254])
    torch.Size([1, 18, 256, 256])
    '''

    逐深度卷积同样适用Conv2d类进行构建,相较于一般卷积,多了一个参数groups,意思是将输入的通道分为多少组,每组内部分别进行一般卷积。当groups=输入通道数时,输入的每个通道都是一个组,相当于每个通道分配一个卷积核进行卷积,这样就实现了逐通道卷积。当输入通道数不等于输出通道数时,例如上面代码的dw_conv2,out_channels必须是通道数量的整数倍,相当于给每个通道分配一个以上的卷积核,例如,dw_conv2就是给每个通道分配了6个卷积核,所以一个通道变成了6通道输出,3个通道就会输出18个通道,但是内部计算还是按照逐深度卷积的定义来完成的。

    2.3 逐深度卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,则:

    • 参数量:

      k

      ×

      k

      ×

      C

      i

      n

      k \\times k \\times C_{in}

      k×k×Cin

    • 计算量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      H

      ×

      W

      k \\times k \\times C_{in} \\times H' \\times W'

      k×k×Cin×H×W

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。对比一般卷积的参数量

    k

    ×

    k

    ×

    C

    i

    n

    ×

    C

    o

    u

    t

    k \\times k \\times C_{in} \\times C_{out}

    k×k×Cin×Cout,逐深度卷积的参数量只有一般卷积的

    1

    /

    C

    o

    u

    t

    1/C_{out}

    1/Cout,计算量也大幅下降。这正是逐深度卷积的核心优势——用极小的参数量完成空间特征的提取。

    2.4 逐深度卷积的局限

    尽管逐深度卷积大幅降低了参数量和计算量,但它也存在明显的不足:

    • 通道间信息无法交互:由于每个通道独立卷积、互不混合,逐深度卷积无法利用通道之间的相关性信息;
    • 特征表达能力有限:单独使用逐深度卷积时,模型对特征的表达能力较弱,通常需要配合逐点卷积(Pointwise Convolution) 来混合通道信息,二者组合便构成了经典的深度可分离卷积(Depthwise Separable Convolution)。

    正是为了弥补逐深度卷积在通道交互上的不足,后续才发展出了逐点卷积以及深度可分离卷积,这些将在后续章节中详细讲解。

    3 逐点卷积

    逐点卷积(Pointwise Convolution)是一般卷积的一种特殊形式,它的核心思想是用

    1

    ×

    1

    1 \\times 1

    1×1 的卷积核在通道维度上进行加权求和,从而在保持空间尺寸不变的前提下,实现通道之间的信息交互与维度变换。

    3.1 什么是逐点卷积

    在一般卷积中,卷积核尺寸通常大于

    1

    1

    1(如

    3

    ×

    3

    3 \\times 3

    3×3

    5

    ×

    5

    5 \\times 5

    5×5),卷积核会在空间和通道两个维度上同时滑动并求和。而逐点卷积则完全不同:它的卷积核尺寸固定为

    1

    ×

    1

    1 \\times 1

    1×1,只在通道维度上做加权求和,不涉及空间邻域的聚合。

    假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,逐点卷积使用

    C

    o

    u

    t

    C_{out}

    Cout

    1

    ×

    1

    ×

    C

    i

    n

    1 \\times 1 \\times C_{in}

    1×1×Cin 的卷积核,则输出特征图

    Y

    Y

    Y 上第

    j

    j

    j 个通道、位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    j

    (

    i

    ,

    j

    )

    =

    c

    =

    0

    C

    i

    n

    1

    X

    c

    (

    i

    ,

    j

    )

    K

    j

    (

    c

    )

    +

    b

    j

    Y_j(i,j) = \\sum_{c=0}^{C_{in}-1} X_c(i,j) \\cdot K_j(c) + b_j

    Yj(i,j)=c=0Cin1Xc(i,j)Kj(c)+bj

    其中

    X

    c

    X_c

    Xc 为输入的第

    c

    c

    c 个通道,

    K

    j

    K_j

    Kj 为第

    j

    j

    j 个输出通道对应的

    1

    ×

    1

    ×

    C

    i

    n

    1 \\times 1 \\times C_{in}

    1×1×Cin 卷积核,

    b

    j

    b_j

    bj 为第

    j

    j

    j 个通道的偏置项。可以看到,输出特征图的空间尺寸与输入完全一致,而通道数由

    C

    i

    n

    C_{in}

    Cin 变为

    C

    o

    u

    t

    C_{out}

    Cout,这正是逐点卷积的核心作用——在通道维度上自由地升维或降维。 逐点卷积示意图

    3.2 逐点卷积的运算过程

    逐点卷积的完整过程可以拆解为以下几步:

  • 确定卷积核:设定卷积核尺寸固定为

    1

    ×

    1

    1 \\times 1

    1×1,卷积核个数等于输出通道数

    C

    o

    u

    t

    C_{out}

    Cout,每个卷积核的通道数等于输入通道数

    C

    i

    n

    C_{in}

    Cin

  • 逐位置滑动:卷积核在输入特征图的每一个空间位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 上滑动,由于卷积核尺寸为

    1

    ×

    1

    1 \\times 1

    1×1,滑动时不会跨越空间邻域。

  • 通道加权求和:在每个空间位置上,将

    C

    i

    n

    C_{in}

    Cin 个通道的值与卷积核对应通道的权重逐元素相乘后求和,再加上偏置,得到该位置在某个输出通道上的值。

  • 拼接输出:所有

    C

    o

    u

    t

    C_{out}

    Cout 个卷积核计算完成后,将各通道的输出按顺序拼接,得到尺寸为

    H

    ×

    W

    ×

    C

    o

    u

    t

    H \\times W \\times C_{out}

    H×W×Cout 的输出特征图。

  • 下面是一个直观的对比示意图:

    #mermaid-svg-F6NyHO90bqQkko3u{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-F6NyHO90bqQkko3u .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-F6NyHO90bqQkko3u .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-F6NyHO90bqQkko3u .error-icon{fill:#552222;}#mermaid-svg-F6NyHO90bqQkko3u .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-F6NyHO90bqQkko3u .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-F6NyHO90bqQkko3u .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-F6NyHO90bqQkko3u .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-F6NyHO90bqQkko3u .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-F6NyHO90bqQkko3u .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-F6NyHO90bqQkko3u .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-F6NyHO90bqQkko3u .marker{fill:#333333;stroke:#333333;}#mermaid-svg-F6NyHO90bqQkko3u .marker.cross{stroke:#333333;}#mermaid-svg-F6NyHO90bqQkko3u svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-F6NyHO90bqQkko3u p{margin:0;}#mermaid-svg-F6NyHO90bqQkko3u .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-F6NyHO90bqQkko3u .cluster-label text{fill:#333;}#mermaid-svg-F6NyHO90bqQkko3u .cluster-label span{color:#333;}#mermaid-svg-F6NyHO90bqQkko3u .cluster-label span p{background-color:transparent;}#mermaid-svg-F6NyHO90bqQkko3u .label text,#mermaid-svg-F6NyHO90bqQkko3u span{fill:#333;color:#333;}#mermaid-svg-F6NyHO90bqQkko3u .node rect,#mermaid-svg-F6NyHO90bqQkko3u .node circle,#mermaid-svg-F6NyHO90bqQkko3u .node ellipse,#mermaid-svg-F6NyHO90bqQkko3u .node polygon,#mermaid-svg-F6NyHO90bqQkko3u .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-F6NyHO90bqQkko3u .rough-node .label text,#mermaid-svg-F6NyHO90bqQkko3u .node .label text,#mermaid-svg-F6NyHO90bqQkko3u .image-shape .label,#mermaid-svg-F6NyHO90bqQkko3u .icon-shape .label{text-anchor:middle;}#mermaid-svg-F6NyHO90bqQkko3u .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-F6NyHO90bqQkko3u .rough-node .label,#mermaid-svg-F6NyHO90bqQkko3u .node .label,#mermaid-svg-F6NyHO90bqQkko3u .image-shape .label,#mermaid-svg-F6NyHO90bqQkko3u .icon-shape .label{text-align:center;}#mermaid-svg-F6NyHO90bqQkko3u .node.clickable{cursor:pointer;}#mermaid-svg-F6NyHO90bqQkko3u .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-F6NyHO90bqQkko3u .arrowheadPath{fill:#333333;}#mermaid-svg-F6NyHO90bqQkko3u .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-F6NyHO90bqQkko3u .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-F6NyHO90bqQkko3u .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F6NyHO90bqQkko3u .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-F6NyHO90bqQkko3u .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F6NyHO90bqQkko3u .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-F6NyHO90bqQkko3u .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-F6NyHO90bqQkko3u .cluster text{fill:#333;}#mermaid-svg-F6NyHO90bqQkko3u .cluster span{color:#333;}#mermaid-svg-F6NyHO90bqQkko3u div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-F6NyHO90bqQkko3u .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-F6NyHO90bqQkko3u rect.text{fill:none;stroke-width:0;}#mermaid-svg-F6NyHO90bqQkko3u .icon-shape,#mermaid-svg-F6NyHO90bqQkko3u .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-F6NyHO90bqQkko3u .icon-shape p,#mermaid-svg-F6NyHO90bqQkko3u .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-F6NyHO90bqQkko3u .icon-shape .label rect,#mermaid-svg-F6NyHO90bqQkko3u .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-F6NyHO90bqQkko3u .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-F6NyHO90bqQkko3u .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-F6NyHO90bqQkko3u :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    逐点卷积

    输入 C_in 个通道

    卷积核 1×1×C_in

    仅通道维度加权求和

    输出 C_out 个通道

    一般卷积

    输入 C_in 个通道

    卷积核 K×K×C_in

    空间+通道同时聚合

    输出 C_out 个通道

    逐点卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #测试不同卷积参数下的输出尺寸和通道数
    pw_conv1=Conv2d(in_channels=3,out_channels=16,kernel_size=1,stride=1,padding=0)
    pw_conv2=Conv2d(in_channels=3,out_channels=64,kernel_size=1,stride=1,padding=0)
    y1=pw_conv1(image)
    y2=pw_conv2(image)
    y=[y1,y2]
    for yy in y:
    print(yy.shape)
    #输出
    '''
    torch.Size([1, 16, 256, 256])
    torch.Size([1, 64, 256, 256])
    '''

    逐点卷积同样适用Conv2d类进行构建,只需将kernel_size设为1即可。可以看到,无论输出通道数如何变化,输出特征图的空间尺寸始终与输入保持一致,这正是

    1

    ×

    1

    1 \\times 1

    1×1 卷积核不改变空间尺寸的体现。逐点卷积常用于改变通道数,例如在深度可分离卷积中,先用逐深度卷积提取空间特征,再用逐点卷积混合通道信息并调整通道数。

    3.3 逐点卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,则:

    • 参数量:

      C

      i

      n

      ×

      C

      o

      u

      t

      C_{in} \\times C_{out}

      Cin×Cout

    • 计算量:

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      C_{in} \\times C_{out} \\times H \\times W

      Cin×Cout×H×W

    其中

    H

    H

    H

    W

    W

    W 为输入(也是输出)特征图的尺寸。对比一般卷积的参数量

    k

    ×

    k

    ×

    C

    i

    n

    ×

    C

    o

    u

    t

    k \\times k \\times C_{in} \\times C_{out}

    k×k×Cin×Cout,逐点卷积的参数量只有一般卷积的

    1

    /

    k

    2

    1/k^2

    1/k2,计算量也相应大幅下降。这正是逐点卷积的核心优势——用极小的代价完成通道维度的信息融合与变换。

    3.4 逐点卷积的局限

    尽管逐点卷积在通道变换上非常高效,但它也存在明显的不足:

    • 无法提取空间特征:由于卷积核尺寸为

      1

      ×

      1

      1 \\times 1

      1×1,逐点卷积只能聚合通道维度的信息,无法感知空间邻域,因此不能单独用于提取局部空间特征;

    • 单独使用表达能力有限:单独使用逐点卷积时,模型只能做通道间的线性组合,对特征的表达能力较弱,通常需要配合逐深度卷积(Depthwise Convolution) 来提取空间特征,二者组合便构成了经典的深度可分离卷积(Depthwise Separable Convolution)。

    正是为了弥补逐点卷积在空间特征提取上的不足,后续才发展出了深度可分离卷积,这些将在后续章节中详细讲解。

    4深度可分离卷积

    深度可分离卷积(Depthwise Separable Convolution)是逐深度卷积(Depthwise Convolution)与逐点卷积(Pointwise Convolution)的级联组合,它的核心思想是将一般卷积分解为“空间特征提取”和“通道信息融合”两个独立步骤,从而在保持相近表达能力的同时大幅降低参数量与计算量。

    4.1 什么是深度可分离卷积

    在一般卷积中,卷积核会同时在空间和通道两个维度上做加权求和,空间特征提取与通道信息融合是一步完成的。而深度可分离卷积则把这一过程拆成两步,深度可分离卷积=逐深度卷积+逐点卷积:

  • 逐深度卷积:先用

    k

    ×

    k

    k \\times k

    k×k 的卷积核对每个输入通道分别做空间卷积,提取空间特征,但通道之间互不混合;

  • 逐点卷积:再用

    1

    ×

    1

    1 \\times 1

    1×1 的卷积核在通道维度上做加权求和,融合通道信息并调整通道数。 其计算过程如下图: 深度可分离卷积

  • 假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,深度可分离卷积先经过逐深度卷积(卷积核尺寸

    k

    ×

    k

    k \\times k

    k×k),再经过逐点卷积(输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout),则输出特征图

    Y

    Y

    Y 上第

    j

    j

    j 个通道、位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    j

    (

    i

    ,

    j

    )

    =

    c

    =

    0

    C

    i

    n

    1

    (

    m

    =

    0

    k

    1

    n

    =

    0

    k

    1

    X

    c

    (

    i

    +

    m

    ,

    j

    +

    n

    )

    K

    c

    (

    m

    ,

    n

    )

    +

    b

    c

    )

    P

    j

    (

    c

    )

    +

    b

    j

    Y_j(i,j) = \\sum_{c=0}^{C_{in}-1} \\left( \\sum_{m=0}^{k-1} \\sum_{n=0}^{k-1} X_c(i+m, j+n) \\cdot K_c(m,n) + b_c \\right) \\cdot P_j(c) + b_j

    Yj(i,j)=c=0Cin1(m=0k1n=0k1Xc(i+m,j+n)Kc(m,n)+bc)Pj(c)+bj

    其中

    X

    c

    X_c

    Xc 为输入的第

    c

    c

    c 个通道,

    K

    c

    K_c

    Kc 为逐深度卷积中第

    c

    c

    c 个通道对应的

    k

    ×

    k

    k \\times k

    k×k 卷积核,

    b

    c

    b_c

    bc 为其偏置项;

    P

    j

    P_j

    Pj 为逐点卷积中第

    j

    j

    j 个输出通道对应的

    1

    ×

    1

    ×

    C

    i

    n

    1 \\times 1 \\times C_{in}

    1×1×Cin 卷积核,

    b

    j

    b_j

    bj 为其偏置项。可以看到,深度可分离卷积的输出通道数由逐点卷积决定,而空间尺寸则由逐深度卷积决定,二者各司其职。

    4.2 深度可分离卷积的运算过程

    深度可分离卷积的完整过程可以拆解为以下几步:

  • 逐深度卷积:对输入特征图的每一个通道,用对应的

    k

    ×

    k

    k \\times k

    k×k 卷积核在该通道上滑动并加权求和,得到与输入通道数相同的中间特征图,完成空间特征提取。

  • 逐点卷积:用

    C

    o

    u

    t

    C_{out}

    Cout

    1

    ×

    1

    ×

    C

    i

    n

    1 \\times 1 \\times C_{in}

    1×1×Cin 的卷积核,在中间特征图的每个空间位置上对通道维度做加权求和,融合通道信息并调整通道数。

  • 拼接输出:所有

    C

    o

    u

    t

    C_{out}

    Cout 个逐点卷积核计算完成后,将各通道的输出按顺序拼接,得到尺寸为

    H

    ×

    W

    ×

    C

    o

    u

    t

    H' \\times W' \\times C_{out}

    H×W×Cout 的输出特征图。

  • 下面是一个直观的对比示意图:

    #mermaid-svg-T3XYeo7ciFzJ8wPb{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T3XYeo7ciFzJ8wPb .error-icon{fill:#552222;}#mermaid-svg-T3XYeo7ciFzJ8wPb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T3XYeo7ciFzJ8wPb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .marker.cross{stroke:#333333;}#mermaid-svg-T3XYeo7ciFzJ8wPb svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T3XYeo7ciFzJ8wPb p{margin:0;}#mermaid-svg-T3XYeo7ciFzJ8wPb .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster-label text{fill:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster-label span{color:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster-label span p{background-color:transparent;}#mermaid-svg-T3XYeo7ciFzJ8wPb .label text,#mermaid-svg-T3XYeo7ciFzJ8wPb span{fill:#333;color:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .node rect,#mermaid-svg-T3XYeo7ciFzJ8wPb .node circle,#mermaid-svg-T3XYeo7ciFzJ8wPb .node ellipse,#mermaid-svg-T3XYeo7ciFzJ8wPb .node polygon,#mermaid-svg-T3XYeo7ciFzJ8wPb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .rough-node .label text,#mermaid-svg-T3XYeo7ciFzJ8wPb .node .label text,#mermaid-svg-T3XYeo7ciFzJ8wPb .image-shape .label,#mermaid-svg-T3XYeo7ciFzJ8wPb .icon-shape .label{text-anchor:middle;}#mermaid-svg-T3XYeo7ciFzJ8wPb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .rough-node .label,#mermaid-svg-T3XYeo7ciFzJ8wPb .node .label,#mermaid-svg-T3XYeo7ciFzJ8wPb .image-shape .label,#mermaid-svg-T3XYeo7ciFzJ8wPb .icon-shape .label{text-align:center;}#mermaid-svg-T3XYeo7ciFzJ8wPb .node.clickable{cursor:pointer;}#mermaid-svg-T3XYeo7ciFzJ8wPb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .arrowheadPath{fill:#333333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T3XYeo7ciFzJ8wPb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-T3XYeo7ciFzJ8wPb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T3XYeo7ciFzJ8wPb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster text{fill:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb .cluster span{color:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-T3XYeo7ciFzJ8wPb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-T3XYeo7ciFzJ8wPb rect.text{fill:none;stroke-width:0;}#mermaid-svg-T3XYeo7ciFzJ8wPb .icon-shape,#mermaid-svg-T3XYeo7ciFzJ8wPb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T3XYeo7ciFzJ8wPb .icon-shape p,#mermaid-svg-T3XYeo7ciFzJ8wPb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-T3XYeo7ciFzJ8wPb .icon-shape .label rect,#mermaid-svg-T3XYeo7ciFzJ8wPb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T3XYeo7ciFzJ8wPb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-T3XYeo7ciFzJ8wPb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-T3XYeo7ciFzJ8wPb :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    深度可分离卷积

    输入 C_in 个通道

    逐深度卷积 K×K×1

    中间特征图 C_in 个通道

    逐点卷积 1×1×C_in

    输出 C_out 个通道

    一般卷积

    输入 C_in 个通道

    卷积核 K×K×C_in

    空间+通道一步完成

    输出 C_out 个通道

    深度可分离卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #深度可分离卷积 = 逐深度卷积 + 逐点卷积
    dw_conv=Conv2d(in_channels=3,out_channels=3,kernel_size=3,stride=1,padding=1,groups=3)
    pw_conv=Conv2d(in_channels=3,out_channels=16,kernel_size=1,stride=1,padding=0)
    y1=dw_conv(image)
    y2=pw_conv(y1)
    print(y1.shape)
    print(y2.shape)
    #输出
    '''
    torch.Size([1, 3, 256, 256])
    torch.Size([1, 16, 256, 256])
    '''

    深度可分离卷积在Pytorch中就是逐深度卷积与逐点卷积的串联:先用一个 groups=输入通道数 的 Conv2d 完成逐深度卷积,再用一个 kernel_size=1 的 Conv2d 完成逐点卷积。可以看到,逐深度卷积保持通道数不变、只改变空间尺寸,逐点卷积保持空间尺寸不变、只改变通道数,二者组合即可自由地调整输出特征图的形状。

    4.3 深度可分离卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,则:

    • 参数量:

      k

      ×

      k

      ×

      C

      i

      n

      +

      C

      i

      n

      ×

      C

      o

      u

      t

      k \\times k \\times C_{in} + C_{in} \\times C_{out}

      k×k×Cin+Cin×Cout

    • 计算量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      H

      ×

      W

      +

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      k \\times k \\times C_{in} \\times H' \\times W' + C_{in} \\times C_{out} \\times H' \\times W'

      k×k×Cin×H×W+Cin×Cout×H×W

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。对比一般卷积的参数量

    k

    ×

    k

    ×

    C

    i

    n

    ×

    C

    o

    u

    t

    k \\times k \\times C_{in} \\times C_{out}

    k×k×Cin×Cout,深度可分离卷积的参数量约为一般卷积的

    1

    /

    C

    o

    u

    t

    +

    1

    /

    k

    2

    1/C_{out} + 1/k^2

    1/Cout+1/k2,当

    C

    o

    u

    t

    C_{out}

    Cout 较大时,参数量可压缩到一般卷积的

    1

    /

    k

    2

    1/k^2

    1/k2 左右,计算量也相应大幅下降。这正是深度可分离卷积的核心优势——用极小的代价同时完成空间特征提取与通道信息融合,因此被广泛应用于 MobileNet 等轻量级网络。

    4.4 深度可分离卷积的局限

    尽管深度可分离卷积在参数量和计算量上优势明显,但它也存在一些不足:

    • 表达能力相对有限:将空间与通道的联合建模拆分为两步,相比一般卷积的联合优化,特征表达能力略有下降,通常需要更深的网络或更多的通道数来弥补;
    • 对硬件实现不友好:逐深度卷积的通道间计算相互独立,在部分硬件上难以充分利用并行计算资源,实际加速效果可能不如理论值;
    • 需要精心设计:深度可分离卷积的效果对通道数、卷积核尺寸等超参数较为敏感,需要结合具体任务进行调优。

    正是为了在保持轻量化的同时进一步提升表达能力,后续才发展出了空洞卷积、不对称卷积以及分组卷积等变体,这些将在后续章节中详细讲解。

    5空洞卷积

    空洞卷积(Dilated Convolution)是一般卷积的一种特殊形式,它的核心思想是在卷积核的元素之间插入空洞(即间隔),在不增加参数量和计算量的前提下扩大感受野(Receptive Field),从而让每个输出点能够“看到”输入上更大范围的区域。 空洞卷积示意图

    5.1 什么是空洞卷积

    在一般卷积中,卷积核是连续排列的,例如

    3

    ×

    3

    3 \\times 3

    3×3 卷积核覆盖输入上相邻的

    3

    ×

    3

    3 \\times 3

    3×3 区域。而空洞卷积则完全不同:它在卷积核的相邻元素之间插入

    d

    1

    d-1

    d1 个空洞(dilation rate 为

    d

    d

    d),使得卷积核在输入上覆盖的范围变大,但参与计算的元素个数不变。

    假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,空洞卷积的卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,膨胀率为

    d

    d

    d,则输出特征图

    Y

    Y

    Y 上位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    (

    i

    ,

    j

    )

    =

    m

    =

    0

    k

    1

    n

    =

    0

    k

    1

    X

    (

    i

    +

    m

    d

    ,

    j

    +

    n

    d

    )

    K

    (

    m

    ,

    n

    )

    +

    b

    Y(i,j) = \\sum_{m=0}^{k-1} \\sum_{n=0}^{k-1} X(i + m \\cdot d, j + n \\cdot d) \\cdot K(m,n) + b

    Y(i,j)=m=0k1n=0k1X(i+md,j+nd)K(m,n)+b

    其中

    X

    X

    X 为输入特征图,

    K

    K

    K

    k

    ×

    k

    k \\times k

    k×k 的卷积核,

    b

    b

    b 为偏置项。可以看到,卷积核的权重个数仍然是

    k

    ×

    k

    k \\times k

    k×k 个,但采样点之间的间隔变成了

    d

    d

    d。当

    d

    =

    1

    d=1

    d=1 时,空洞卷积退化为一般卷积;当

    d

    >

    1

    d>1

    d>1 时,卷积核覆盖的范围被放大。

    空洞卷积的等效感受野尺寸为:

    R

    F

    =

    k

    +

    (

    k

    1

    )

    ×

    (

    d

    1

    )

    RF = k + (k-1) \\times (d-1)

    RF=k+(k1)×(d1)

    例如,

    3

    ×

    3

    3 \\times 3

    3×3 卷积核在

    d

    =

    2

    d=2

    d=2 时,等效感受野为

    5

    ×

    5

    5 \\times 5

    5×5;在

    d

    =

    3

    d=3

    d=3 时,等效感受野为

    7

    ×

    7

    7 \\times 7

    7×7。参数量始终是

    k

    ×

    k

    k \\times k

    k×k,与

    d

    d

    d 无关,这正是空洞卷积的核心优势——用与一般卷积相同的参数量,获得更大的感受野。

    5.2 空洞卷积的运算过程

    空洞卷积的完整过程可以拆解为以下几步:

  • 确定卷积核与膨胀率:设定卷积核尺寸(如

    3

    ×

    3

    3 \\times 3

    3×3)、膨胀率

    d

    d

    d(dilation rate)、步长(Stride)和填充(Padding)。

  • 插入空洞:在卷积核的相邻元素之间插入

    d

    1

    d-1

    d1 个空洞,得到等效的“膨胀卷积核”,其覆盖范围为

    k

    +

    (

    k

    1

    )

    ×

    (

    d

    1

    )

    k + (k-1) \\times (d-1)

    k+(k1)×(d1)

  • 滑动窗口:膨胀后的卷积核从输入左上角开始,按步长在输入上从左到右、从上到下滑动。
  • 加权求和:每滑动到一个位置,将卷积核的

    k

    ×

    k

    k \\times k

    k×k 个权重与对应位置(间隔为

    d

    d

    d)的输入元素逐元素相乘后求和,再加上偏置,得到输出特征图上的一个值。

  • 下面是一个直观的对比示意图:

    #mermaid-svg-Tw6jqlNC5zOU8SHK{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Tw6jqlNC5zOU8SHK .error-icon{fill:#552222;}#mermaid-svg-Tw6jqlNC5zOU8SHK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Tw6jqlNC5zOU8SHK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .marker.cross{stroke:#333333;}#mermaid-svg-Tw6jqlNC5zOU8SHK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Tw6jqlNC5zOU8SHK p{margin:0;}#mermaid-svg-Tw6jqlNC5zOU8SHK .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster-label text{fill:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster-label span{color:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster-label span p{background-color:transparent;}#mermaid-svg-Tw6jqlNC5zOU8SHK .label text,#mermaid-svg-Tw6jqlNC5zOU8SHK span{fill:#333;color:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .node rect,#mermaid-svg-Tw6jqlNC5zOU8SHK .node circle,#mermaid-svg-Tw6jqlNC5zOU8SHK .node ellipse,#mermaid-svg-Tw6jqlNC5zOU8SHK .node polygon,#mermaid-svg-Tw6jqlNC5zOU8SHK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .rough-node .label text,#mermaid-svg-Tw6jqlNC5zOU8SHK .node .label text,#mermaid-svg-Tw6jqlNC5zOU8SHK .image-shape .label,#mermaid-svg-Tw6jqlNC5zOU8SHK .icon-shape .label{text-anchor:middle;}#mermaid-svg-Tw6jqlNC5zOU8SHK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .rough-node .label,#mermaid-svg-Tw6jqlNC5zOU8SHK .node .label,#mermaid-svg-Tw6jqlNC5zOU8SHK .image-shape .label,#mermaid-svg-Tw6jqlNC5zOU8SHK .icon-shape .label{text-align:center;}#mermaid-svg-Tw6jqlNC5zOU8SHK .node.clickable{cursor:pointer;}#mermaid-svg-Tw6jqlNC5zOU8SHK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .arrowheadPath{fill:#333333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tw6jqlNC5zOU8SHK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Tw6jqlNC5zOU8SHK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tw6jqlNC5zOU8SHK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster text{fill:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK .cluster span{color:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Tw6jqlNC5zOU8SHK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Tw6jqlNC5zOU8SHK rect.text{fill:none;stroke-width:0;}#mermaid-svg-Tw6jqlNC5zOU8SHK .icon-shape,#mermaid-svg-Tw6jqlNC5zOU8SHK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Tw6jqlNC5zOU8SHK .icon-shape p,#mermaid-svg-Tw6jqlNC5zOU8SHK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Tw6jqlNC5zOU8SHK .icon-shape .label rect,#mermaid-svg-Tw6jqlNC5zOU8SHK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Tw6jqlNC5zOU8SHK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Tw6jqlNC5zOU8SHK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Tw6jqlNC5zOU8SHK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    空洞卷积 d=3

    3×3 卷积核

    插入空洞后覆盖 7×7 区域

    感受野 7×7

    空洞卷积 d=2

    3×3 卷积核

    插入空洞后覆盖 5×5 区域

    感受野 5×5

    一般卷积 d=1

    3×3 卷积核

    覆盖 3×3 区域

    感受野 3×3

    空洞卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #测试不同膨胀率下的输出尺寸和通道数
    dil_conv1=Conv2d(in_channels=3,out_channels=16,kernel_size=3,stride=1,padding=1,dilation=1)
    dil_conv2=Conv2d(in_channels=3,out_channels=16,kernel_size=3,stride=1,padding=2,dilation=2)
    dil_conv3=Conv2d(in_channels=3,out_channels=16,kernel_size=3,stride=1,padding=3,dilation=3)
    y1=dil_conv1(image)
    y2=dil_conv2(image)
    y3=dil_conv3(image)
    y=[y1,y2,y3]
    for yy in y:
    print(yy.shape)
    #输出
    '''
    torch.Size([1, 16, 256, 256])
    torch.Size([1, 16, 256, 256])
    torch.Size([1, 16, 256, 256])
    '''

    空洞卷积同样适用Conv2d类进行构建,只需设置dilation参数即可。可以看到,当padding设置为

    (

    d

    1

    )

    ×

    k

    /

    2

    (d-1) \\times k / 2

    (d1)×k/2 时,输出特征图的空间尺寸与输入保持一致。例如,

    3

    ×

    3

    3 \\times 3

    3×3 卷积核在

    d

    =

    2

    d=2

    d=2 时,padding=2 即可保持尺寸不变;在

    d

    =

    3

    d=3

    d=3 时,padding=3 即可保持尺寸不变。膨胀率越大,卷积核覆盖的范围越大,但输出尺寸可以通过调整padding来保持。

    5.3 空洞卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,膨胀率为

    d

    d

    d,则:

    • 参数量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      k \\times k \\times C_{in} \\times C_{out}

      k×k×Cin×Cout

    • 计算量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      k \\times k \\times C_{in} \\times C_{out} \\times H' \\times W'

      k×k×Cin×Cout×H×W

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。可以看到,空洞卷积的参数量和计算量与一般卷积完全相同,与膨胀率

    d

    d

    d 无关。但它的等效感受野却从

    k

    ×

    k

    k \\times k

    k×k 扩大到了

    k

    +

    (

    k

    1

    )

    ×

    (

    d

    1

    )

    k + (k-1) \\times (d-1)

    k+(k1)×(d1),这正是空洞卷积的核心优势——在不增加任何参数和计算开销的前提下,大幅扩大感受野。

    5.4 空洞卷积的局限

    尽管空洞卷积在扩大感受野上优势明显,但它也存在一些不足:

    • 网格效应(Gridding Artifact):当多个空洞卷积层堆叠且膨胀率相同时,采样点会呈现规则的网格状分布,导致部分区域的信息被遗漏,影响特征的连续性;
    • 局部信息丢失:由于采样点之间存在间隔,空洞卷积会跳过部分像素,对于小目标或细节丰富的区域,可能丢失重要的局部信息;
    • 需要精心设计膨胀率:空洞卷积的效果对膨胀率的取值较为敏感,通常需要采用混合膨胀率(Hybrid Dilated Convolution) 或与其他卷积组合使用,才能兼顾感受野与信息完整性。

    正是为了在扩大感受野的同时避免网格效应,后续才发展出了不对称卷积以及分组卷积等变体,这些将在后续章节中详细讲解。

    6不对称卷积

    不对称卷积(Asymmetric Convolution)是一般卷积的一种特殊形式,它的核心思想是将一个

    n

    ×

    n

    n \\times n

    n×n 的卷积核分解为

    n

    ×

    1

    n \\times 1

    n×1

    1

    ×

    n

    1 \\times n

    1×n 两个卷积核的串联,从而在保持相近感受野的前提下大幅降低参数量与计算量。

    6.1 什么是不对称卷积

    在一般卷积中,卷积核是方形的,例如

    3

    ×

    3

    3 \\times 3

    3×3

    5

    ×

    5

    5 \\times 5

    5×5,它在空间的两个维度上同时提取特征。而不对称卷积则完全不同:它把一个

    n

    ×

    n

    n \\times n

    n×n 的卷积核拆分成一个

    n

    ×

    1

    n \\times 1

    n×1 的卷积核和一个

    1

    ×

    n

    1 \\times n

    1×n 的卷积核,先沿一个方向(如竖直方向)做卷积,再沿另一个方向(如水平方向)做卷积。如下图: 不对称卷积

    假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,不对称卷积先使用

    n

    ×

    1

    n \\times 1

    n×1 的卷积核,再使用

    1

    ×

    n

    1 \\times n

    1×n 的卷积核,则中间特征图

    Z

    Z

    Z 上位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Z

    (

    i

    ,

    j

    )

    =

    m

    =

    0

    n

    1

    X

    (

    i

    +

    m

    ,

    j

    )

    K

    v

    (

    m

    )

    +

    b

    v

    Z(i,j) = \\sum_{m=0}^{n-1} X(i+m, j) \\cdot K_v(m) + b_v

    Z(i,j)=m=0n1X(i+m,j)Kv(m)+bv

    其中

    X

    X

    X 为输入特征图,

    K

    v

    K_v

    Kv

    n

    ×

    1

    n \\times 1

    n×1 的竖直卷积核,

    b

    v

    b_v

    bv 为其偏置项。随后,输出特征图

    Y

    Y

    Y 上位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    (

    i

    ,

    j

    )

    =

    n

    =

    0

    n

    1

    Z

    (

    i

    ,

    j

    +

    n

    )

    K

    h

    (

    n

    )

    +

    b

    h

    Y(i,j) = \\sum_{n=0}^{n-1} Z(i, j+n) \\cdot K_h(n) + b_h

    Y(i,j)=n=0n1Z(i,j+n)Kh(n)+bh

    其中

    K

    h

    K_h

    Kh

    1

    ×

    n

    1 \\times n

    1×n 的水平卷积核,

    b

    h

    b_h

    bh 为其偏置项。可以看到,两步卷积的等效感受野与一个

    n

    ×

    n

    n \\times n

    n×n 卷积相同,但参数量却大幅下降。例如,

    3

    ×

    3

    3 \\times 3

    3×3 卷积分解为

    3

    ×

    1

    3 \\times 1

    3×1

    1

    ×

    3

    1 \\times 3

    1×3 后,等效感受野仍然是

    3

    ×

    3

    3 \\times 3

    3×3

    6.2 不对称卷积的运算过程

    不对称卷积的完整过程可以拆解为以下几步:

  • 确定卷积核:设定卷积核尺寸

    n

    n

    n,将其分解为

    n

    ×

    1

    n \\times 1

    n×1

    1

    ×

    n

    1 \\times n

    1×n 两个卷积核,并设定步长(Stride)和填充(Padding)。

  • 竖直方向卷积:先用

    n

    ×

    1

    n \\times 1

    n×1 的卷积核在输入上沿竖直方向滑动并加权求和,得到中间特征图。

  • 水平方向卷积:再用

    1

    ×

    n

    1 \\times n

    1×n 的卷积核在中间特征图上沿水平方向滑动并加权求和,得到最终输出特征图。

  • 拼接输出:所有通道计算完成后,将各通道的输出按顺序拼接,得到最终的输出特征图。
  • 下面是一个直观的对比示意图:

    #mermaid-svg-aABI7sbbipSZoG4H{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aABI7sbbipSZoG4H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aABI7sbbipSZoG4H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aABI7sbbipSZoG4H .error-icon{fill:#552222;}#mermaid-svg-aABI7sbbipSZoG4H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aABI7sbbipSZoG4H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aABI7sbbipSZoG4H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aABI7sbbipSZoG4H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aABI7sbbipSZoG4H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aABI7sbbipSZoG4H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aABI7sbbipSZoG4H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aABI7sbbipSZoG4H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aABI7sbbipSZoG4H .marker.cross{stroke:#333333;}#mermaid-svg-aABI7sbbipSZoG4H svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aABI7sbbipSZoG4H p{margin:0;}#mermaid-svg-aABI7sbbipSZoG4H .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aABI7sbbipSZoG4H .cluster-label text{fill:#333;}#mermaid-svg-aABI7sbbipSZoG4H .cluster-label span{color:#333;}#mermaid-svg-aABI7sbbipSZoG4H .cluster-label span p{background-color:transparent;}#mermaid-svg-aABI7sbbipSZoG4H .label text,#mermaid-svg-aABI7sbbipSZoG4H span{fill:#333;color:#333;}#mermaid-svg-aABI7sbbipSZoG4H .node rect,#mermaid-svg-aABI7sbbipSZoG4H .node circle,#mermaid-svg-aABI7sbbipSZoG4H .node ellipse,#mermaid-svg-aABI7sbbipSZoG4H .node polygon,#mermaid-svg-aABI7sbbipSZoG4H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aABI7sbbipSZoG4H .rough-node .label text,#mermaid-svg-aABI7sbbipSZoG4H .node .label text,#mermaid-svg-aABI7sbbipSZoG4H .image-shape .label,#mermaid-svg-aABI7sbbipSZoG4H .icon-shape .label{text-anchor:middle;}#mermaid-svg-aABI7sbbipSZoG4H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aABI7sbbipSZoG4H .rough-node .label,#mermaid-svg-aABI7sbbipSZoG4H .node .label,#mermaid-svg-aABI7sbbipSZoG4H .image-shape .label,#mermaid-svg-aABI7sbbipSZoG4H .icon-shape .label{text-align:center;}#mermaid-svg-aABI7sbbipSZoG4H .node.clickable{cursor:pointer;}#mermaid-svg-aABI7sbbipSZoG4H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aABI7sbbipSZoG4H .arrowheadPath{fill:#333333;}#mermaid-svg-aABI7sbbipSZoG4H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aABI7sbbipSZoG4H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aABI7sbbipSZoG4H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aABI7sbbipSZoG4H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aABI7sbbipSZoG4H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aABI7sbbipSZoG4H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aABI7sbbipSZoG4H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aABI7sbbipSZoG4H .cluster text{fill:#333;}#mermaid-svg-aABI7sbbipSZoG4H .cluster span{color:#333;}#mermaid-svg-aABI7sbbipSZoG4H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aABI7sbbipSZoG4H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aABI7sbbipSZoG4H rect.text{fill:none;stroke-width:0;}#mermaid-svg-aABI7sbbipSZoG4H .icon-shape,#mermaid-svg-aABI7sbbipSZoG4H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aABI7sbbipSZoG4H .icon-shape p,#mermaid-svg-aABI7sbbipSZoG4H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aABI7sbbipSZoG4H .icon-shape .label rect,#mermaid-svg-aABI7sbbipSZoG4H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aABI7sbbipSZoG4H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aABI7sbbipSZoG4H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aABI7sbbipSZoG4H :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    不对称卷积

    输入特征图

    卷积核 n×1 竖直卷积

    中间特征图

    卷积核 1×n 水平卷积

    输出特征图

    一般卷积

    输入特征图

    卷积核 n×n

    一步完成空间特征提取

    输出特征图

    不对称卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,3,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #不对称卷积 = n×1 卷积 + 1×n 卷积
    asym_conv1=Conv2d(in_channels=3,out_channels=16,kernel_size=(3,1),stride=1,padding=(1,0))
    asym_conv2=Conv2d(in_channels=16,out_channels=16,kernel_size=(1,3),stride=1,padding=(0,1))
    y1=asym_conv1(image)
    y2=asym_conv2(y1)
    print(y1.shape)
    print(y2.shape)
    #输出
    '''
    torch.Size([1, 16, 256, 256])
    torch.Size([1, 16, 256, 256])
    '''

    不对称卷积同样适用Conv2d类进行构建,只需将kernel_size设为元组即可。可以看到,先经过

    n

    ×

    1

    n \\times 1

    n×1 卷积,再经过

    1

    ×

    n

    1 \\times n

    1×n 卷积,输出特征图的空间尺寸与输入保持一致,而等效感受野与一个

    n

    ×

    n

    n \\times n

    n×n 卷积相同。当padding设置为

    (

    n

    1

    )

    /

    2

    (n-1)/2

    (n1)/2 时,两步卷积都能保持空间尺寸不变。

    6.3 不对称卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,卷积核尺寸为

    n

    ×

    n

    n \\times n

    n×n,则:

    • 参数量:

      n

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      +

      n

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      =

      2

      n

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      n \\times C_{in} \\times C_{out} + n \\times C_{in} \\times C_{out} = 2n \\times C_{in} \\times C_{out}

      n×Cin×Cout+n×Cin×Cout=2n×Cin×Cout

    • 计算量:

      2

      n

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      2n \\times C_{in} \\times C_{out} \\times H' \\times W'

      2n×Cin×Cout×H×W

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。对比一般卷积的参数量

    n

    ×

    n

    ×

    C

    i

    n

    ×

    C

    o

    u

    t

    n \\times n \\times C_{in} \\times C_{out}

    n×n×Cin×Cout,不对称卷积的参数量只有一般卷积的

    2

    /

    n

    2/n

    2/n,计算量也相应大幅下降。例如,

    3

    ×

    3

    3 \\times 3

    3×3 卷积分解为

    3

    ×

    1

    3 \\times 1

    3×1

    1

    ×

    3

    1 \\times 3

    1×3 后,参数量从

    9

    9

    9 降为

    6

    6

    6,减少了约

    1

    /

    3

    1/3

    1/3。这正是不对称卷积的核心优势——用更少的参数实现相近的感受野。

    6.4 不对称卷积的局限

    尽管不对称卷积在参数量和计算量上优势明显,但它也存在一些不足:

    • 表达能力相对有限:将二维卷积分解为两个一维卷积,相当于对特征提取施加了更强的结构约束,相比一般卷积的联合优化,特征表达能力略有下降;
    • 对方向性特征敏感:不对称卷积对水平与竖直方向的特征提取效果较好,但对对角线方向等复杂纹理的建模能力较弱;
    • 需要精心设计:不对称卷积的效果对卷积核尺寸、分解方式等超参数较为敏感,通常需要结合具体任务进行调优。

    正是为了在降低参数量的同时保持较强的表达能力,后续才发展出了分组卷积等变体,这些将在后续章节中详细讲解。

    7分组卷积

    分组卷积(Grouped Convolution)是一般卷积的一种特殊形式,它的核心思想是将输入通道划分为若干组,每组内部独立进行一般卷积,从而在保持相近表达能力的前提下大幅降低参数量与计算量。当分组数等于输入通道数时,分组卷积就退化为逐深度卷积。

    7.1 什么是分组卷积

    在一般卷积中,卷积核会在所有输入通道上同时滑动并求和,将所有通道的信息混合在一起。而分组卷积则完全不同:它先把输入特征图的

    C

    i

    n

    C_{in}

    Cin 个通道平均分成

    G

    G

    G 组,每组包含

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G 个通道,然后对每一组分别进行一般卷积,组与组之间互不混合。

    假设输入特征图有

    C

    i

    n

    C_{in}

    Cin 个通道,尺寸为

    H

    ×

    W

    H \\times W

    H×W,分组数为

    G

    G

    G,则每组输入有

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G 个通道。分组卷积使用

    C

    o

    u

    t

    C_{out}

    Cout 个卷积核,同样分成

    G

    G

    G 组,每组有

    C

    o

    u

    t

    /

    G

    C_{out}/G

    Cout/G 个卷积核,每个卷积核的通道数为

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G。则输出特征图

    Y

    Y

    Y 上第

    g

    g

    g 组、第

    j

    j

    j 个通道、位置

    (

    i

    ,

    j

    )

    (i,j)

    (i,j) 的值可以表示为:

    Y

    g

    ,

    j

    (

    i

    ,

    j

    )

    =

    c

    =

    0

    C

    i

    n

    /

    G

    1

    m

    =

    0

    k

    1

    n

    =

    0

    k

    1

    X

    g

    ,

    c

    (

    i

    +

    m

    ,

    j

    +

    n

    )

    K

    g

    ,

    j

    ,

    c

    (

    m

    ,

    n

    )

    +

    b

    g

    ,

    j

    Y_{g,j}(i,j) = \\sum_{c=0}^{C_{in}/G-1} \\sum_{m=0}^{k-1} \\sum_{n=0}^{k-1} X_{g,c}(i+m, j+n) \\cdot K_{g,j,c}(m,n) + b_{g,j}

    Yg,j(i,j)=c=0Cin/G1m=0k1n=0k1Xg,c(i+m,j+n)Kg,j,c(m,n)+bg,j

    其中

    X

    g

    ,

    c

    X_{g,c}

    Xg,c 为输入第

    g

    g

    g 组的第

    c

    c

    c 个通道,

    K

    g

    ,

    j

    ,

    c

    K_{g,j,c}

    Kg,j,c 为第

    g

    g

    g 组第

    j

    j

    j 个卷积核在第

    c

    c

    c 个通道上的权重,

    b

    g

    ,

    j

    b_{g,j}

    bg,j 为其偏置项。可以看到,每一组只与自己的输入通道做卷积,组与组之间互不干扰。当

    G

    =

    1

    G=1

    G=1 时,分组卷积退化为一般卷积;当

    G

    =

    C

    i

    n

    G=C_{in}

    G=Cin 时,分组卷积退化为逐深度卷积。 分组卷积

    7.2 分组卷积的运算过程

    分组卷积的完整过程可以拆解为以下几步:

  • 确定分组数:设定分组数

    G

    G

    G,要求

    C

    i

    n

    C_{in}

    Cin

    C

    o

    u

    t

    C_{out}

    Cout 都能被

    G

    G

    G 整除,每组输入通道数为

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G,每组卷积核个数为

    C

    o

    u

    t

    /

    G

    C_{out}/G

    Cout/G

  • 通道分组:将输入特征图的

    C

    i

    n

    C_{in}

    Cin 个通道平均分成

    G

    G

    G 组,每组包含

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G 个通道。

  • 组内卷积:对每一组,用该组对应的

    C

    o

    u

    t

    /

    G

    C_{out}/G

    Cout/G 个卷积核在该组的

    C

    i

    n

    /

    G

    C_{in}/G

    Cin/G 个通道上做一般卷积,得到该组的

    C

    o

    u

    t

    /

    G

    C_{out}/G

    Cout/G 个输出通道。

  • 拼接输出:所有

    G

    G

    G 组卷积完成后,将各组的输出按顺序拼接,得到

    C

    o

    u

    t

    C_{out}

    Cout 个通道的输出特征图。

  • 下面是一个直观的对比示意图:

    #mermaid-svg-byFsaB2pEhfdgil4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-byFsaB2pEhfdgil4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-byFsaB2pEhfdgil4 .error-icon{fill:#552222;}#mermaid-svg-byFsaB2pEhfdgil4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-byFsaB2pEhfdgil4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-byFsaB2pEhfdgil4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-byFsaB2pEhfdgil4 .marker.cross{stroke:#333333;}#mermaid-svg-byFsaB2pEhfdgil4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-byFsaB2pEhfdgil4 p{margin:0;}#mermaid-svg-byFsaB2pEhfdgil4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-byFsaB2pEhfdgil4 .cluster-label text{fill:#333;}#mermaid-svg-byFsaB2pEhfdgil4 .cluster-label span{color:#333;}#mermaid-svg-byFsaB2pEhfdgil4 .cluster-label span p{background-color:transparent;}#mermaid-svg-byFsaB2pEhfdgil4 .label text,#mermaid-svg-byFsaB2pEhfdgil4 span{fill:#333;color:#333;}#mermaid-svg-byFsaB2pEhfdgil4 .node rect,#mermaid-svg-byFsaB2pEhfdgil4 .node circle,#mermaid-svg-byFsaB2pEhfdgil4 .node ellipse,#mermaid-svg-byFsaB2pEhfdgil4 .node polygon,#mermaid-svg-byFsaB2pEhfdgil4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-byFsaB2pEhfdgil4 .rough-node .label text,#mermaid-svg-byFsaB2pEhfdgil4 .node .label text,#mermaid-svg-byFsaB2pEhfdgil4 .image-shape .label,#mermaid-svg-byFsaB2pEhfdgil4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-byFsaB2pEhfdgil4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-byFsaB2pEhfdgil4 .rough-node .label,#mermaid-svg-byFsaB2pEhfdgil4 .node .label,#mermaid-svg-byFsaB2pEhfdgil4 .image-shape .label,#mermaid-svg-byFsaB2pEhfdgil4 .icon-shape .label{text-align:center;}#mermaid-svg-byFsaB2pEhfdgil4 .node.clickable{cursor:pointer;}#mermaid-svg-byFsaB2pEhfdgil4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-byFsaB2pEhfdgil4 .arrowheadPath{fill:#333333;}#mermaid-svg-byFsaB2pEhfdgil4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-byFsaB2pEhfdgil4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-byFsaB2pEhfdgil4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-byFsaB2pEhfdgil4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-byFsaB2pEhfdgil4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-byFsaB2pEhfdgil4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-byFsaB2pEhfdgil4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-byFsaB2pEhfdgil4 .cluster text{fill:#333;}#mermaid-svg-byFsaB2pEhfdgil4 .cluster span{color:#333;}#mermaid-svg-byFsaB2pEhfdgil4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-byFsaB2pEhfdgil4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-byFsaB2pEhfdgil4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-byFsaB2pEhfdgil4 .icon-shape,#mermaid-svg-byFsaB2pEhfdgil4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-byFsaB2pEhfdgil4 .icon-shape p,#mermaid-svg-byFsaB2pEhfdgil4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-byFsaB2pEhfdgil4 .icon-shape .label rect,#mermaid-svg-byFsaB2pEhfdgil4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-byFsaB2pEhfdgil4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-byFsaB2pEhfdgil4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-byFsaB2pEhfdgil4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    分组卷积 G=2

    输入 C_in 个通道

    分成 2 组,每组 C_in/2 通道

    组内独立卷积 K×K×C_in/2

    组间不混合

    输出 C_out 个通道

    一般卷积 G=1

    输入 C_in 个通道

    卷积核 K×K×C_in

    所有通道求和混合

    输出 C_out 个通道

    分组卷积在Pytorch中的实现如下:

    from torch.nn import Conv2d
    import torch

    image=torch.rand((1,4,256,256)) #构造一个假图像,维度分别是(B,C,W,H)
    #测试不同分组数下的输出尺寸和通道数
    group_conv1=Conv2d(in_channels=4,out_channels=8,kernel_size=3,stride=1,padding=1,groups=2)
    group_conv2=Conv2d(in_channels=4,out_channels=8,kernel_size=3,stride=1,padding=1,groups=4)
    y1=group_conv1(image)
    y2=group_conv2(image)
    y=[y1,y2]
    for yy in y:
    print(yy.shape)
    #输出
    '''
    torch.Size([1, 8, 256, 256])
    torch.Size([1, 8, 256, 256])
    '''

    分组卷积同样适用Conv2d类进行构建,只需设置groups参数即可。可以看到,当groups=2时,输入4个通道被分成2组,每组2个通道,每组分配4个卷积核,输出8个通道;当groups=4时,输入4个通道被分成4组,每组1个通道,每组分配2个卷积核,输出8个通道。注意,in_channels和out_channels都必须能被groups整除,否则会报错。

    7.3 分组卷积的参数量与计算量

    假设输入通道数为

    C

    i

    n

    C_{in}

    Cin,输出通道数为

    C

    o

    u

    t

    C_{out}

    Cout,卷积核尺寸为

    k

    ×

    k

    k \\times k

    k×k,分组数为

    G

    G

    G,则:

    • 参数量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      /

      G

      k \\times k \\times C_{in} \\times C_{out} / G

      k×k×Cin×Cout/G

    • 计算量:

      k

      ×

      k

      ×

      C

      i

      n

      ×

      C

      o

      u

      t

      ×

      H

      ×

      W

      /

      G

      k \\times k \\times C_{in} \\times C_{out} \\times H' \\times W' / G

      k×k×Cin×Cout×H×W/G

    其中

    H

    H'

    H

    W

    W'

    W 为输出特征图的尺寸。对比一般卷积的参数量

    k

    ×

    k

    ×

    C

    i

    n

    ×

    C

    o

    u

    t

    k \\times k \\times C_{in} \\times C_{out}

    k×k×Cin×Cout,分组卷积的参数量只有一般卷积的

    1

    /

    G

    1/G

    1/G,计算量也相应下降为一般卷积的

    1

    /

    G

    1/G

    1/G。这正是分组卷积的核心优势——通过分组在保持感受野不变的前提下,将参数量和计算量压缩到原来的

    1

    /

    G

    1/G

    1/G。当

    G

    =

    C

    i

    n

    G=C_{in}

    G=Cin 时,参数量变为

    k

    ×

    k

    ×

    C

    o

    u

    t

    k \\times k \\times C_{out}

    k×k×Cout,与逐深度卷积的结论一致。

    7.4 分组卷积的局限

    尽管分组卷积在参数量和计算量上优势明显,但它也存在一些不足:

    • 组间信息无法交互:由于每组独立卷积、互不混合,分组卷积无法利用不同组之间的通道相关性信息,可能损失部分表达能力;
    • 分组数需要精心设计:分组数

      G

      G

      G 的取值对模型效果影响较大,

      G

      G

      G 过大时组内通道数过少,特征表达能力下降;

      G

      G

      G 过小时参数量压缩有限,需要结合具体任务进行调优;

    • 对硬件实现不友好:分组卷积的组间计算相互独立,在部分硬件上难以充分利用并行计算资源,实际加速效果可能不如理论值。

    尽管存在上述局限,分组卷积凭借其显著的参数压缩能力,被广泛应用于 ResNeXt、MobileNet 等经典网络结构中,是轻量化卷积的重要设计手段之一。

    赞(0)
    未经允许不得转载:171主机测评 » 图解各种卷积层(一般卷积、逐深度卷积、逐点卷积、空洞卷积、不对称卷积、深度可分离卷积、分组卷积)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址