HelloAI
L3 第 6 篇 🐣 难度 🕒 15 分钟

CNN 卷积原理:从滤镜到 ResNet

在 Transformer 称霸前,CNN 是计算机视觉的统治者。它今天仍然是处理图像的标配。这一篇讲清楚"卷积"到底是什么。

阿莱
2026/6/16

L0-02 我们讲过:2012 年 AlexNet 用 8 层卷积网络在 ImageNet 比赛上把错误率砍掉一半,引爆了深度学习革命。

那是 CNN(卷积神经网络) 的高光时刻。今天虽然 Transformer 在很多领域抢了风头,但处理图像,CNN 仍然是标配——因为它的归纳偏好(inductive bias)天生适合视觉。

这一篇把 CNN 的核心—— 卷积 ——讲清楚。

🎮 建议先去 CNN 卷积扫描可视化 玩 5 分钟。亲手拖几个 kernel 看效果,比读 1000 字都有用。

第一站:为什么不能用全连接处理图像

最朴素的神经网络叫 全连接(Fully Connected, FC)——每个输入和每个输出都连接。

但用 FC 处理图像有三个致命问题:

问题 1:参数量爆炸

一张 224×224 的彩色图片有 224×224×3=150,528224 \times 224 \times 3 = 150{,}528 个像素。 如果第一层有 1000 个神经元——参数数量 = 150,528×10001.5150{,}528 \times 1000 ≈ 1.5 亿。

仅一层!

问题 2:丢失”局部性”

图像的关键信息是局部的——猫的耳朵在某一小块区域里。 FC 把所有像素一视同仁,把局部结构信息全打散了。

问题 3:不具有”平移不变性”

猫在图片左上还是右下,对识别”是不是猫”应该没影响。但 FC 学到的是”左上像素 0 怎样” + “左上像素 1 怎样”——位置敏感,学了猫在左上认不出右下的猫。

CNN 完美解决这三个问题——靠的是卷积

第二站:卷积是什么

如果你做过照片滤镜调整(PS、Lightroom、Snapseed),你已经用过卷积了。

卷积 = 一个小窗口(kernel)在图像上滑动,每个位置算一个数

最简单的例子:模糊滤镜

输入图像:

[1001005050100100505020202002002020200200]\begin{bmatrix} 100 & 100 & 50 & 50 \\ 100 & 100 & 50 & 50 \\ 20 & 20 & 200 & 200 \\ 20 & 20 & 200 & 200 \end{bmatrix}

模糊 kernel(3×3 平均):

19[111111111]\frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}

操作:让 kernel 在图像上滑动,每个位置做”元素相乘再求和”。例如算左上角输出:

100+100+50+100+100+50+20+20+200982.2\frac{100+100+50 + 100+100+50 + 20+20+200}{9} ≈ 82.2

最终输出比输入平滑(模糊)。

这就是卷积。

第三站:不同的 kernel = 不同的”过滤器”

让我们看几个经典 kernel:

水平边缘检测(Sobel-Y)

[121000121]\begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix}

直觉:上面减下面——如果图像在垂直方向有强烈变化(亮→暗),结果就大。找的是水平方向的边

垂直边缘检测(Sobel-X)

[101202101]\begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix}

类似道理,找的是垂直方向的边。

锐化

[010151010]\begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix}

中心 ×5,邻居 ×-1——增强中心和邻居的差异,让边缘”跳出来”。

模糊

19[111111111]\frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}

平均了 3×3 邻居,让图像变平滑。

这些 kernel 在传统图像处理里都是手工设计的

第四站:CNN 的革命——让 kernel 自己学

CNN 的关键洞察:

kernel 里的数,不用人写——让模型从数据里学出来。

数学上:把 kernel 也当成可训练参数,用梯度下降优化。

  • 一层 CNN 通常有几十个 kernel
  • 每个 kernel 学到一种不同的”特征检测器”
  • 浅层学边缘、纹理;深层学眼睛、脸、车轮等

一个完整 CNN 层的伪代码

import torch.nn as nn

class CNNBlock(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        # 卷积层:64 个 3×3 kernel
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)
        # 激活函数
        self.relu = nn.ReLU()
        # Pooling 减小尺寸
        self.pool = nn.MaxPool2d(2)

    def forward(self, x):
        x = self.conv(x)   # 卷积
        x = self.relu(x)   # 非线性
        x = self.pool(x)   # 池化
        return x

这就是 CNN 的”积木”

第五站:CNN 解决了 FC 的三个问题

✅ 参数量爆炸 → 参数共享

一个 3×3 kernel 只有 9 个参数。它在整张图上滑动——所有位置共享这 9 个参数。

CNN 一层的参数 = n_kernels × 9 + bias——比 FC 少几千倍。

✅ 局部性 → 卷积天然只看局部

每个输出位置只看附近 3×3 区域。局部信息被精准捕获。

✅ 平移不变性 → 同一个 kernel 用在所有位置

学到的特征不依赖位置——“耳朵 kernel”无论扫到图像哪里都能识别耳朵。

💡 CNN 的核心洞察

CNN = 卷积 + 参数共享 + 平移不变性。 这三点让它特别适合”有局部结构 + 位置无关”的数据——典型就是图像。

第六站:CNN 的标准积木

一个真实 CNN 通常长这样:

输入图像 (3×224×224)
    ↓ [Conv 64个 3×3] → 64×224×224
    ↓ [ReLU + Pool 2×2] → 64×112×112
    ↓ [Conv 128个 3×3] → 128×112×112
    ↓ [ReLU + Pool 2×2] → 128×56×56
    ↓ [Conv 256个 3×3] → 256×56×56
    ↓ [ReLU + Pool 2×2] → 256×28×28
    ↓ ... (更多层)
    ↓ [Flatten] → 一个长向量
    ↓ [Fully Connected] → 1000 类的概率分布

每层逐渐”看”得更广(尽管 kernel 小,但因为是堆叠,深层每个神经元的”感受野”很大)。

几个重要概念

Padding:在图像边缘补 0,让卷积后大小不变。 Stride:kernel 滑动步长(默认 1,2 就是隔一个滑)。 Pooling:把 2×2 区域压缩成 1 个数(取最大值或平均),把图像尺寸缩小一半。 Channel:彩色图像有 RGB 3 个通道,每个通道独立卷积,然后求和。

第七站:经典 CNN 架构演化

LeNet (1998) - CNN 的祖宗

LeCun 设计的 5 层 CNN,用于手写数字识别。

AlexNet (2012) - 引爆深度学习

8 层。证明了”深度学习真行”。

VGG (2014) - 小而深

所有 kernel 都是 3×3,做 16-19 层。简洁优雅

GoogLeNet / Inception (2014) - “走多路”

同一层有多种 kernel size 并行,结果拼接。

ResNet (2015) - 改变游戏的”残差连接”

解决了”太深就训不动”的问题。让 100 层、1000 层成为可能

ResNet 的关键是跳跃连接(skip connection)

def residual_block(x):
    y = conv(x)
    y = relu(y)
    y = conv(y)
    return x + y   # ← 这一加是革命

**这个简单的”加”**让梯度能直接从深层流回浅层,深网络从此可训。

历史小知识:ResNet 那篇论文里最有名的可视化——20 层网络比 56 层还好——揭示了”深网络反而难训”的反常现象。残差连接解决了这个问题。

EfficientNet (2019) - 平衡深度、宽度、分辨率

按系统化方法缩放网络,性价比最高

Vision Transformer (2020) - 颠覆 CNN 统治

“如果 attention 这么好,为啥不用在图像上?” 把图像切成 16×16 patch,喂给 Transformer——发现也能打。

实际工业部署里,CNN 仍然是主力——它在小数据上表现更好、推理更快、能耗更低。

第八站:CNN 还做什么

除了分类,CNN 是这些任务的基础:

  • 目标检测(YOLO 系列、Faster R-CNN)—— 框出图里的物体
  • 语义分割(U-Net)—— 给每个像素打类别标签
  • 图像生成(GAN)—— 生成新图像
  • 超分辨率 —— 把模糊图变清晰
  • 风格迁移 —— 把梵高风格套到你照片上
  • 医疗影像 —— 看 CT/MRI
  • 自动驾驶感知 —— 识别车道、车辆、行人

所有这些都依赖卷积

一句话总结

CNN = 让 kernel 学。

Transformer 革命前,整个视觉领域都在堆 CNN。今天它仍然是视觉的默认起点——直到你证明 Transformer 在你的具体任务上更好为止。

想”看见”它

👀 CNN 卷积扫描可视化 —— 玩 6 种预设 kernel,看它们抽取不同的特征。

🔬 读完你解锁了什么
  • 能读懂 ResNet、VGG、EfficientNet 的论文
  • 能用 PyTorch 搭一个简单的图像分类器
  • 能理解为什么”图像 + Transformer” 是 ViT,“图像 + CNN” 是 ResNet——本质都是 inductive bias 的选择

下一篇推荐:L3-07 · 词嵌入(Word Embedding)从 Word2Vec 到 BERT —— CNN 处理像素,词嵌入处理文字。

📬

读到这里说明你认真在学 🎯

订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。

💬

讨论区

· 用 GitHub 账号登录评论
⚠️ Giscus 评论未配置 —— 在 src/components/Comments.astro 顶部填入 仓库 ID 和分类 ID(见组件注释里的配置步骤)。