标准神经网络层,如 nn.Linear,将输入数据视为一个扁平向量。尽管功能强大,但这种方法未能内在理解图像等数据中存在的空间结构。对于图像来说,相互靠近的像素通常是关联的,它们构成边缘、纹理或物体的一部分。当直接应用于图像时,全连接层面临两个主要问题:参数效率低下: 将一张中等大小的图像(例如,224x224 像素,3 个颜色通道)展平为向量会导致输入维度非常大。即使将其连接到一个中等大小的隐藏层,也需要大量权重,使得模型容易过拟合,并且计算成本高昂。空间信息丢失: 展平图像会丢弃像素的 2D(或包含通道的 3D)排列。网络会丢失关于哪些像素最初是相邻的信息。卷积神经网络 (CNN) 是一种专门设计用于处理具有网格状拓扑数据(如图像(2D 网格)或时间序列数据(1D 网格))的神经网络。它们通过结合两个主要思想来解决标准网络的局限:局部感受野(通过卷积)和空间下采样(通过池化)。卷积操作:识别局部模式CNN 的核心组成部分是卷积层。卷积层不将每个输入单元连接到每个输出单元,而是使用小的过滤器(也称为核),它们在输入数据上滑动。每个过滤器都是一个小的权重矩阵。想象一个微小的放大镜(即过滤器)在输入图像上滑动。在每个位置,过滤器会与其当前覆盖的图像区域执行元素级乘法,并将结果求和以在输出中生成一个单一值。这个过程在整个输入图像上重复进行,生成一个输出特征图。digraph ConvolutionOp { bgcolor="white"; rankdir=TB; node [shape=rect, style=filled, fillcolor="#e9ecef", fontname="sans-serif"]; edge [fontname="sans-serif"]; subgraph cluster_input { label="输入区域"; bgcolor="#a5d8ff"; I1 [label=""]; I2 [label=""]; I3 [label=""]; I4 [label=""]; I5 [label=""]; I6 [label=""]; I7 [label=""]; I8 [label=""]; I9 [label=""]; } subgraph cluster_filter { label="过滤器(核)"; bgcolor="#ffc9c9"; F1 [label="w", shape=circle]; F2 [label="w", shape=circle]; F3 [label="w", shape=circle]; F4 [label="w", shape=circle]; } subgraph cluster_output { label="输出值"; bgcolor="#b2f2bb"; O [label="\u03a3(输入 \u00d7 过滤器)", shape=plaintext]; } F1 -> O; F2 -> O; F3 -> O; F4 -> O; } 过滤器对输入的局部区域施加权重,以计算输出特征图中的一个值。这种滑动过滤器方法具有两个显著优点:局部连接: 特征图中的每个单元仅连接到输入的一个小区域(过滤器大小)。这使得网络能够在早期层中学习到局部模式,如边缘或角落。参数共享: 相同的过滤器(具有相同的权重集合)在输入图像的不同位置重复使用。这与全连接层相比大幅减少了参数数量,并使网络对特征的平移具有等变性。如果一个模式(如垂直边缘)被过滤器学习,它可以在图像中任何位置检测到该模式。通常,一个卷积层会使用多个过滤器,每个过滤器学习识别不同类型的特征(例如,一个过滤器识别水平边缘,另一个识别垂直边缘,还有一个识别特定纹理)。这些过滤器的输出堆叠在一起,形成该层的最终输出体。PyTorch 主要通过 nn.Conv2d 层来实现图像数据的这一操作。激活函数就像在标准网络中一样,非线性激活函数(例如 ReLU,在 PyTorch 中实现为 nn.ReLU)通常在卷积操作之后进行元素级应用。这使得网络能够学习特征之间复杂的非线性关系。池化操作:下采样与不变性在通过卷积层检测到特征后,通常有益于使表示更紧凑并对小的空间变异具有抵抗力。这通过使用池化层来实现。最常见的类型是最大池化。它也涉及在特征图上滑动一个窗口(通常小于卷积过滤器且不重叠或带步幅)。但是,它不应用学习到的权重,而只是简单地取出该窗口内的最大值。digraph MaxPooling { bgcolor="white"; rankdir=LR; node [shape=plaintext, fontname="sans-serif"]; edge [fontname="sans-serif"]; subgraph cluster_input { label="特征图区域 (2x2)"; bgcolor="#a5d8ff"; FM1 [label="1"]; FM2 [label="5"]; FM3 [label="3"]; FM4 [label="2"]; } subgraph cluster_output { label="输出值"; bgcolor="#b2f2bb"; O [label="max(1, 5, 3, 2) = 5"]; } FM1 -> O; FM2 -> O; FM3 -> O; FM4 -> O; } 最大池化选择特征图局部窗口内的最大值。池化提供多项益处:维度降低: 它减少了特征图的空间维度(高度和宽度),降低了后续层的计算负担。平移不变性(局部): 通过用其最大激活来概括局部区域,池化使表示对特征在该区域内的确切位置更具稳定性。PyTorch 提供了 nn.MaxPool2d 等池化层。典型 CNN 架构一个典型的 CNN 架构通常会堆叠这些组件:一个或多个卷积 -> 激活 -> 池化层块。早期层倾向于使用较小的过滤器来捕捉精细细节,而后期层可能使用较大的过滤器,或依赖于早期层的池化特征来捕捉更大空间区域上的更复杂模式。在经过多个卷积和池化层之后,得到的特征图通常会展平为一个向量。然后,这个向量被馈入一个或多个全连接 (nn.Linear) 层,类似于标准前馈网络,用于最终的分类或回归。digraph CNN_Architecture { bgcolor="white"; rankdir=TB; node [shape=box, style=filled, fillcolor="#e9ecef", fontname="sans-serif"]; edge [fontname="sans-serif"]; Input [label="输入图像", fillcolor="#a5d8ff"]; Conv1 [label="Conv + ReLU", fillcolor="#96f2d7"]; Pool1 [label="MaxPool", fillcolor="#ffd8a8"]; Conv2 [label="Conv + ReLU", fillcolor="#96f2d7"]; Pool2 [label="MaxPool", fillcolor="#ffd8a8"]; Flatten [label="Flatten", fillcolor="#eebefa"]; FC1 [label="Linear + ReLU", fillcolor="#bac8ff"]; Output [label="输出(分数)", fillcolor="#ffc9c9"]; Input -> Conv1 -> Pool1 -> Conv2 -> Pool2 -> Flatten -> FC1 -> Output; }一个典型的 CNN 架构流程。CNN 运用卷积和池化,直接从网格状数据中自动学习特征的分层表示,这使得它们在图像识别、物体检测等任务中表现非常出色,甚至在文本得到适当表示时,也能用于自然语言处理。在下一节中,你将看到如何在 PyTorch 中实现像 nn.Conv2d 和 nn.MaxPool2d 这样的构建模块,以构建你的第一个 CNN。