Skip to content

MLP 如何把像素变成可分类的表示 ​

先给结论:MLP 是一串“全连接线性变换 + 非线性激活”的组合。 它接收一组数字,通过训练调整权重,把原始数字变成更适合当前任务的中间表示,最后给出预测。

本页不假设你已经知道“神经元”“隐藏层”或“表示学习”。我们只做一个贯穿始终的任务:让网络区分 5×5 点阵里的字母 O 和 X。

学习问题 ​

完成本页后,你应当能沿着下面这条链路解释每一个对象,而不是只记住一个公式:

text
5×5 点阵
→ 25 个输入值
→ 6 个隐藏神经元
→ 6 维隐藏表示
→ O/X 两个分数
→ 概率与分类结果

前置只需要矩阵乘法和最小优化循环。本页先解释前向计算和表示;梯度的具体算法留到反向传播。

MLP 到底是什么 ​

MLP 是 Multilayer Perceptron,多层感知机。名字虽然有“多层”,但理解它只需要四类对象:

对象在点阵任务中是什么负责什么
输入25 个像素值提供原始观测,不执行学习
全连接层权重矩阵 W 和偏置 b让每个输出读取上一层的全部数值并加权求和
激活函数本页使用 tanh引入非线性,让多层不能被合并成一层
输出层O、X 两个分数经 softmax 变成两个类别的概率

“隐藏层”只是位于输入和最终输出之间的层。它并不神秘,也不是藏着人类写好的“圆形检测器”;它保存的是训练过程为了降低 loss 而形成的一组中间数值。

输入层通常只表示数据入口,不计作一次参数化计算。因此本页所说的“两层 MLP”指两个带参数的全连接层:25 → 6 和 6 → 2。

把点阵变成网络输入 ​

下面是两个理想样本。亮格记作 1,暗格记作 0:

text
O                 X
0 1 1 1 0         1 0 0 0 1
1 0 0 0 1         0 1 0 1 0
1 0 0 0 1         0 0 1 0 0
1 0 0 0 1         0 1 0 1 0
0 1 1 1 0         1 0 0 0 1

计算机不会直接接收“这是一个 O”。我们先按固定顺序把五行连接起来:

text
x = [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 0,1,1,1,0]
shape(x) = [25]

标签 y 才告诉训练过程正确答案是 O 还是 X。x 是观测,y 是监督信号;预测时只有 x,不能把答案偷偷放进输入。

操作演示:从随机猜测到学会分类 ​

下面的 Canvas 真正在浏览器中运行一个 25 → 6 → 2 的小型 MLP。训练集包含两个标准点阵,以及每次翻转一个像素得到的带噪样本。

建议按顺序操作:

  1. 点击“重置网络”,观察未经训练的随机预测。此时接近 50% 或偏向任一类都没有意义。
  2. 点击一次“训练 1 轮”,注意平均 loss 和隐藏圆点发生了变化。
  3. 再训练 100 轮,分别载入 O、X,检查正确类别概率是否升高。
  4. 点击点阵中的一两个像素制造噪声,观察预测是否仍稳定;修改太多时,模型应当变得不确定甚至出错。

演示中的蓝、橙隐藏圆点表示激活的正负,深浅表示绝对值大小。颜色不代表某个神经元天然属于 O 或 X;输出层还会继续组合全部六个隐藏值。

一个隐藏神经元怎样计算 ​

第 j 个隐藏神经元读取全部 25 个输入:

aj=x1W1j+x2W2j+⋯+x25W25j+bj

然后应用激活函数:

hj=tanh⁡(aj)

可以把它理解成两步:

  1. 加权汇总:某些像素对该神经元产生正贡献,另一些产生负贡献;
  2. 非线性压缩:tanh 把任意实数映射到 (-1,1),并改变多层组合的表达能力。

六个隐藏神经元同时计算后,得到:

h=[h1,h2,h3,h4,h5,h6]

这个六维向量 h 就是当前点阵的隐藏表示。原来一个样本用 25 个像素描述;经过第一层后,同一个样本改用 6 个任务相关的数值描述。

整个前向传播的 shape ​

对单个样本保留 batch 维,可以完整写成:

text
x  [1,25] @ W1 [25,6] + b1 [6] → a [1,6]
a  [1,6]  → tanh → h [1,6]
h  [1,6]  @ W2 [6,2]  + b2 [2] → logits [1,2]
logits [1,2] → softmax → p [1,2]

这里的 logits 是两个尚未归一化的分数,softmax 才把它们变为和为 1 的概率:

pk=ezkezO+ezX

若 p=[0.91,0.09],模型预测 O;这表示模型在当前参数与数据下的相对倾向,不等于“91% 客观确定为 O”。

参数和激活不是一回事 ​

本例可训练参数总数是:

25×6+6⏟W1,b1+6×2+2⏟W2,b2=170
类型本例对象生命周期
参数W1、b1、W2、b2跨样本保留,由优化器更新
输入x来自当前样本
激活a、h、logits、p由当前输入和参数临时计算
梯度参数对应的 ∂L/∂W、∂L/∂b反向传播产生,供下一次更新使用

参数是网络“学到并保存”的数值;隐藏表示是特定输入经过当前参数后得到的结果。换一个点阵,参数不变,但 h 会变化。

为什么一定要有非线性 ​

如果去掉 tanh,两层全连接计算是:

(xW1+b1)W2+b2=x(W1W2)+(b1W2+b2)

右侧仍然只是一次线性变换。十个没有激活函数的线性层也能合并为一个线性层,深度没有带来新的决策边界。

非线性使不同区域可以形成不同响应,隐藏层才能把原空间中难以分开的模式变换到更容易分类的表示空间。经典 XOR 例子正是这个事实的最小证明;点阵任务则让这个过程有了可见输入。

网络怎样“学”到权重 ​

本页演示使用交叉熵。若正确类别是 O,单个样本的 loss 为:

L=−log⁡pO

正确类别概率越接近 1,loss 越小。一次训练循环仍然是第 0 章已经见过的结构:

text
前向:点阵 → 隐藏表示 → 概率
计算:概率 + 正确标签 → loss
反向:计算每个参数对 loss 的影响
更新:让参数沿降低 loss 的方向移动

所以“学习”不是把 O 图片存进某个神经元,而是反复修改 170 个参数,使训练样本经过网络后更倾向正确输出。隐藏表示随参数更新而改变,它是学习过程的结果之一。

从点阵 MLP 到真实图像 ​

如果输入是 28×28 灰度图,最直接的 MLP 会把它展平成 784 个数。这能运行,但有明显限制:

  • 展平后不再显式保留上下左右的二维邻接关系;
  • 同一个局部形状移动一个位置,就会对应另一组输入参数;
  • 第一层参数量随像素数和隐藏宽度快速增长。

CNN 通过局部连接与权重共享利用图像结构;Transformer 可以把图像切成 patch 再处理。它们不是否定 MLP,而是在输入结构和扩展方式上加入更合适的归纳偏置。

常见误解与边界 ​

  • 神经元不是生物神经元的精确模拟。 在这里它就是加权和加激活函数。
  • 隐藏维度不是预先命名的人工特征。 单个维度可能可解释,也可能只有多个维度联合才有意义。
  • 训练 loss 下降不等于泛化。 本演示只证明小网络能拟合一组人工点阵及其单像素噪声。
  • 概率高不保证输入合理。 对远离训练分布的乱点阵,softmax 仍可能给出很高分。
  • 网络更宽、更深不必然更好。 容量、优化、数据质量和评估必须一起考虑。

本节自测 ​

静态答案与检查点
  1. 错误;没有非线性的连续线性层仍可合并。
  2. 25×6+6+6×2+2=170。
  3. 回答应明确:参数跨样本保存并更新;隐藏表示依赖当前输入;换输入时参数可以不变而表示改变。

小结与下一步 ​

现在应当能够把 MLP 还原为具体计算:点阵是 25 个输入值,全连接层用参数混合它们,tanh 引入非线性,六个激活组成隐藏表示,输出层再将它映射为 O/X 概率;训练则用 loss 反复修正参数。

下一步学习反向传播:梯度怎样沿计算图返回,理解一次训练更新如何高效得到全部 170 个参数的梯度;随后在MLP 实验中用 PyTorch 验证非线性的作用。

最近更新