先弄清楚:这台机器到底在做什么
这个演示要完成的任务叫做图像分类:输入是一张手写数字图像,输出是 0–9 中的一个数字类别。
你可以把整件事想成一场有标准答案的猜数游戏:
- 训练:先给网络看大量带有正确类别标签的手写数字图像。例如,一张图片旁明确写着“正确类别是 3”。网络每预测错误一次,训练程序就调整模型参数——包括卷积核权重、偏置以及后续层的权重——让下一次预测更接近正确类别。
- 推理:训练结束后,已经学到的模型参数保持不变。此时输入一张新的手写数字图像,网络只使用这些固定参数,计算它属于
0–9各类别的概率,不再修改权重。
为避免混淆,本文统一使用以下称呼:
- 数字类别:答案属于
0–9中的哪一类,例如“类别 3”。 - 像素值:图片中每个小格的亮度,本页用
0–1表示。 - 模型参数:网络在训练时会调整、在推理时保持不变的数值,主要包括权重和偏置。
这个页面做的是“推理”,不是现场训练。你的笔迹只在当前浏览器中计算,不会上传。
CNN 究竟是什么
CNN 的全名是 Convolutional Neural Network,中文叫卷积神经网络。
先不要被“神经网络”这个名字吓到。在这个演示里,它本质上是一条由许多数学运算组成的流水线:
图片 → 找边缘 → 组合成形状 → 给 0–9 打分 → 选最高分
其中“卷积”是这条流水线最关键的观察方式:它不一次看完整张图,而是拿一个小窗口从左到右、从上到下逐格扫描,先找到边、拐角和笔画方向,再把它们组合成更完整的数字字形。
先认识 4 个词
- 像素:图片中最小的格子。这里的黑白图可以看成
28 × 28 = 784个像素值;0接近黑,1接近白。 - 层:流水线上的一个工位。每一层只做一类较简单的计算,多层接力后才能完成识别。
- 卷积核:一个很小的权重方阵,比如
3 × 3的 9 个权重。它像一枚“花纹探测器”,专门检查局部区域是否出现某种明暗变化。真实模型中的核不是人手写的规则,而是从训练数据中学出来的。 - 特征图:卷积核扫完整张图后产生的新图。哪里与它想找的花纹越像,对应位置的特征值就越大、显示得越亮。
卷积核到底怎么算
它没有在做什么神秘的事,每停在一个位置,只做下面五步:
- 用
3 × 3的卷积核盖住图片上的3 × 3个像素。 - 将 9 个像素值与 9 个卷积核权重逐项相乘,共做 9 次乘法。
- 把 9 个乘积全部加起来,再加上一个叫做偏置的基础分。偏置也是训练出来的,它用来调整这个卷积核“多容易被触发”。
- 通过 ReLU:正数原样保留,负数改成
0。可以把它理解成“不像就不点亮,像才点亮”。 - 向右移动一格,在新位置重复同样的计算。
把它写成一行就是:
输出 = ReLU(9 个“像素 × 卷积核权重”的和 + 偏置)
不需要背这个公式。只要记住:小窗口负责取数,卷积核负责打分,ReLU 负责把没有匹配到的负分关掉。
为什么这样就能找到边缘?因为卷积核里的正权重表示“这里亮就加分”,负权重表示“这里亮就扣分”。当一块像素的明暗排列恰好与卷积核偏好的花纹一致,总分就会很高。
下方的第一张互动卡用一个简化的“竖直边缘核”演示整个计算。点击“下一格”,可以看到窗口移动后,参与计算的 9 个像素和最终分数如何变化。
卷积核里的权重是谁设定的
先给出短答案:不是人逐格填的,而是模型在训练中一点点学出来的。
人会决定“这一层用 8 个 3 × 3 卷积核”,这叫网络结构;但每个核里的 9 个权重和 1 个偏置应该是多少,由训练来决定。
第一步:先从“乱猜”开始
训练开始时,权重通常会被随机初始化成一组接近 0 的小数。它们此时没有“找边缘”或“找圆弧”的能力,第一次预测几乎是随机猜。
为什么不把所有卷积核都初始化成完全相同的 0?因为那样 8 个核会收到完全相同的修改,永远学成一样的东西。用略有不同的随机数开局,是为了打破这种对称,让不同核有机会分工学习不同特征。
第二步:让当前卷积核先猜一次
一张带有正确类别标签的手写图片进入网络,依次经过卷积、池化和分类层,最后产生属于 0–9 各类别的概率。数据从输入一路流向输出的过程,叫做正向传播。
假设图片的正确答案是 3,模型却把 8 的概率给得最高,这次猜测就是错的。但“错了”还不足以指导修改,还要知道错得多严重。
第三步:用损失函数量化错误程度
损失函数会把“预测”与“正确答案”的差距变成一个数,称为损失。预测越离谱,损失越大;预测越接近答案,损失越小。
训练的目标不是让某一个卷积核“看起来像边缘检测器”,而是让整个网络在大量图片上的平均损失尽可能小。这也是真实卷积核的权重常常不整齐、不能逐个用人类语言命名的原因。
第四步:把错误的责任一层层传回去
最终答案猜错,不只是最后一层的责任。前面的卷积核提取了什么特征,也会影响后面的判断。
反向传播会从最后的损失出发,沿着网络倒着往回算,为每个权重算出一个梯度。梯度可以先理解成一张“责任单”:
- 这个权重如果变大一点,损失会变大还是变小?
- 它对这次错误的影响大不大?
- 它应该向上调还是向下调?
它不是把误差平均分给所有参数。某个权重对本次预测的影响越大,收到的修改信号通常也越大。
第五步:每次只修改一小步
有了梯度后,梯度下降负责真正更新权重:
新权重 = 旧权重 − 学习率 × 梯度
学习率决定每次修改多少。太大可能一步跨过更好的位置,在两边来回震荡;太小则学得非常慢。合适的学习率会让损失逐步下降,而不是期待一次就把答案改对。
下方的第二张互动卡使用一个可以心算的简化例子,展示一个全为 0 的卷积核如何在三次更新中逐渐学成“左负右正”:
| 训练次数 | 左列权重 | 中列权重 | 右列权重 | 预测分数 | 损失 |
|---|---|---|---|---|---|
| 0 | 0.000 | 0.000 | 0.000 | 0.000 | 0.5000 |
| 1 | -0.100 | 0.000 | 0.100 | 0.600 | 0.0800 |
| 2 | -0.140 | 0.000 | 0.140 | 0.840 | 0.0128 |
| 3 | -0.156 | 0.000 | 0.156 | 0.936 | 0.0020 |
可以看到,“学会找边”不是突然产生的,而是预测逐步靠近目标、损失逐步下降的结果。
真实卷积核为什么看起来比这个例子乱
上面的例子直接告诉小卷积核“这是一条边”,只是为了把一次更新讲清楚。真实 CNN 并没有“边缘正确答案”,它只知道整张图最后应该是 3 还是 8。卷积核与其他层一起调整,只要最终分类损失下降就会保留这次改动。
因此,真实结果通常会有三个特点:
- 权重通常是
-0.42、0.27这样的小数,而不是整齐的-1、0、1。 - 每个核只是团队中的一员,单独拿出来未必有完美的人类语义;页面中的“竖边”“斜边”标签只是近似解读。
- 换一个随机起点重新训练,最后的具体参数值可能不同,但整体识别效果可以同样好。
训练结束后,这些模型参数才会固定下来。你在本页输入新的手写数字图像时,只在做正向传播,卷积核权重不会再更改。
为什么还要一层层叠加
一个卷积核通常只会找到一种很简单的局部特征。所以 CNN 会让多个核并行工作,再把它们叠成多层:
784 个像素值 → 边缘 / 方向 → 拐角 / 圆弧 → 手写字形的整体结构 → 0–9 各类别的概率
第一层不需要知道“这是 3”,它只要找边。后面的层再把边拼成更大的部件。这就是神经网络“由简单特征逐层组合出复杂概念”的核心思路。
现在再亲手试一次
先用下面的小例子看懂一次卷积计算,然后在画板上写一个 0–9 的数字。模型会把你的笔迹依次变成:
28 × 28的像素值矩阵。- 第一层卷积核找到的边缘和笔画方向。
- 池化后更小、更抗抖动的特征图。
- 第二层卷积组合出的拐角和圆弧。
- 展平后的一维特征向量,以及经过 Softmax 换算的类别概率。
画完后向下滚动,可以逐层看真实 CNN 刚才计算出来的中间结果。如果不想手写,也可以直接点击预设数字。
先看懂一次计算,再运行真实模型
卷积核不是黑盒:它只做 9 次乘法
左边是一张只有 0 和 1 的迷你图片,右边是一个寻找“左侧暗、右侧亮”的 3×3 卷积核。 彩色框每次只看 9 个像素;它移动一格,就重新算出一个结果。
相同位置两两相乘
这里出现了从暗到亮的竖直变化,与这个卷积核想找的左边缘相似,所以得到正分。
再追问一步:这 9 个权重从哪里来
卷积核不是人填的,是一次次改出来的
人只规定“使用 3×3 的小窗口”,不会逐个指定里面该填什么。 训练开始时这些权重通常是接近 0 的随机小数;模型猜一次、量一次错误、改一点点,重复许多次后才得到最终数值。
- 1随机初始化先从一组没有意义的小数出发
- 2正向传播用当前权重计算预测
- 3计算损失量出预测离答案有多远
- 4反向传播算清每个权重该往哪边改
- 5梯度下降按学习率只修改一小步
教一个全为 0 的卷积核认识“左暗右亮”
为了能心算,把暗、过渡、亮分别写成 −1、0、1,并告诉模型这块花纹的目标分数是 1。 这里直接给了“边缘答案”只是教学简化;真实 CNN 只拿到整张图片的类别标签(例如“这是 3”),误差会从输出层一路反传到卷积核。
0.1(学习率)× 1.000(误差)× 对应像素卷积核现在全是 0,所以无论看到什么都只能打 0 分。点击“训练一步”开始修改。
为什么真实卷积核不是整齐的 −1、0、1?
右边是模型第 0 个卷积核的真实参数。它不是单独练习“找一条标准边”,而是与另外 7 个卷积核、后面的卷积层和分类层一起,为“最终的数字类别有没有预测正确”负责。 因此优化器只追求整套网络的损失更小,不追求权重值整齐或方便人类解释。
每个权重都是大量样本、许多轮更新共同累积的结果。换一组随机初始值重新训练,最后的参数值通常会不同;只要它与其他卷积核配合后同样能正确识别,就仍然是有效答案。
用鼠标 / 手指在这里手写一个数字
计算机视觉,其实是披着风衣的五层数学结构
你在上面画的数字,会像在一条流水线上一样,依次经过下面 5 个工位。 每个工位都在真的计算、图也真的在变—— 最后由一排“评委”投票,票数最高的就是答案。边画边往下看,图里很多地方还能点一点、悬停一下。
这套顺序不是随便排的——整条流水线在由简到繁地搭积木:
上料 · 你画的手写数字
流水线的第一步:把你的字缩成 28×28 的小格子、摆正。注意——在电脑眼里这根本不是一张“图”,而是 784 个像素值。上面这张图你可以点点看:每个格子都有一个 0~1 的亮度值。
💡 为什么这么做为什么先缩成 28×28、还要摆正?因为后面每个“检查员”都是按固定的大小、固定的位置训练出来的。先把输入统一成同一种格式,它们才认得——就像考试得用统一答题卡。
Conv2D(二维卷积)· 找边缘
第 1 个工位站着 8 个“检查员”(卷积核),各自只认一种花纹,拿着一个 3×3 的小窗口滑过整张图,看到就在那个位置点亮——于是 1 张图变成了 8 张“这种花纹出现在哪儿”的地图。每张图下面标了那位检查员大致在找什么。(注:网络没被告诉要找什么,这些名字是照它自己练出来的卷积核近似标的,所以有的清晰、有的偏杂。)
💡 为什么这么做为什么第一步先找“边”?因为一个手写数字属于哪个类别,几乎全写在它的轮廓和笔画走向上,而不在于笔画是深是浅、背景是什么。直接盯着每个像素的亮度既啰嗦又脆弱(你写深一点、浅一点,数值全变);而“这儿有没有一条边、朝哪个方向”这种线索才真正稳,才是区分 1 和 7 的关键。所以先把最基础、最通用的积木——边和角——抠出来,后面所有判断都搭在它上面。
MaxPool(最大池化)· 缩小去噪
第 2 个工位负责“打包压缩”:把每 2×2 一小格只留最亮的那个点,图整整缩小一半。关键亮点全留着,细枝末节和噪声被丢掉——既省力,又让识别不那么挑剔你画得偏一点、大一点。(还是刚才那 8 张检查员的地图,只是每张缩小了一半。把鼠标放到格子上能看到具体数值。)
💡 为什么这么做为什么要缩小去噪?三个好处:① 更抗抖——你把字写偏一点、大一点,边的精确位置会变,但“这一带有条竖边”不变;只留每小块里最强的信号,等于说“我只关心附近有没有这个特征,不纠结它在第几个像素”,识别因此对位置、大小、笔迹都更宽容。② 省算力——图小一半,后面每层计算量降到约四分之一。③ 放大视野——图缩小后,下一层同样的 3×3 窗口能覆盖原图更大一片,正好接着往下拼更大的形状。
Conv2D(二维卷积)· 拼出更大的部件
第 3 个工位是更资深的 16 个检查员。他们不看原图,而是看上一批人交上来的“花纹地图”,把短横短竖拼成拐角、圆弧这类更大的部件。越往后,识别的东西越接近数字字形的局部结构。(同样可以把鼠标放到格子上看特征值。)
💡 为什么这么做为什么还要再卷一层、拼更大的部件?因为光看“边”还判断不出数字类别:横线竖线到处都是,1、4、7 都有竖线。真正区分它们的是这些边怎么组合——一个圈、一个朝左的开口、一个交叉。第二层站在第一层的“边缘地图”上,把邻近的边拼成更大的形状零件(拐角、圆弧、闭环)。这就是“由简到繁搭积木”:像素→边→部件,越往深,识别的结构越大、越抽象、越接近“这到底是几”。
Flatten(展平)· 排成一队
第 4 个工位把 16 张二维特征图一张张拆开、首尾接成一条长队(16×11×11 = 1936 个特征值)。这一步不改动任何信息,纯粹是换个队形。
💡 为什么这么做为什么要拍平成一条队?因为做最终判断的“评委”(下一层)只接受一维特征向量,没法直接读取二维特征图。拍平纯粹是为了对接它的输入格式,好让它一次性从头读到尾——信息一个都没丢。
Dense(全连接层)+ Softmax(概率换算)· 投票选答案
最后一个工位坐着 10 位“评委”,分别代表 0~9 十个数字类别。每位评委把长队里的 1936 个特征值按自己的偏好加权求和,得到一个原始分(可能是 8.7、-1.2 这种,没上限、还能是负的)。原始分不好读,于是用 Softmax:它是一把“换算尺”,把这 10 个分数压成一串加起来正好等于 100% 的概率——分越高,占的比例越大。这样你就能直接读成“我有 92% 的把握是 3”。柱子最高的那个,就是答案。
💡 为什么这么做为什么用投票 + 概率来收尾?前面几层只是“看到了哪些零件、在哪儿”,还没下结论。让 10 位评委各自按“我代表的数字类别应该具有什么形状”去打分,就把“看到了什么”变成“所以最像几”;再用 Softmax 换算成加起来 100% 的概率,是为了让结果好读、能比较——“92% 是 3、5% 是 5”比一堆原始分直观得多。
🧠 它是怎么学会的?
这些“检查员”和“评委”的眼力,不是人一条条规则写出来的。 一开始他们全靠瞎猜、错得一塌糊涂。我们拿 6 万张带有正确类别标签的手写数字图像一张张给它看, 每猜错一次,就把大家的判断往正确方向微调一点点; 这样重复几十万次,他们就慢慢练成了现在的样子(这个 demo 认对的概率约 98.5%)。 所以你换种写法它多半也认得——因为它见过的写法实在太多了。