Skip to content

s10 CNN 核心原理:卷积与感受野

WARNING

🧪 Beta公测版本提示:教程主体已完成,正在优化细节,欢迎大家提Issue反馈问题或建议。

从零理解卷积操作 —— 为什么卷积神经网络能"看懂"图像。卷积层问的不是「这张图整体乘一个大矩阵」,而是「同一把小尺子,在每个位置量一遍局部」。本章把滑动求和写成公式,再用一个必须手算的 3×3 数字例对上 padding、stride、感受野。架构怎么堆见 经典架构;检测头见 目标检测;把图切成 patch 见 ViT

本章阅读方式:正文先给结论公式和一张图;需要逐步代数时点开灰色的「逐步推导」。建议第一遍只读正文和数字例,卡在某一行再展开。


一、为什么用卷积处理图像?

传统的全连接神经网络处理图像时,面临两个根本问题。假设一张 32×32 的 RGB 图像,输入维度为 32×32×3=3072。如果第一层有 1000 个神经元,那么权重矩阵的大小就是 1000×3072300 万个参数。这仅仅是一层,而且对于稍微大一点的图像(如 224×224×3=150528),参数量会暴涨到上亿级别,根本无法训练。

然而,卷积操作天然地利用了图像的三个重要先验,完美解决了这些问题:

1. 平移不变性(Translation Invariance)

一只猫出现在图像的左上角还是右下角,它都是猫。卷积核在图像上滑动,无论目标移动到哪个位置,同一个卷积核都能检测到它。这是卷积的核心设计理念——权值共享:一个 3×3 的卷积核只有 9 个参数,但它被应用在图像的所有位置。

2. 局部连接(Local Connectivity)

图像中相距较远的像素之间通常没有直接的语义关联。一个边缘检测器只需要看局部的 3×35×5 区域,不需要看全图。卷积的局部感受野正是对这一现象的建模。

3. 参数共享(Parameter Sharing)

同一个特征(如"水平边缘")可能在图像的任意位置出现。卷积核在整个图像上共享权重,使得检测"水平边缘"只需要学一组参数,而非为每个位置单独学习。

一句话总结:卷积层将全连接层的 O(H2W2) 参数量降到了 O(K2CinCout),其中 K 是卷积核大小(通常 3 或 5),与输入尺寸无关。

卷积操作详解——滑动计算过程

图解说明:卷积核盖在输入的一小块上,逐元素相乘再求和,得到输出的一个像素;然后向右(再向下)滑动。同一组 9 个数在全图共享——这就是权值共享。

保姆级参数量对比。 输入 32×32×3,第一层若输出 32 通道、3×3 核、有偏置:

Params=32×3×3×3+32=896.

若改成全连接、输出仍想保持 32×32×32 个位置,权重是 3072×(323232),大约 一亿 量级。卷积把「每个输出位置各学一套」改成「全图共用一套」,差的就是这个 HoutWout 倍。


二、卷积操作:从数学到直观

2.1 二维卷积的数学定义

给定输入图像 XRH×W 和卷积核 KRk×k,输出特征图 Y 在位置 (i,j) 的值定义为:

Y[i,j]=m=0k1n=0k1X[i+m,j+n]K[m,n]+b

其中 b 是偏置项。深度学习框架里的「卷积」多数是不翻转核的互相关;学核时翻转与否只是把学到的 K 整体转 180,表达力相同。下文按框架习惯,直接写互相关。

逐步推导:一个 3×3 核在 4×4 图上怎样滑出 2×2(点击展开)

取输入(无 padding、stride=1)

X=(1230012330122301),K=(101101101).

这个 K 是竖直边缘探测器:左边减右边。盖在左上角:

Y[0,0]=11+20+3(1)+01+10+2(1)+31+00+1(1)=1+03+0+02+3+01=2.

向右滑一格,窗口变成第 0–2 行、第 1–3 列:

Y[0,1]=2+00+1+03+0+02=2.

再往下、再往右,得到 2×2Y。输出高宽 =43+1=2,正是 VALID 公式。若四周 pad 一圈 0(SAME),窗口还能对准原图边缘像素,输出变回 4×4

偏置 b 加在每一个输出位置上,不随 (i,j) 变——它是「这张特征图整体亮一点还是暗一点」,不是每个位置各一个 b

2.2 直观理解:滑动窗口

卷积核就像一个"探测器",在输入图像上从左到右、从上到下滑动。每次停在一个位置,就做一次逐元素乘法再求和

  1. 3×3 的卷积核"盖"在图像的 3×3 区域上
  2. 对应位置的 9 对数字相乘
  3. 把 9 个乘积加起来,得到输出特征图上的一个像素值
  4. 卷积核向右滑动一格(步长),重复以上过程

这个过程类似于信号处理中的互相关(Cross-Correlation)操作——深度学习中的"卷积"严格来说是互相关,因为卷积核没有翻转。但在实际使用中,大家统一称之为卷积。

卷积 vs 全连接——参数量对比

图解说明:全连接每个输出连全体输入;卷积只连核盖住的那一块,且各位置共用同一核。参数从「跟像素数平方走」变成「只跟核大小和通道数走」。


三、Padding、Stride 与输出尺寸

3.1 Padding(填充)

如果不做 padding,每次卷积都会使输出尺寸缩小。对于 H×W 的输入和 k×k 的卷积核:

  • VALID padding(无填充):输出尺寸为 (Hk+1)×(Wk+1)
  • SAME padding(等尺寸):在输入边缘填充 P=k/2 圈零值,使得输出尺寸与输入相同:H×W

SAME padding 的命名非常直观——输入输出保持相同尺寸。对于 3×3 卷积核,需要在四周各填充 1 个像素(P=1);对于 5×5 卷积核,需要填充 P=2

3.2 Stride(步长)

步长 S 控制卷积核每次滑动的距离。S=1 时卷积核每次移动一个像素,S=2 时每次移动两个像素,输出尺寸减半。

3.3 Dilation(空洞卷积)

空洞卷积通过在卷积核元素之间插入"空洞"(零值)来扩大感受野,而不增加参数数量。对于 dilation rate d,有效卷积核大小为 (k1)d+1

通用输出尺寸公式:对于输入尺寸 W、卷积核大小 k、padding P、stride S、dilation d

Wout=W+2Pd(k1)1S+1

d=1 时退化为标准形式:

Wout=W+2PkS+1

Padding 与 Stride —— 输出尺寸控制

图解说明:左是 VALID,边缘像素当不了窗口中心,图会缩;中是 SAME,补零让输出对齐输入;右是 stride=2,窗口跳着走,分辨率大约减半。

逐步推导:输出尺寸公式每一项在数格子(点击展开)

把核的左上角能放在哪些整数位置,数一遍。输入宽 W,左右各 pad P,有效宽度变成 W+2P。核宽 k,dilation d 时核真正跨过的格数是 d(k1)+1(两个端点之间插入 d1 个空洞)。左上角最右能放到下标 W+2Pd(k1)1。从 0 起每隔 S 放一次,能放的次数是

W+2Pd(k1)1S+1.

数字例。 W=8k=3P=1S=2d=1

Wout=8+232+1=3.5+1=4.

SAME 的直觉是 S=1 时希望 Wout=W,于是 2Pk+1=0,即 P=k/2k 为偶数时左右 pad 不对称,框架会按约定把多出来的 1 格分到一边——读文档时不要假设「四周一定一样多」。

空洞卷积:k=3,d=2 的有效跨度是 5,感受野变大、参数仍是 9 个。语义分割常用它在不降分辨率的前提下看更远。


四、池化(Pooling):降维与不变性

池化层不包含可学习的参数,它通过固定的下采样操作缩小特征图的尺寸。

4.1 最大池化(Max Pooling)

k×k 窗口内取最大值。最大池化保留了"最显著的特征是否出现"这一信息,而忽略其精确位置。

输入 2×2 区域:        最大池化输出:
[1, 3]                  9
[7, 9]

4.2 平均池化(Average Pooling)

k×k 窗口内取平均值。平均池化保留了区域内的整体强度信息,对噪声更鲁棒,但会模糊显著特征。

4.3 池化的作用

  1. 降维2×2 池化(stride=2)将特征图尺寸减半,减少后续层的计算量
  2. 平移不变性:输入微小平移时,池化后的输出可能完全不变——这有助于分类任务的鲁棒性
  3. 增大感受野:不需要增加卷积核大小,就能让深层神经元看到更大的输入区域

五、感受野(Receptive Field)

5.1 什么是感受野?

在 CNN 中,某一层特征图上的一个神经元的值,由输入图像上的某一区域决定。这个区域就是该神经元的感受野

  • 第 1 层(3×3 卷积):每个神经元看到输入图像的 3×3 区域
  • 第 2 层(再做一个 3×3 卷积):每个神经元看到输入图像的 5×5 区域
  • 第 3 层:感受野扩大到 7×7

5.2 感受野的递推公式

设第 l 层的卷积核大小为 kl,步长为 s1,s2,...,sl。第 l 层神经元在原图上的感受野大小 RFl 递推如下:

RFl=RFl1+(kl1)×i=1l1si

其中 RF0=1

直觉:每加一层卷积,感受野以 (k1) 为步长线性增长(在原始图像尺度上)。而池化的步长会加速感受野的扩张——一个 2×2 池化(stride=2)会直接使感受野翻倍。

逐步推导:两层 3×3s=1 为什么感受野是 5(点击展开)

第 0 层把每个输入像素看成感受野 1。第一层 k=3,s=1:输出一个位置看输入 3 格,

RF1=1+(31)×1=3.

第二层再做一个 3×3。它看的是第一层上相邻 3 个位置。第一层相邻位置在原图上错开的步长等于第一层 stride 的乘积(这里是 1),所以多看 (31)×1=2 格:

RF2=3+2=5.

若中间插入 2×2 池化、s=2,乘积里多一个 2,后面每加一层 3×3 就在原图上多跨 2×2=4 格,感受野涨得快。这就是「池化不只是降维,还在加速视野扩张」。

VGG 用两个 3×3 替代一个 5×5:感受野同为 5,参数 2×9=1825,中间还多一次 ReLU。非线性次数增加,拟合弯曲边界更便宜。

5.3 感受野为什么重要?

  • 分类任务:高层神经元需要足够大的感受野来覆盖整个目标物体
  • 语义分割:需要同时拥有大感受野(全局上下文)和小感受野(精细边界)
  • 目标检测:需要在不同尺度上检测不同大小的目标

小卷积核堆叠 vs 大卷积核:两个 3×3 卷积(感受野 5×5,参数 18)可以替代一个 5×5 卷积(感受野 5×5,参数 25),且非线性更强。这就是 VGG 的设计哲学。

感受野增长——CNN 逐层视野扩展

图解说明:浅层一个点只看见边缘小窗;堆层之后,同一个点对应原图上一块越来越大的区域。分类要这块盖住物体;分割还要浅层的小窗来保边缘。


六、多通道卷积

真实图像有多个通道(如 RGB 三通道),而 CNN 的每一层也会输出多个特征图(多个通道)。

6.1 输入通道→输出通道

一个卷积层的卷积核是 3D 的:形状为 (Cout,Cin,k,k)

对于第 j 个输出通道 (j=1,...,Cout)

Y[j,:,:]=c=0Cin1XcKj,c+bj

符号 表示 2D 卷积。这意味着每个输出通道是所有输入通道的卷积结果之和——卷积核在空间维度上是 2D 的,在通道维度上做了一次全连接。

换句话说,一个 Cin 通道的输入经过 Cout 个卷积核后,产生 Cout 个通道的输出。每个卷积核需要处理所有 Cin 个输入通道。

6.2 1×1 卷积(Pointwise Convolution)

1×1 卷积是一个特殊但极其重要的操作。它在空间上不做任何聚合(只看一个像素),但会混合所有输入通道:

Y[j,:,:]=c=0Cin1Wj,cXc+bj

1×1 卷积的三个关键用途:

  1. 通道降维/升维:将 256 通道的输入降到 64 通道,大幅减少后续 3×3 卷积的计算量
  2. 跨通道信息融合:在每个空间位置上独立地混合通道信息,等价于逐像素的全连接
  3. 增加非线性1×1 Conv + ReLU 相当于在不增加感受野的情况下增加网络的表达能力

这是 GoogLeNet Inception 模块和 ResNet Bottleneck 设计的核心工具。


七、卷积层的计算量与参数量

对于一个卷积层,设输入大小为 (Cin,H,W),输出大小为 (Cout,Hout,Wout),卷积核大小为 k×k

参数量

Params=Cout×Cin×k×k+Cout

最后的 +Cout 是偏置项。

计算量(FLOPs)

每次卷积有 k2 次乘法(和一次加法),每个输出位置都要做一次,共 Cout×Cin×Hout×Wout 个位置:

FLOPs2×Cout×Cin×k2×Hout×Wout

因子 2 是因为每次乘法通常伴随一次加法(Multiply-Add 算一次)。

对比全连接层:假设输入为 Cin×H×W 的展开向量,全连接到 Cout×Hout×Wout 需要约 CinCoutHWHoutWout 个参数——是卷积层的 HoutWout 倍。对于 32×32 的输入,这个倍数轻松达到成百上千。


八、Im2Col:卷积的矩阵乘法实现

在底层实现中,卷积通常被转化为矩阵乘法(GEMM)来利用 GPU 的并行计算能力。这个转化过程叫做 im2col(image to column):

  1. 提取输入中每一个"将被卷积核覆盖的小块"(patches),每个 patch 的大小是 Cin×k×k
  2. 将所有 patches 排列成一个矩阵 X~,形状为 (Hout×Wout,Cin×k×k)
  3. 将卷积核展开成矩阵 K~,形状为 (Cin×k×k,Cout)
  4. 做一次矩阵乘法:Y~=X~K~,再 reshape 为输出形状 (Cout,Hout,Wout)

这就是为什么现代深度学习框架中的卷积操作能跑得这么快——底层调用的是高度优化的 GEMM 库(如 cuBLAS、MKL)。

保姆级形状账。 Cin=3k=3Hout=Wout=30Cout=16:每个 patch 长 333=27,共 30×30=900 个 patch,于是 X~900×27K~27×16。一次 GEMM 代替了四重循环。代价是 X~ 把重叠窗口各拷一份,吃内存;Winograd、FFT 卷积是另一类加速,小核时 Winograd 更常见。

池化不是卷积:没有可学核,只在窗口里取 max 或 mean。反向时 max 只把梯度送给窗口里那个最大的位置;average 则把梯度均分。这就是「最大池化保留最显著特征」在实现上的含义。


九、本节小结

概念一句话
卷积的动机利用图像的平移不变性、局部连接和参数共享,大幅降低参数量
卷积操作卷积核在输入上滑动,每次做逐元素乘法再求和
Padding在输入边缘填零,控制输出尺寸(VALID 无填充,SAME 保持尺寸)
Stride卷积核滑动步长,控制下采样程度
池化无参数的下采样(最大池化保留显著特征,平均池化保留整体信息)
感受野深层神经元对应到原始输入上的区域大小,随层数单调增长
多通道Cin 输入 × Cout 个 3D 卷积核 → Cout 输出通道
1×1 卷积逐像素的跨通道线性混合,用于升降维和通道交互
计算量O(CinCoutk2HoutWout),与输出分辨率成正比

下一节 s11 经典架构演进 将展示这些基本组件如何被组装成 LeNet、AlexNet、VGG、ResNet 等里程碑式的网络架构,以及它们各自的创新点在哪里。量子机器学习里也常用卷积或全连接先压缩图像,再写进线路,见 量子机器学习

📥 Code

FileViewDownload
demo.pyOpenDownload
exercise.pyOpenDownload

参考

  1. LeCun, Y., Bottou, L., Bengio, Y., & Haffner, P. (1998). Gradient-Based Learning Applied to Document Recognition. Proceedings of the IEEE. (LeNet-5) [doi:10.1109/5.726791]
  2. Fukushima, K. (1980). Neocognitron: A Self-organizing Neural Network Model for a Mechanism of Pattern Recognition. Biological Cybernetics. (CNN 前身)