彻底的了解Convolutional Layer
从零开始解释每一个图像识别系统背后的基础构件。
原作者:Jonathan Schlosser
引言
卷积神经网络(Convolutional Neural Networks, CNNs)是一类专门为处理图像、视频等视觉数据而设计的深度学习模型。从手机上的人脸检测,到医院中的医学图像诊断,几乎所有现代图像识别系统背后都离不开它们。
CNN 并不会把一张图像当作一串扁平的像素值列表来处理,而是能够理解图像中的空间结构。它们会有意识地学习检测边缘、纹理、形状,以及越来越复杂的模式。
本文将拆解 CNN 的核心构件:卷积层。我们会介绍卷积操作如何工作,它背后的数学公式,步幅与填充这两个关键参数,以及如何分别在 TensorFlow 和 PyTorch 中实现卷积层。本文的目标是让你清楚理解:当一张图像经过卷积层时,内部究竟发生了什么。这样,当你构建或使用 CNN 时,就能理解每一步到底在做什么。
**警告:**下面提供的代码是在特定环境中开发的。由于库的更新或变化,实际运行时可能需要做一些调整。

为什么全连接网络不适合处理图像
在深入卷积之前,我们需要先理解它要解决的问题。假设有一张 256×256 的彩色图像。它包含:
256 × 256 × 3 = 196,608 个输入值。
如果你把这些像素中的每一个都连接到第一个隐藏层中的 1,000 个神经元,那么仅仅这一层就需要 1.96 亿个参数。
这会带来三个问题:
计算成本,在第一层就拥有数亿参数的网络,训练起来在内存和计算时间上都极其昂贵。
过拟合,参数如此之多,而普通数据集的规模通常有限,网络很容易记住训练数据,而不是学到可以泛化的特征。你需要一个极其庞大的数据集,才能为这么多参数提供足够的训练信号。
没有空间意识,全连接层会把每个像素独立对待。它不知道相邻像素之间有关联,也不知道一组像素可以形成边缘,更不知道同一种边缘可能出现在图像中的任何位置。网络必须在每一个可能位置上,分别学习“垂直边缘长什么样”。
CNN 通过一个机制同时解决了这三个问题:卷积。
它不是把每个像素都连接到每个神经元,而是使用小型滤波器在图像上滑动,并在每个位置共享同一组权重。这大幅减少了参数数量,强制网络具有空间意识,并且让网络获得平移不变性。也就是说,网络能够识别某个特征,比如边缘或纹理,无论它出现在图像中的哪个位置。
CNN 如何模拟人类视觉
CNN 的设计在某种程度上受到人类视觉皮层的启发。
当你看一个场景时,你的大脑并不是同时处理每一个像素。视觉皮层中的不同神经元会响应视野中的不同区域,并且它们专门用于检测特定类型的模式:有些神经元响应垂直线条,有些响应水平线条,还有些响应特定方向或颜色。大脑通过组合这些简单检测,逐渐构建出复杂理解。
CNN 的工作方式类似。
早期层会学习检测简单特征,例如边缘和纹理。后续层会把这些简单特征组合起来,识别更复杂的模式:边缘组合成角,角组合成形状,形状组合成物体。这种层级化的特征提取,正是 CNN 架构最强大的能力之一。
卷积操作
卷积层是 CNN 的基础。它会把滤波器,也称为卷积核,应用到输入图像上,以检测边缘、纹理和各种模式等特征。
它是如何工作的
滤波器是一个小矩阵,通常大小为 3×3 或 5×5。它会在输入图像上滑动。在每一个位置,滤波器都会与图像中对应的区域进行逐元素相乘,然后把结果相加,得到一个单一数值。当滤波器滑过整张图像后,它会生成一个输出,这个输出被称为特征图。
在每个位置上的过程如下:
- 把滤波器放在输入图像的某个区域上。
- 将滤波器中的每个数值与对应的像素值相乘,也就是逐元素相乘。
- 把所有乘积加起来,得到一个数字。
- 加上一个偏置项。
- 将滤波器移动到下一个位置,然后重复上述过程。
一个用于检测垂直边缘的滤波器,会在图像中出现垂直边缘的位置产生较大的数值,而在其他位置产生接近于零的数值。最终得到的特征图,本质上就是一张“热力图”,显示该特定模式在输入图像中出现的位置。

数学表达
给定输入图像 (X) 和滤波器 (W),卷积操作在位置 ((i, j)) 上可以表示为:
其中:
- Y(i,j) 是输出特征图中位置 ((i,j)) 的值;
- W(m,n) 是卷积核,也就是滤波器;
- b 是偏置项;
- 求和会遍历滤波器的空间维度。
在每个位置,滤波器都会覆盖输入中对应的区域。每一对重叠的数值相乘,所有乘积相加,然后加上偏置。得到的单一数字表示:滤波器所代表的模式在该位置上出现的强度。
为什么卷积有效
卷积之所以特别适合图像处理,是因为它具有以下几个性质:
参数共享。
同一个滤波器权重会被用于图像中的每一个位置。一个 3×3 滤波器只有 9 个可学习参数,无论输入图像是 28×28 还是 1024×1024。这正是 CNN 比全连接网络参数效率高得多的原因。
局部连接。
每一个输出值只依赖输入中的一个小区域,也就是滤波器大小所覆盖的区域。这编码了一种假设:有用的特征通常是局部的。对于大多数视觉模式来说,这个假设是成立的。
平移不变性。
由于同一个滤波器会应用在所有位置,所以如果某个特征在图像的一个区域可以被检测出来,那么它出现在其他区域时,也能以同样方式被检测出来。网络不需要在每一个位置单独学习“垂直边缘是什么样”。
多个滤波器。
每个卷积层会同时应用多个滤波器,每个滤波器学习检测不同的特征。一个滤波器可能学习水平边缘,另一个可能学习角点,还有一个可能学习某种特定纹理。所有滤波器生成的特征图集合,构成了对输入图像的丰富表示。

image.png
实现
TensorFlow 和 PyTorch 都让卷积实现变得很直接。下面的示例会创建一张随机的 28×28 灰度图像,并将其传入一个包含 32 个滤波器的卷积层。
这两个框架之间有一个重要区别:维度顺序不同。TensorFlow 使用:
而 PyTorch 使用:
在两个框架之间切换时,这一点是常见 bug 来源。
TensorFlow / Keras
import tensorflow as tf
from keras.layers import Conv2D
import numpy as np
# Create a dummy image (1 sample, 28x28 pixels, 1 channel)
image = np.random.rand(1, 28, 28, 1).astype(np.float32)
# Apply a convolutional layer with 32 filters and a 3x3 kernel
conv_layer = Conv2D(filters=32, kernel_size=(3,3), strides=1, padding='same', activation=None)
# Apply the layer to the image
output = conv_layer(image)
print("Output Shape (TensorFlow):", output.shape)
输入的形状是:
(1, 28, 28, 1)
这表示:一张图像,尺寸为 28×28,1 个颜色通道,也就是灰度图像。
输出形状是:
(1, 28, 28, 32)
由于我们使用了 padding='same',所以空间维度保持为 28×28;而现在有了 32 个通道,每个通道对应一个滤波器生成的特征图。
关键参数如下:
filters=32:要应用的不同滤波器数量,每个滤波器都会学习检测不同特征;kernel_size=(3,3):每个滤波器是一个 3×3 矩阵;strides=1:滤波器每次移动一个像素;padding='same':在边界周围添加零,使输出的空间尺寸与输入一致。
PyTorch
import torch
import torch.nn as nn
# Create a dummy image (1 sample, 1 channel, 28x28 pixels)
image = torch.rand(1, 1, 28, 28)
# Define a convolutional layer with 32 filters and a 3x3 kernel
conv_layer = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1)
# Apply the layer to the image
output = conv_layer(image)
print("Output Shape (PyTorch):", output.shape)
PyTorch 版本通过 in_channels=1 和 out_channels=32 明确写出了通道维度。对于 3×3 卷积核来说,padding=1 可以达到与 TensorFlow 中 "same" padding 相同的效果。
注意,PyTorch 的输出形状会把通道维度放在空间维度之前,这是 PyTorch 的惯例。
步幅与填充
【图片:按回车或点击可全屏查看】
有两个参数控制滤波器如何在图像上移动,以及如何处理边缘:步幅和填充。理解这两个参数,对于预测输出维度和设计 CNN 架构非常重要。
步幅
步幅定义了滤波器每一步跳过多少个像素。
步幅为 1:
滤波器每次移动一个像素。这是默认设置,也会产生最细致的输出,因为没有跳过任何位置。
步幅为 2:
滤波器每次移动两个像素,相当于跳过每隔一个位置。这会让输出尺寸在每个维度上大约减半。步幅 2 有时会作为池化层的替代方案,用于下采样,因为它的计算成本更低。
步幅的选择会直接影响输出维度。更大的步幅会产生更小的输出。这对于减少后续层的计算量很有用,但代价是会损失空间分辨率。

填充
填充是在输入图像边缘周围添加额外像素,通常是零,然后再执行卷积。没有填充时,滤波器无法以边缘像素为中心进行卷积,因此输出会比输入更小。
常见的填充策略有两种:
Valid Padding:不填充
不添加额外像素。由于滤波器只能放在完全位于图像内部的位置上,所以输出尺寸会小于输入尺寸。
输出大小为:
其中:
- (N) 是输入大小;
- (F) 是滤波器大小;
- (S) 是步幅。
例如,对于一个 28×28 的输入,使用 3×3 滤波器和步幅 1:
(28 - 3) / 1 + 1 = 26
也就是说,每个维度都会损失两个像素。
Same Padding:零填充
在边界周围添加零,使输出拥有与输入相同的空间维度,当步幅为 1 时尤其如此。这是现代架构中最常见的选择,因为它可以防止特征图在每一层都不断缩小。
Same padding 下的输出大小为:
如果没有 same padding,一个拥有很多卷积层的网络会让空间维度不断缩小。经过足够多层后,特征图会变得非常小。Same padding 可以防止这种情况,从而让架构设计者在网络设计上拥有更大灵活性。
常见参数选择
在实践中,大多数 CNN 架构会使用一组相对稳定的参数选择:

关于堆叠小滤波器的洞见值得特别强调。
一个 5×5 滤波器有 25 个参数。两个 3×3 滤波器总共有 18 个参数,却可以覆盖相同的空间范围。而且,由于两层之间通常会加入非线性激活函数,这种两层组合拥有更强的表达能力。
这就是为什么 3×3 滤波器主导了现代 CNN 架构。这个设计原则由 VGGNet 确立。

特征图与层级化特征学习
当一个包含 32 个滤波器的卷积层处理输入图像时,它会生成 32 张特征图。每张特征图都是一个滤波器扫描整张图像后的结果,用来突出显示该滤波器所对应的模式出现在哪里。

在一个训练完成的 CNN 中,网络不同深度上的特征图会显示不同抽象层级的内容:
早期层,靠近输入层:
学习简单的低级特征,例如不同方向的边缘、颜色梯度和基础纹理。
中间层:
把低级特征组合成更复杂的模式,例如角点、曲线、简单形状和重复纹理。
后期层,靠近输出层:
检测高级语义特征,例如眼睛、车轮、窗户,或者其他物体部件。
这种层级化特征学习会在训练过程中自动发生。网络通过反向传播发现:某些低级特征组合对于检测更高级模式是有用的,而这些高级模式又有助于最终分类任务。整个过程不需要手工特征工程。
每一层中滤波器的数量,控制了网络在该层能够检测的“特征词汇量”。早期层通常使用较少滤波器,例如 32 或 64 个;后期层则使用更多滤波器,例如 256 或 512 个。原因是高级特征比低级特征更加多样,也更加复杂。
局限性与现实期待
卷积是局部操作。每一个输出值只依赖输入中的一个小块区域,这个区域由滤波器大小决定。图像中相距较远部分的信息,只有在经过多层之后才能相互作用。
对于那些需要全局上下文的任务,例如理解整体场景布局,可能还需要更大的感受野、注意力机制或全局池化等额外机制。
滤波器大小是一种权衡。较小的滤波器,例如 3×3,更节省参数,并且可以通过堆叠来获得更大的感受野,但它们需要更多层。较大的滤波器,例如 5×5 或 7×7,可以在单次操作中捕捉更多上下文,但参数更多。现代共识更倾向于使用小滤波器和更多层。
卷积操作假设平移不变性。也就是说,同一个滤波器会被应用到所有位置。这对于边缘、纹理等可以出现在任意位置的特征非常有效。但某些任务需要依赖位置的处理方式,而单靠卷积无法提供这种能力。
CNN 需要精心设计架构。滤波器数量、层的排列方式、是否加入池化层和归一化层,都会显著影响性能。卷积层是基本构件,但这些构件如何组合,同样极其重要。
结论
卷积层是每一个 CNN 的核心构件。它通过让小滤波器在输入图像上滑动,计算逐元素乘积并求和,从而生成特征图。这些特征图会突出显示特定模式出现的位置。
通过参数共享和局部连接,卷积相比全连接层获得了巨大的效率提升,同时也把空间结构编码进网络设计之中。
滤波器大小、步幅和填充等关键参数,控制着卷积如何执行,并决定输出维度。现代共识倾向于使用 3×3 滤波器、same padding 和步幅 1,依靠网络深度,也就是更多层,而不是大型滤波器,来增加网络的感受野。
理解单个卷积层如何工作,是理解完整 CNN 架构的基础。在下一篇文章中,我们将考察卷积层如何与池化层、归一化层以及其他组件组合起来,构建 LeNet、AlexNet、VGG 和 ResNet 等架构。
如果你喜欢这篇文章,欢迎继续关注我的写作,也欢迎在 LinkedIn 上与我联系!
谢谢大家,祝编码愉快!
资源
- Deep Learning Book, Chapter 9: Convolutional Networks,Goodfellow, Bengio, Courville
- Very Deep Convolutional Networks for Large-Scale Image Recognition,Simonyan & Zisserman, 2014
- A Guide to Convolution Arithmetic for Deep Learning,Dumoulin & Visin, 2016
作者简介
Jonathan Schlosser 是一名 AI 工程师、教育者,也是 Outerspacd 的创始人。他目前参与 UNC Chapel Hill 数据科学硕士项目,并曾通过 Correlation One、Amazon、Google 等项目教授过数百名数据科学专业人士。
他在数据和 AI 领域拥有 10 多年经验,从数据科学岗位到构建 AI 驱动应用都有涉猎。他的写作主题包括深度学习、大语言模型和 AI 智能体,风格直接、简化,偏重教学说明。