MLP 处理图像的局限
用 MLP 直接处理 MNIST,分析其在参数规模和位置敏感性上的问题。
直接拿 MLP 处理图像,行不行?
上一节我们看到, 的 MNIST 图像在 PyTorch 里就是一个 的张量。 MLP 接受的是 一维向量 ,那把这张图 展平 成 784 维向量, 丢进上一章的 MLP,能直接进行手写数字分类吗?
从代码层面看,答案是"能跑通"——MNIST 这种 28×28 的小图甚至能跑出不错的准确率。 但这种做法 背后藏着两个隐患 ,一旦输入图像变大、或者数字稍微动一动位置,问题就会显现。 本节先把 MLP 跑起来作为基线,再亲手戳一下它的两个隐患。
基线:MLP + 展平 + MNIST
把图像张量从 展平成长度 的向量,然后接一个常规 MLP—— 本节用 这个尺寸(后面课程与 CNN 对比时保持口径一致):
训练 5 轮左右,准确率能稳定到约 95% – 97% 。 看起来 MLP 处理小尺寸图像并不差。但 这个结果建立在两个前提上 : 图像尺寸很小,且数字已经预先居中。我们下面分别戳穿这两层"皮"。
隐患一:尺寸一放大,参数量就爆炸
MNIST 是 维输入。 现实里的照片通常远大于此——一张普通彩色照片可能是 万维输入。
如果照搬 MLP 的做法,第一层全连接需要把每个输入像素与每个隐藏神经元两两相连。 假设隐藏层只有 256 个神经元:
单是 一层 就需要约 2.36 亿 个参数。 不仅训练成本极高,模型也极易过拟合,且大量的连接其实在做"无用功"—— 图像中相距很远的像素之间通常关联微弱,把它们用一根权重连起来纯属浪费。
隐患二:把数字挪一挪,准确率就崩了
MNIST 的数字都被预先居中。但真实场景里,待识别的内容并不会自动居中—— 同一个 "5",可能写在画面正中,也可能偏左、偏上、偏下。 训练好的 MLP 能否扛住这点位移?我们做一个小实验。
为了让效果直观、又能在浏览器里实时跑起来,下面的实验把网络的"任务规模"做了简化: 在 28 × 28 的画布上随机抽取 4 种几何形状之一 (圆环 / 竖线 / 横线 / 十字), 每种形状都是 14 × 14 大小, 居中 放在画布中央; 训练一个 的 MLP 来识别它们。 训练时,图形始终居中——这与 MNIST 一致。
训练完成后,你可以通过滑块把图形整体 左右、上下平移 若干像素, 看看 MLP 对它的预测概率怎么变化。
实际拖动你会看到:只要图形稍微偏离训练时的居中位置,预测概率就剧烈抖动, 模型甚至会把同一个图形识别成完全不同的类。 这就是位置敏感问题 :MLP 的每个权重都与某个固定的输入坐标绑定, 平移之后,原本笔画落在某些坐标上的"贡献"就转移到了另一组完全不同的权重上, 模型自然给出不同的回答。
两个隐患背后的三个共同问题
把上面两个现象拆开看,会发现它们其实指向 MLP 处理图像的 三个共同的根本问题 :
要解决这三个问题,需要重新审视图像数据本身的 结构 , 而不是把它当作一个普通的高维向量来处理。 图像有两个非常重要的性质:
换句话说, 处理图像的层结构应当与这两个性质对得上 。 把它落到对权重的具体约束上,两条性质各自暗示了一个朴素的设计:
- 为了贴合 局部性 ——每个输出只看一小块邻域, 而不是把所有像素都连进来;
- 为了贴合 平移不变性 ——同一组权重需要在画面的 不同位置 反复使用 ,也就是 参数共享 。这样一来,无论笔画落在哪个坐标, 都能由 同一组 权重检出,从而对位置变化保持稳定。
而 MLP 的全连接结构这两条都不沾——它一上来就把整张图拉成一条向量, 既丢掉了"局部"这件事,每个权重又被钉死在一个固定坐标上、 与邻居们各干各的、彼此之间没有任何复用, 所以才会同时引出前面那两个隐患。