跳转至

核心组件

卷积核、步长、填充(Padding)的作用与输出尺寸计算

image.png

  • 卷积核 (Kernel/Filter):卷积核是一个权重矩阵,在输入数据上滑动,对局部区域进行加权求和,以提取某种特征(如边缘、纹理)。每个卷积核学习一种特定的模式,多个卷积核构成一层,分别提取不同特征。卷积核的大小(如 3×3、5×5)决定了局部感受野的大小。

  • 步长 (Stride):卷积核滑动的步幅。步长越大,输出特征图在空间维度上缩小越快,计算量也越小,但可能丢失细节信息。通常步长为 1 时保留较多空间信息,步长为 2 常用于下采样。

  • 填充 (Padding):在输入特征图的四周添加额外像素(通常为零值),用于控制输出尺寸,并让边缘像素也能被充分利用。填充可以防止空间维度过快缩小,并允许边缘信息更好地参与卷积。

image.png

对于正方形输入、核和步长,公式相同。地板函数 ⌊⋅⌋表示当滑动窗口超出边界时停止(即舍弃最右侧和底部的不完整窗口)。如果不需要舍弃,PyTorch 中也支持“ceil_mode”,但默认是 floor。

举例:输入 32×32,核 3×3,步长 1,填充 1(即每边加 1 个像素),则输出为 (32+2-3)/1+1=32,尺寸不变。若步长 2,填充 0,则输出 (32-3)/2+1 = 15(向下取整),尺寸减半。


卷积为什么能捕捉局部特征?与全连接层相比的优势

捕捉局部特征的原理

卷积核每次只计算一个小的局部窗口(如 3×3 或 5×5)内的加权和,因此它直接编码“局部连接性”。图像和序列数据具有局部相关性(相邻像素、相邻词之间关系更紧密),卷积核学习到的权重正是对特定局部模式的检测器,比如边缘、角点、颜色斑点等。通过堆叠多个卷积层,浅层捕捉简单局部特征,深层则将这些局部特征组合成更大范围的全局模式。

与全连接层相比的优势

image.png

  • 平移等变性:卷积运算具有平移等变性质,即输入图像平移,输出特征图也相应平移。这使得模型能够识别出现在任意位置的同一特征,极大提升了泛化能力。全连接层没有这种性质。

  • 局部感受野:卷积强制神经元只关注局部区域,符合自然数据的局部结构先验,避免了全连接层学习不必要的全局连接。这种归纳偏置在数据有限时非常重要。

  • 计算高效:卷积可以通过矩阵乘法和 FFT 等快速算法实现,且现代硬件对其有极致优化。

因此,卷积比全连接层更适用于图像、音频等具有空间/时间结构的数据。


权值共享及其参数量节省

权值共享的概念

在卷积层中,同一个卷积核在整个输入特征图的不同位置上滑动,所有权重参数在所有位置共享。这意味着无论特征出现在输入的哪个位置,都使用相同的权重进行检测。不同于全连接层中每个输入-输出连接都有独立的参数,卷积层的参数集只限于核本身的元素。

体现

例如一个 3×3 的卷积核,滑动过 100×100 的输入,它只包含 9 个权重(以及 1 个偏置),而不是 10000×输出的全连接权重。

参数量节省的量化

image.png

  • 例如输入 224×224×3,输出 224×224×64,卷积核 3×3:参数量 = 3×3×3×64 = 1,728。若使用全连接,参数量将达到 224×224×3 × 224×224×64 ≈ 6.9×10^11,不可行。

权值共享极大地压缩了模型,使得深度卷积网络可以训练,并成为强大的正则化器。


Padding 的 “valid” 和 “same” 模式

  • "valid" 模式:等同于不填充(padding=0)。此时卷积核只在输入内部完整滑动,边界像素可能被忽略。输出尺寸会缩小,公式简化为 ⌊(W−K)/S⌋+1。这种模式会逐渐收缩空间维度,信息集中在中心区域。

  • "same" 模式:通过填充,使得输出空间尺寸与输入相同(当步长为 1 时)。通常需要根据步长和核大小计算需要的填充量。对于步长为 1 的情况,需要填充 P=(K−1)/2(如果 K 为奇数)。更一般地,为了保持尺寸,需要满足:

image.png

  • 但要求 SS 通常为 1 才行。如果 S>1S>1,无法保持精确相同尺寸。TensorFlow 中的 "same" 模式会自动计算填充以确保输出为 ⌈W/S⌉ 或 W/S 向上取整,并且会在右侧和底部多填充一些(非对称填充)。PyTorch 没有内置 "same" 字符串,需手动计算。

“same”下 padding 计算(常用情况) 对于步长为 1,希望输出尺寸等于输入尺寸,且卷积核为奇数边长 K,则单边填充P=⌊K/2⌋。例如 3×3 核,填充 1;5×5 核,填充 2。这保证了输出尺寸不变(假设 input 整除步长等)。

image.png


空洞卷积 (Dilated/Atrous Convolution) 的工作原理

空洞卷积在标准卷积核的元素之间插入空洞(即零值),从而在不增加参数数量的情况下,指数级地扩大感受野。

工作原理 设空洞率为 d(dilation rate),表示卷积核元素之间间隔 d−1 个零。例如,一个 3×3 卷积核,空洞率 d=2 时,实际的感受野覆盖范围相当于 5×5,但只有 9 个非零权重被学习(其余都是零且不可训练)。空洞率 d=1 就是标准卷积。

增大感受野而不增加参数 感受野(Receptive Field)是指输出特征图上每个像素点能够“看到”的输入区域大小。通过堆叠标准卷积,感受野随深度线性增长(每增加一层,感受野增加 K−1)。使用空洞卷积,可以在相同层数下获得指数级增长的感受野。例如,连续使用空洞率为 1,2,4 的卷积,感受野迅速扩大到 15×15(而参数数量仍然是 3×3 的规模)。这在语义分割、时序预测等任务中非常关键,既能捕捉长距离依赖,又不丢失分辨率或引入大量参数。

公式

image.png


转置卷积 (Transposed Convolution) 与棋盘效应

上采样原理 转置卷积并非正向卷积的逆运算,而是一种可学习的上采样方法。它将输入特征图的每个像素乘以一个卷积核,然后把结果按照步长“平铺”到输出特征图上,重叠区域相加。实际上,它等价于在输入像素之间插入 S−1 个零,然后进行标准卷积。这可以恢复更大的空间尺寸。

标准实现:输入尺寸 i,核大小 k,步长 s,填充 p,输出尺寸 o 满足:

image.png

这个公式刚好是正向卷积的输出公式反解 ii 得到。

棋盘效应 (Checkerboard Artifacts)

当转置卷积的步长大于 1,且卷积核大小不能被步长整除时,输出特征图的某些位置会比其他位置被更多次的核覆盖,导致亮度不均匀,呈现出棋盘格状的伪影。这是因为平铺叠加时,重叠区域的值被多次相加,而某些区域未被平等覆盖。

解决方案

  • 使用可以被步长整除的核大小(如步长 2 时,核大小 4×4 而非 3×3)。

  • 采用“先上采样(双线性插值或最近邻)再标准卷积”的策略,这样可以完全避免棋盘效应。

  • 在生成模型(如 GAN)中,常用 resize-convolution 替代转置卷积。


深度可分离卷积 (Depthwise Separable Convolution)

组成两步

深度可分离卷积将标准卷积分解为两个步骤:

  1. 深度卷积 (Depthwise Convolution):每个输入通道单独应用一个卷积核(即一个单通道滤波器),独立提取空间特征。若输入有 M 个通道,则有 M 个独立的二维卷积核(每个大小为 K×K)。这一步不进行跨通道的混合。

  2. 逐点卷积 (Pointwise Convolution):使用 1×1 卷积将深度卷积的输出通道进行线性组合,生成新的 N 个输出通道。这实现了跨通道的信息融合。

参数量和计算量节省

image.png

通常 N 较大,约为 1/N 的节省。例如 K=3,N=64,标准参数 576M,分离参数 9M+64M=73M,节省约 87%。计算量节省同理。

这种分解在 MobileNet 系列和 Xception 中广泛使用,极大降低了移动端模型的复杂度。


逐点卷积和深度卷积各自的作用

  • 深度卷积 (Depthwise Conv):独立处理每个输入通道,仅提取空间特征。它假设通道间的空间特征可以独立学习,不进行通道间的信息交互。由于每个通道使用自己的卷积核,参数量和计算量极低。但因为它不融合跨通道信息,所以输出通道数与输入相同,无法改变通道数量,且特征表达有限。

  • 逐点卷积 (Pointwise Conv,即 1×1 卷积):在通道方向上组合特征,相当于对每个像素位置进行全连接(通道间的线性变换)。它可以升维或降维通道数,引入非线性(配合激活),实现通道间信息融合。由于核大小为 1×1,没有空间上下文,计算量也很小。它在深度可分离卷积中负责将独立的空间特征组合成丰富的语义特征。

两者结合:深度卷积提取每个通道的空间模式,逐点卷积将这些模式加权组合,生成新的特征表示。这种设计在保持高表达力的同时,大幅减少了参数和计算。


可变形卷积 (Deformable Convolution)

image.png

可变形卷积显著提升了检测和分割模型对几何变换的建模能力,是 DCNv1、DCNv2 的核心创新点。


池化层的作用是什么?最大池化与平均池化的区别?

池化层(Pooling Layer)的作用

  • 降低空间分辨率,减小计算量:通过下采样减少特征图的高度和宽度,使得后续层的计算量和内存消耗大幅降低。

  • 增大感受野:经过池化后,同一层特征图上的一个像素能对应输入图像中更大的区域,有利于捕捉全局或更大范围的上下文信息。

  • 引入平移不变性:池化操作在局部区域对特征进行聚合,当输入特征发生微小位移时,池化输出变化不大,从而增强模型对位置变化的鲁棒性。尤其是最大池化,它对邻域内的精确位置不敏感。

  • 防止过拟合:通过降低空间维度和抽象层级,减少了参数数量和模型容量,具有一定的正则化效果。

最大池化(Max Pooling)与平均池化(Average Pooling)的区别

  • 操作方式:
  • 最大池化:取池化窗口内的最大值作为输出。
  • 平均池化:取窗口内所有值的平均值作为输出。

  • 特性差异:

  • 最大池化偏向于保留最显著的特征(纹理、边缘等尖锐激活),抑制了较弱信号,更适用于分类任务中提取强判别特征,因为它保留的是局部区域最强烈的模式响应。
  • 平均池化则平滑了整个区域,保留的是整体背景信息,减少极端值的影响,常用于过渡层或最后一层(全局平均池化)。在降低分辨率时,平均池化能减少估计方差,提供更平滑的特征。
  • 梯度传导:最大池化在反向传播时将梯度只传递给最大值的位置,其他位置为零;平均池化则将梯度平均分配给窗口内所有元素。

  • 典型使用场景:

  • 经典 CNN(如 AlexNet、VGG)常用最大池化进行下采样。
  • 平均池化常见于 GoogLeNet 的全局平均池化(GAP)或某些轻量级网络中,也用于 ResNet 的 transition 下采样(早期曾用)。

最大池化与平均池化的反向传播

最大池化的反向传播

对于最大池化,前向传播时需记录最大值的位置(索引)。反向传播时,上游梯度只传给这个最大值对应的位置,其他位置的梯度为零。这种方式相当于一个稀疏梯度路由:梯度只通过池化窗口内贡献最大的那个单元回传,其余神经元不获得更新信号。这有助于保留最强特征,但在某些情况下也可能导致信息丢失(梯度阻塞)。具体步骤:

  1. 保存最大值的位置掩码(argmax)。

  2. 将上游梯度张量按照掩码展开成与输入相同的形状,最大值位置置为对应梯度,其余为零。

平均池化的反向传播

image.png

实现细节(PyTorch) 框架会自动处理反向传播,只需使用 torch.nn.MaxPool2dtorch.nn.AvgPool2d 即可。对于最大池化,PyTorch 的 CUDA 实现高效利用了位置索引;对于平均池化,会按照窗口大小均匀分配。


Global Average Pooling (GAP) 替代 Flatten + 全连接的好处

Global Average Pooling 是对整个特征图的每个通道求均值,将 H×W×C的特征图变成 1×1×C 的向量,然后直接送入 softmax 分类器。

好处:

  • 大幅减少参数:传统 Flatten + 全连接层会产生巨大的权重矩阵(例如 7×7×512 的输入连接到 4096 个神经元,参数量约 102M),GAP 后直接接分类器,参数量仅为C × num_classes ,几乎没有额外参数,显著降低过拟合风险。

  • 空间信息整合更鲁棒:GAP 对空间位置做了全局平均,天然具有平移不变性,且对输入尺寸不敏感,可以接受任意大小的输入图像(因为最后特征图的尺寸可任意,均值池化后得到固定长度向量)。

  • 正则化效果:通过强制特征图每个通道的全局平均值直接对应一个类别置信度,鼓励每张特征图学习到代表某个类别的“存在性图”(即该类别对应的通道在物体出现区域有高激活),这样网络更有可解释性(类激活映射 CAM)。

  • 架构简洁:去除了庞大的全连接隐藏层,模型更轻量,代表性网络如 NIN、GoogLeNet、ResNet 均使用 GAP 作为分类头。

因此,在现代 CNN 设计中,GAP + 一个线性全连接层(或直接 softmax)几乎成为标准,完全取代了早年的重型 Flatten + 大 FC。


全连接层和 1×1 卷积层的关系,能否相互转化?

关系

  • 数学上,全连接层等价于对空间维度进行“全局”的卷积:如果输入特征图的尺寸恰好等于卷积核的尺寸,那么 1×1 卷积与全连接等价。更一般地,当卷积核的空间大小与输入的空间大小相同(即全局卷积)时,1×1 卷积实际上是对每个位置的全连接,但权重共享且缺乏空间交互。

image.png

实际转化

在 FCN 中,可以将训练好的分类网络的全连接层替换为等效卷积层,使网络能够接受任意尺寸输入并输出热图。例如,VGG 的 fc6 权重(4096×7×7×512)可重塑为 4096 个 7×7 的卷积核,步长 1,得到 1×1×4096 的输出;若输入变大,则输出更大空间的热图。这种转化使得全卷积网络适用于分割、检测等密集预测任务。

结论:1×1 卷积是逐位置的全连接,全连接是全局尺寸的卷积;它们可以相互转化,但语义场景不同。


CNN 中特征图通道数、高度、宽度在卷积和池化后的变化

  • 卷积层:

image.png

  • 1×1 卷积:空间尺寸不变(步长 1,填充 0),通道数可任意调整。

  • 全连接层:通常在最后,输入特征图被展平为向量,丢弃空间维度。加入 GAP 后则输出 1×1×C。

总结变化趋势

深度 CNN 中,随着层数加深,空间尺寸逐渐减小(通过步长卷积或池化),通道数逐渐增加(更丰富的语义特征)。这种设计使网络从局部细节过渡到全局抽象。


CNN 中卷积核大小的设置:小核堆叠 vs 大核

常用设置

绝大多数现代 CNN 使用 3×3 卷积 作为基本组件(如 VGG、ResNet),有些会结合 1×1、5×5,但大核(7×7 以上)通常仅在第一层或特定结构中出现。早期网络(如 AlexNet)使用较大的卷积核(11×11、5×5),但后来被小核堆叠取代。

小核堆叠的优势

image.png

  1. 更强的非线性:每个卷积层后通常跟随激活函数(如 ReLU),两个 3×3 层之间多了一个非线性变换,增强了模型的表达能力和决策函数的复杂性。一个 5×5 卷积只有一个激活层。

  2. 相同的感受野:两个 3×3 卷积的堆叠,其有效感受野等于一个 5×5 卷积。三个 3×3 卷积的感受野相当于一个 7×7 卷积。因此用小核可以获得与大核相同的感受野。

  3. 更高效的表示:堆叠小核构成的多层结构提供了更丰富的特征层次,底层可提取简单局部特征,高层组合为更复杂模式。大核容易引入过多的空间局部平滑,而小核堆叠得到的特征更加结构化。

第一层卷积往往使用较大的核(如 7×7,步长 2)以便迅速扩大感受野并减少计算量,这是出于计算和内存的实际考虑,但仍可替换为多个 3×3。

因此,主流架构几乎全部采用 3×3 小核堆叠,并辅以 1×1 卷积调节维度。


组卷积(Group Convolution)及其在 ResNeXt 中的使用

组卷积原理 标准卷积在输入的所有通道上进行滤波。组卷积将输入通道和卷积核分为 G 组,每组内的卷积核只处理对应组的输入通道,组与组之间没有信息交互。最后各组输出在通道维度上拼接。

image.png

在 ResNeXt 中的使用

ResNeXt 引入了“基数(cardinality)”的概念,实际上就是采用组卷积来构建残差块。它将 Inception 模块中“分割-变换-合并”的思路统一为使用相同拓扑的并行路径,每条路径执行一个低维的 1×1 卷积降维,再进行 3×3 组卷积(组数=基数),然后再用 1×1 卷积升维。通过调整基数(即组的数量),在保持总复杂度不变的情况下,可以增加模型的容量和准确性。ResNeXt 证明,增加基数比单纯增加深度或宽度能更有效地提升性能。

示例:ResNeXt-50 使用 32 组(基数=32),每个瓶颈块内 3×3 卷积的组数为 32,输入输出通道压缩为 4d,形成一个紧凑高效的多路结构。


1×1 卷积的作用:升降维、跨通道融合、增加非线性

1×1 卷积是核大小为 1×1 的卷积,它等价于在每个像素位置上对所有输入通道做一次线性变换。它的三大作用:

  • 升降维:通过设置输出通道数小于输入通道数,压缩特征图数量(降维),减少后续层的计算量;或相反增加通道数(升维)以增加特征丰富度。例如在 ResNet 的瓶颈结构中,先用 1×1 卷积将 256 通道降为 64,3×3 卷积处理后再升回 256。

  • 跨通道信息融合:1×1 卷积在全通道维度上做线性组合,相当于整合各通道的特征,实现了通道间的信息交换。这在深度可分离卷积中作为逐点卷积负责融合深度卷积提取的各通道独立空间特征。

  • 增加非线性:1×1 卷积后通常接激活函数(如 ReLU),在不改变空间尺寸的情况下为网络引入额外的非线性变换,增强了模型的表达能力。多个 1×1 卷积可以构成小型“多层感知机”作用于每个位置。

其他应用

  • 用于构建全卷积网络中的分类层(代替全连接)。

  • 在注意力机制中生成权重图(如 SE block 中的降维-升维操作使用 1×1 卷积)。

  • 在 DenseNet 中用作特征压缩。


在 PyTorch 中实现带有 Padding、Stride 的卷积并验证输出尺寸

代码实现:

import torch
import torch.nn as nn

# 定义卷积层
conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3,
                 stride=2, padding=1, bias=False)

# 创建示例输入(batch_size=1, 3通道, 高=32, 宽=32)
input_tensor = torch.randn(1, 3, 32, 32)

# 前向传播
output_tensor = conv(input_tensor)
print(f"输入尺寸: {input_tensor.shape}")
print(f"输出尺寸: {output_tensor.shape}")

# 手动计算验证
H_in, W_in = 32, 32
K = 3
S = 2
P = 1
H_out = (H_in + 2*P - K) // S + 1
W_out = (W_in + 2*P - K) // S + 1
print(f"预期输出尺寸: (1, 64, {H_out}, {W_out})")

输出将显示 torch.Size([1, 64, 16, 16]),与手动计算结果一致。

更复杂的验证:

  • 通过 torch.nn.functional.conv2d 直接操作,并比较结果与 nn.Conv2d 的输出是否一致。

  • 可使用 torchinfosummary 库显示每一层的尺寸变化。

常用技巧:

  • 设置 padding = kernel_size // 2stride=1 时输出尺寸与输入相同。

  • stride > 1 且需要精确尺寸控制时,可使用 nn.Conv2dpadding 参数或结合 nn.ZeroPad2d

此外,还可以自定义权重初始化,验证梯度流动,确保反向传播无误。

以上是对 CNN 中池化、全连接与卷积关系、组卷积、1×1 卷积等问题的全面解答。如果有任何希望进一步深入的主题,可以继续探讨。