🧠 第八章 神经网络训练
📄 一句话概括

32×32×3 的输入,16 个 3×3 卷积核只要 448 个参数; 同样输入输出改用全连接要 44251200 个,差 98775 倍。 一个边缘检测核在合成图上打出 91 个强响应,全落在埋的方块边界上。

📝 本节和前面几节的关系

上一节的感知机把输入摊平成一维,图像的空间结构就丢了。 这一节讲卷积怎么把「相邻」这件事变成参数结构。

一、卷积在算什么

拿一个小窗口(比如 3×3)在图上从左到右、从上到下滑,每滑到一个位置, 就把窗口里的数和核里的数逐位相乘再求和,得到一个输出值。 就这么简单。它和信号处理里的卷积是同一个操作(严格说是互相关,但深度学习圈里都叫卷积)。 输出尺寸的公式:宽减核宽加一。32 宽、核 3,输出就是 30。这是 valid 模式,不补零。 关键点是:同一个核在整张图上滑,用的是同一组数。这叫做权重共享。

二、省参数省得离谱

一个 3×3 核配 3 个输入通道,就是 27 个数;16 个这样的核加 16 个偏置,一共 448 个参数。 同样输入(32×32×3)到同样输出(30×30×16),如果用全连接:3072 个输入接 14400 个输出, 需要 44251200 个参数。 差了 98775 倍。 这个倍数看着夸张,但算法很朴素——全连接是「每个输出位置一套独立权重」,卷积是「所有位置共用一套」。 省参数只是表面。真正的好处是:参数少了两个数量级,过拟合的风险和显存占用都跟着掉下来了。

三、核在找什么:边缘

Demo 用一个经典核:中心 4、四邻 -1(拉普拉斯算子)。它的作用是「中心减四周」。 平坦区域,中心和四周差不多,相减接近 0;边界上中心在方块里、四周在外面,差值就跳起来。 所以它对边缘特别敏感。 我在图上埋了一个 12×12 的亮方块(行 10~21、列 10~21),输出最大值 +19.74、最小值 -11.98, 绝对值大于 6 的位置有 91 个,集中在行 8~21、列 8~21。 行号差一格是正常的:卷积输出的第 8 行对应输入的 8~10 行,它已经碰到方块的上边界了。 做可视化时这个偏移要记住,不然会以为检测偏了。

四、比省参数更重要的是平移等变

同一个核在整张图上滑,意味着物体挪个位置,同一套核照样能检测到。 这叫平移等变:输入平移,输出跟着平移。 全连接没有这个性质。物体挪一格,几乎所有的输入数值都变了,网络得重新学一遍那个位置上的物体。 所以卷积网络在图像上强,不是因为参数少,是因为它把「图像是二维的、 相邻像素有关系」这个先验写进了结构里。 这也是为什么拿卷积网络处理表格数据效果一般——表格的列之间没有「相邻」这回事。

五、动手 Demo:卷积省参数:448 对 4425 万个,还顺手找出边缘

算 32×32×3 输入、16 个 3×3 核这一层的参数量和输出尺寸,再算同样输入输出改用全连接的参数量; 然后造一张带噪合成图(中间埋一个 12×12 亮方块),用中心 4、四邻 -1 的边缘检测核扫一遍, 看强响应落在哪。

for i in range(out_h):
    for j in range(out_w):
        patch = x[i:i + K, j:j + K, :]
        out[i, j] = float((patch * k_edge[:, :, None]).sum())

实跑输出:

--------------------------------------------------------------------
卷积为什么省参数:一次卷积和一层的对比
--------------------------------------------------------------------
  输入                     32 × 32 × 3
  卷积核                   16 个 3 × 3
  步长 / 填充              1 / 0(valid)
  卷积层参数               448
  输出尺寸                 30 × 30 × 16
  同样输入输出用全连接     44251200 个参数
  倍数                     98775 倍

  拿一个 3×3 的边缘检测核(中心 4、四邻 -1)在输入上滑一遍:
  输出形状                 30 × 30
  输出最大值               +19.74
  输出最小值               -11.98
  强响应像素数(绝对值大于 6) 91
  强响应位置范围           行 8~21,列 8~21
  我埋的方块位置           行 10~21,列 10~21
  为什么行号差一格         卷积输出第 8 行对应输入的 8~10 行,它已经碰到了方块的上边界

  强响应正好落在方块的边界上——这就是边缘检测核在做的事:平坦区域四邻和中心差不多,相减接近 0;边界上相差很大,响应就跳起来。
  参数省下来的原因是**权重共享**:同一个 3×3 核在整张图上滑,每个位置用的都是那 9 个数。全连接则是每个位置一套独立权重。
  省参数只是副产品,真正的好处是**平移等变**:物体挪个位置,同一套核照样能检测到。

448 对 44251200,差 98775 倍。 这个倍数里绝大部分来自「14400 个输出位置共用同一套 27 个数」。 强响应 91 个,位置集中在行 8~21、列 8~21。 方块本身是行 10~21,所以响应落在它的边界上,落点是对的。 输出最小值是 -11.98,负值出现在「中心暗、四周亮」的地方。 边缘检测核有正有负,所以边界两侧一个是正峰一个是负峰。 我给合成图加了标准差 0.15 的噪声。 第一版噪声用 1.0,结果全图都是强响应——噪声本身就有边缘,阈值筛不掉。 这件事在真实图上同样成立:用强核找边缘之前,通常得先做一次高斯模糊。 这个 Demo 是逐像素 Python 循环,30×30 也就 900 次,慢不到哪去。 真实尺寸上必须用矩阵化的实现或者专门的卷积库,不然慢到没法用。

30 秒实验

  1. 把核换成「上排 -1、下排 +1」,看强响应落在方块的哪几条边上。
  2. 把卷积核改成 5×5,重算参数量和输出尺寸。
  3. 想一想:为什么卷积的平移等变性质对图像任务特别重要?

常见误区

  1. 「卷积就是降维」——它是提取局部特征,降维是池化干的事。
  2. 「卷积网络强是因为参数多」——恰恰相反,它比全连接少四个数量级。
  3. 「任意数据都能上卷积」——它依赖「相邻位置有关系」这个前提,表格数据不满足。
自测三问(点开对答案) 1. 卷积层的参数量怎么算? —— 卷积核数量乘(输入通道 × 核宽 × 核高),再加核数量个偏置。 2. 为什么卷积比全连接省这么多参数? —— 全连接每个输出位置一套独立权重,卷积所有位置共用同一套核。 3. 平移等变是什么意思? —— 输入平移多少,输出也跟着平移多少,同一套核照样能检测到。

图像是二维的、有空间结构。下一节换成一维的序列:时间上前后有关,网络结构就得跟着变。

相关笔记