卷积
卷积是一个奇怪的东西。学信号处理的时候第一次见它,翻来覆去搞不明白为什么要"翻转";后来做图像处理,发现高斯模糊、边缘检测全都靠它;再后来看 CNN,卷积层直接成了深度学习的基本砖块。同一个运算,三层含义,越看越有意思。
这篇文章是我自己的理解整理,从数学定义一路推到 CNN。
1. 数学上的卷积¶
定义¶
连续情况下,两个函数 \(f\) 和 \(g\) 的卷积定义是:
离散版本更接地气,也是实际上计算机里用的:
这个 \(t-\tau\) 到底在干什么?¶
刚看这个公式的时候,最困惑的就是为什么是 \(g(t-\tau)\) 而不是 \(g(t+\tau)\)。
分三步理解就清楚了:
- \(g(\tau)\) —— 原始信号(比如一个滤波器响应)
- \(g(-\tau)\) —— 沿纵轴翻转(镜面对称)
- \(g(t-\tau) = g(-(\tau - t))\) —— 翻转后再向右平移 \(t\)
然后把翻转平移后的 \(g\) 和 \(f\) 逐点相乘,再加起来,就得到了卷积在 \(t\) 这一点的值。\(t\) 从 \(-\infty\) 滑到 \(+\infty\),每滑一步算一个值,最终得到完整的 \((f*g)(t)\)。
下面这张图把这个过程可视化了:
Tip
为什么必须翻转?
如果你跳过翻转这一步,得到的是互相关 (cross-correlation),不是卷积。
翻不翻转在信号处理里区别很大——卷积有交换律,相关没有。不过有意思的是,在 CNN 里大家嘴上说"卷积层",实际上做的是互相关,只是习惯上还叫卷积。
基本性质¶
卷积有几条基本性质:
- 交换律:\(f * g = g * f\)。把两个函数换位置,结果不变。
- 结合律:\((f * g) * h = f * (g * h)\)。多层滤波可以合并成一个。
- 分配律:\(f * (g + h) = f * g + f * h\)。线性性保证了叠加原理成立。
- 与 \(\delta\) 函数的关系:\(f * \delta = f\)。\(\delta\) 函数是卷积的单位元——任何函数和它卷完还是自己。
几个常见的例子¶
多项式乘法:\((a_0 + a_1 x + a_2 x^2)(b_0 + b_1 x) = \sum c_k x^k\),其中 \(c_k = \sum_i a_i b_{k-i}\)。这就是离散卷积。
移动平均:拿一个全是 \(1/N\) 的窗口去卷积信号,得到的就是平滑后的结果。窗口越长,平滑得越狠。
概率论:两个独立随机变量 \(X\) 和 \(Y\),\(X+Y\) 的密度函数是 \(f_X * f_Y\)。两个独立随机变量之和的分布,恰好是各自分布的卷积。
2. 图像处理中的卷积¶
从一维跳到了二维。图像是一个二维矩阵 \(F(i,j)\),滤波器(也叫核、kernel)是另一个小矩阵 \(K(u,v)\)。
二维离散卷积:
实际操作中,就是把核在图像上一格一格地滑过去,每个位置逐元素相乘再求和,得到一个输出值。
卷积 vs 互相关¶
前面提到过,真正的卷积要翻转核(上下左右各翻一次),互相关不翻转。在图像处理里:
- 严格卷积:\(K\) 翻转 180° 再滑动
- 互相关:\(K\) 直接滑动
因为大多数手工设计的核(比如高斯核)本身就是中心对称的,翻不翻转都一样,所以实际上两种操作经常混着用。关键是理解"滑动 → 乘积累加"这个核心动作就够了。
padding 和 stride¶
滑动的时候有两个实际问题:
- padding:边缘像素参与卷积的次数少,如果不补边,输出尺寸会比输入小。补 0(zero-padding)是最常见的做法。
samepadding 会让输出尺寸和输入一样。 - stride:核每次滑动的步长。stride=2 意味着隔一个像素算一次,输出尺寸减半,但计算量也减半。
几种经典的核¶
不同核的数值设计,决定了从图像里提取什么特征。
| 核 | 矩阵 | 效果 |
|---|---|---|
| 均值模糊 | \(\dfrac{1}{9}\begin{bmatrix}1&1&1\\1&1&1\\1&1&1\end{bmatrix}\) | 最简单的平滑,每个像素变成周围 9 个像素的均值 |
| 锐化 | \(\begin{bmatrix}0&-1&0\\-1&5&-1\\0&-1&0\end{bmatrix}\) | 增强边缘,中心 +5 周围 -1,相当于原图 + 拉普拉斯边缘 |
| Sobel X | \(\begin{bmatrix}-1&0&1\\-2&0&2\\-1&0&1\end{bmatrix}\) | 检测竖直边缘(水平方向梯度) |
| Sobel Y | \(\begin{bmatrix}-1&-2&-1\\0&0&0\\1&2&1\end{bmatrix}\) | 检测水平边缘(竖直方向梯度) |
| Laplacian | \(\begin{bmatrix}0&1&0\\1&-4&1\\0&1&0\end{bmatrix}\) | 二阶导数,检测边缘方向无关 |
| 高斯模糊 | 权重按二维高斯分布衰减 | 比均值模糊更自然,中心权重最大 |
下面是这些核对同一张测试图的效果。代码就嵌在下面,改核、改参数都可以自己试:
3. CNN 中的卷积¶
手工核 vs 学习出来的核¶
前面讲的核都是人手工设计的:高斯、Sobel、Laplacian……每个核提取一种特定的特征。
CNN 的想法直接得多:让网络自己学该用什么核。把核的数值当成可训练的参数,通过反向传播不断更新,最后网络自己找到最适合当前任务的滤波器。
这就是为什么 CNN 不需要人工设计特征——卷积层就是自动的特征提取器。
核心组件¶
卷积层 (Conv2D)
输入是 \(H \times W \times C_{in}\) 的三维张量(高度、宽度、通道数),比如 RGB 图像是 \(C_{in}=3\)。一个卷积层包含多个滤波器(filter),每个滤波器是 \(k \times k \times C_{in}\) 的小立方体。
每个滤波器在输入上滑动,产生一个 \(H' \times W'\) 的特征图。如果有 \(C_{out}\) 个滤波器,输出就是 \(H' \times W' \times C_{out}\)。不同滤波器学会了检测不同特征——有的对边缘敏感,有的对纹理敏感,有的对特定形状敏感。
参数量的计算很直观:每个滤波器有 \(k \times k \times C_{in} + 1\) 个参数(+1 是偏置),\(C_{out}\) 个滤波器就是 \(C_{out}(k^2 C_{in} + 1)\)。和全连接层比起来,参数量少得惊人——这就是卷积层的参数共享带来的好处。
激活函数 (ReLU)
卷积是线性运算,堆再多层也不过是一个大线性变换。ReLU(\(f(x) = \max(0, x)\))给网络加上非线性,让它可以拟合任意复杂的函数。
池化层 (Pooling)
池化做降采样。最常用的是最大池化(MaxPool):\(2 \times 2\) 窗口里取最大值,stride=2。效果是把特征图尺寸减半,同时: - 减少后续层的计算量 - 提供一定的平移不变性 - 增大每个神经元看到的原始图像范围(感受野)
平均池化(AvgPool)也是 \(2 \times 2\) 取均值,但最大池化在实践中更常用。
全连接层 (FC)
卷积和池化提取完特征后,最后接一个或两个全连接层做分类(或回归)。全连接层把前面所有特征综合起来,输出每个类别的得分。
整体架构¶
下面这张图把整个流程串了起来。以 MNIST 手写数字识别(28×28 灰度图 → 10 个数字类别)为例:
从 28×28×1 的输入图像,经过两层卷积+池化变成 4×4×16,展开成 256 维向量,再通过两个全连接层输出 10 个类别的概率。
Note
输出尺寸的计算公式
输入尺寸 \(W_{in}\),核大小 \(K\),padding \(P\),stride \(S\):
比如上面 Conv1:\(W_{in}=28\),\(K=5\),\(P=0\),\(S=1\) → \(W_{out} = 28-5+0+1 = 24\)。
为什么卷积适合图像?¶
三个关键原因:
- 稀疏连接:每个输出像素只和核覆盖的那一小块输入相关,不是和所有输入都连接。一个 \(5 \times 5\) 的核只看 25 个像素,而不是整张图的 784 个。
- 参数共享:同一个核在图像的不同位置使用相同的权重。检测边缘的核在左上角和右下角是同一个东西,不需要为每个位置学一套参数。
- 平移等变性:输入平移了,输出也跟着平移。这是卷积运算本身决定的,不是学出来的。
这三条加起来,让 CNN 在处理图像时比全连接网络高效得多。
没展开的东西(但你应该知道它们存在)¶
这篇文章只讲了最基础的卷积。实际用的时候还有一些重要的变体:
- 1×1 卷积:看起来只是个标量乘法,但在多通道场景下可以做通道间的线性组合,用来降维或升维
- 深度可分离卷积:先对每个通道单独做空间卷积,再用 1×1 卷积混合通道。MobileNet 的核心
- 空洞/膨胀卷积:核的元素之间留空隙,不增加参数量的前提下扩大感受野
- 转置卷积:用来上采样,生成式模型和语义分割里常见
- ResNet 的残差连接:让梯度能跳过层直接回传,解决了深层网络训练不动的问题
总结¶
三个层次看下来,卷积的核心动作始终是同一件事:拿一个函数(或核)去"扫描"另一个函数(或信号),每扫到一个位置就做加权求和。
- 数学上:翻转、滑动、乘积累加
- 图像处理:手工设计核,提取想要的视觉特征
- CNN:把核变成可学习的参数,让网络自己找有用的特征
从手写规则到自动学习,卷积这个运算的内涵一直在扩展,但底层逻辑没变过。