人一眼就能分清猫和人,但计算机收到的是一张密密麻麻写满 0~255 数字的表。本篇先一路追踪到单个像素,看照片如何变成矩阵;再确认像素距离为什么量不出“相似”;然后亲手计算用 3 × 3 滤波器寻找边缘的卷积。最后看看人工设定的特征(人脸框·特征点·边缘强度)的优点和局限。
尖尖的耳朵和毛发,光滑的皮肤。人一眼就能分清。计算机把这张照片当成什么来接收,又能从哪些线索开始找起呢?
左边猫身上的红线是连接额头·眼睛·鼻子的面部骨架,右边人身上的绿框是“这里有一张脸”的检测结果,红点是下颌线·眉毛·嘴唇周围的特征点,粉点是两只眼睛·鼻子·嘴的核心位置。这些都是人事先定好“要看什么”的线索。
本篇关注两点。第一,计算机收到的不是这些线和点,而是数字矩阵(章节 2~3)。第二,从这些数字中寻找边缘之类线索的滤波器,以及人工设定线索的局限(章节 4~6)。
数字示例在整个系列中都用同一张吉娃娃照片(4-4 的主角)来演示,因为像素和滤波器对任何照片的作用方式都一样。动手实践中可以在猫·人·狗·吉娃娃·松饼五张照片中任意选择。
对人简单的问题,对计算机不一定简单。人看到照片的瞬间就能察觉“有毛”“耳朵是尖的”,而计算机必须从数字中把这些线索一个个算出来。猫 vs 人的线索比较明显,很适合作为图像分类的第一道练习。
照片是数字网格,彩色照片是三张这样的网格叠在一起。模型输入的最小单位是一个通道值(0~255)。
数码照片是由横竖细密划分的小格子组成的。其中一个格子叫作像素(pixel,picture element)。一个像素只包含一种颜色,这种颜色用红(R)·绿(G)·蓝(B)三种光的强度来记录。强度是从 0(没有光)到 255(最亮)的整数。所以彩色照片就是排列着高 × 宽 × 3 个数字的表,也就是矩阵(准确地说是 3 层的张量)。
简单来说就像方格纸涂色游戏。把每个方格里分别放了几滴红·绿·蓝三种颜料,用 0~255 记下来,那么任何人只凭这张纸条就能涂出同样的画。计算机拥有的不是画,而是这张纸条。
把照片不断拆分,就会一路降到一个像素、其中的 R·G·B 数字,以及构成一个数字的八个比特。比特是计算机存储的最小单位,但一个比特既不是颜色也不是亮度,只是开/关而已。
所以在图像深度学习中,具有意义的最小信息是一个通道值,也就是“这一格的红色强度是 39”这样的数字。模型的第一层接收的正是这些数字(X[y, x, c])。
但这一个数字里完全没有“吉娃娃”的含义。眼睛的像素 (39, 37, 43) 和蓝莓的像素 (37, 31, 37) 从数字上看几乎一样。含义来自许多像素如何聚在一起,而寻找这种组合的,就是章节 4 的特征提取。
这是把吉娃娃照片横竖各切成 14 格,选出眼睛的一格并把它变成数字的过程。右边的数字是根据照片的真实像素计算出来的值。
选择照片和分辨率,然后点击图中的格子或把鼠标移上去。旁边(手机上在下方)的表格显示所选格子及其周围 7 × 7 格的真实数字。点击图片后,可以用方向键移动格子。
Q1. 一张横 10 格、竖 10 格的彩色照片里有多少个数字?
Q2. 像素值 (R, G, B) = (0, 0, 0) 是什么颜色?
Q3. 把同一张照片向右平移两格,同一位置的数字会怎样?
Q4. 图像深度学习模型输入的最小信息是什么?
像素是组成照片的小格子,每格用 0~255 的数字记录红·绿·蓝光的强度。用 4-1 的表格来类比,一张照片就是有“高 × 宽 × 3”格的一行。在像素放大镜里点击格子确认真实的数字,再改变分辨率,看看数字的个数如何变化。
把两张照片同一位置的数字相减来测距离,能量出“相似”吗?把同一只吉娃娃平移或调暗,再把五张照片两两之间的距离全部测一遍。
两张照片的像素距离,是把同一位置的灰度数字相减后平方、取平均、再开平方根得到的值(0 表示完全相同)。试着把吉娃娃向旁边平移或调暗。在人眼看来它仍然是同一只吉娃娃,但从数字上看,有时它甚至比松饼离得更远。
我们测量了本页五张照片两两之间的像素距离。数字越小,就表示计算结果越“相似”。最小的值已标上颜色。
这张表的值是用本页的五张照片(只裁出脸部并缩小到 56 × 56)测得的。换用其他照片,值会随背景·光照·构图而大幅变化,但“像素距离与含义上的距离不同”这一结论,在真实照片中也是广为人知的性质。
代码 1 把 scikit-image 自带的猫照片(chelsea)和人照片(astronaut)的脸部缩小到 56 × 56,做同样的实验。同一只猫平移 1 格时距离为 16.9,2 格为 27.1,8 格增大到 40.5,而猫和人之间的距离是 85.3。只平移几格,距离就接近与另一种动物之间距离的一半。
像素距离只衡量“同一位置的数字是否相近”。所以它对位置·亮度·构图很敏感,却不知道照片里拍的是什么。这一局限正是需要章节 4 的滤波器和 4-3 的 CNN 的原因。
4-1 的 k-NN 是向“近邻”提问的。要在照片上做同样的事,照片之间的距离就必须反映含义。可是按像素距离,吉娃娃离松饼比离同为狗的金毛寻回犬还近,而同一只吉娃娃只要平移 4 格,就比松饼离得更远。这说明在照片中不能用原始像素距离来寻找近邻。
把 3 × 3 的数字表(滤波器)在照片上滑动,逐位相乘再相加。与图案相似的地方得到大数,把这些结果汇总起来就是特征图。
特征是由许多像素共同构成的模式,比如“这里先亮后突然变暗(边缘)”“比周围暗成一个圆(点)”“细线密密排列(毛的纹理)”。CNN 把 3 × 3 这样的小数字表,即滤波器(卷积核),放在照片上一格一格地滑动,把重叠的数字两两相乘再全部相加。与滤波器图案相似的地方得到大数,其他地方得到小数,把这些结果汇总成的新矩阵就是特征图。这种计算叫作卷积。
简单来说就像找图案印章的游戏。拿一枚刻着“左边暗、右边亮”图案的印章,在照片上的每个位置都比一比,图案吻合得好的位置就记下高分。分数表填满后,照片中的竖直边缘在哪里就一目了然。换一枚印章,要找的图案也随之改变。
滤波器就是用数字写下的“想找的图案”。左列为 −1、右列为 +1 的滤波器,右边比左边越亮,输出的数就越大。所以在吉娃娃的眼睛(暗)和毛发(亮)之间的竖直边缘上,会得到 302 这样的大值,而在只有毛发的平坦区域,得到的值接近 0。
重要的是,同一个滤波器会在照片的所有位置重复使用。一个滤波器只有 9 个数字,却能找出照片中任何位置的边缘。章节 3 中看到的“只平移一格所有数字都变了”的问题也会减轻。因为照片平移时,特征图也只是跟着平移,边缘存在这一事实并没有改变。
真实 CNN 的第一层会使用几十个这样的滤波器。每个滤波器输出一张特征图,所以输出是“照片大小 × 滤波器个数”的厚矩阵。
在吉娃娃眼睛附近的灰度 8 × 8 小块(从缩小到 28 × 28 的照片中裁出)上,把竖直边缘滤波器一格一格地放上去。蓝色数字表示“右边更亮”,橙色数字表示“左边更亮”。
选择照片和滤波器。也可以直接修改滤波器格子里的数字。右边特征图中亮的地方就是“找到图案的地方”。点击特征图的格子,下方会显示该位置的计算过程。为了让输出大小保持 56 × 56,边缘之外用复制最近的边缘像素的方式填充。这与 3 号示意图中的补 0 填充方式不同,因此边框格子的值可能与补 0 时不同。
Q1. 卷积中,滤波器在一个位置的值是怎么得到的?
Q2. 在所有格子都是 10 的平坦小块上应用竖直边缘滤波器 [−1 0 1]×3,结果是?
Q3. 对 56 × 56 的特征图做 2 × 2 最大池化,大小变为?
Q4. CNN 滤波器里的数字是谁决定的?
卷积就是把 4-1 感知机的加权和(w·x + b)在照片的每个小块上反复计算。滤波器的 9 个数字就是权重;由于同一个滤波器会在照片的所有位置重复使用,所以不管眼睛在哪里,都能用同样的方式找到。在代码 2 中,我们会确认手算结果与 scipy 的结果一致,并看到:把手写数字平移 2 格后,直接使用像素的神经网络准确率跌到 14.2%,而小型 CNN 仍保持 90.4%。
在深度学习之前,由人来决定“测量什么”。本节看看这种方法的优点,以及照片一变判断就会翻转的局限。
第 1 节的图片。绿色框是“这里有一张脸”的检测结果,红点是下颌线、眉毛、嘴唇轮廓上的人脸特征点,粉色点是双眼、鼻子、嘴的核心位置。猫脸上的红线是连接额头、眼睛和鼻子的面部骨架。
像“两眼间距”“耳尖角度”这样,由人先决定要测量什么。
滤波器数字 K 一开始设为随机值,再由训练朝着答对的方向修正。
请切换到“边缘强度”视图。有意思的是,整张照片的平均边缘强度两者几乎相同。因为人像照片的长发里也有很多细线。区别在于边缘位于哪里。猫的毛纹和条纹一直密布到脸部正中,而人的脸颊和额头很光滑,边缘集中在眼睛、鼻子、嘴和头发上。下方“中间区域”的数值显示了这一差异。这正是我们需要按位置排列的地图——也就是特征图——而不是一个平均数的原因。
第 3 层左右的局部特征也区分得很清楚。头顶尖尖的三角形耳朵、额头的条纹、小小的粉色鼻子和长长的胡须,人脸上都没有。第 1 节图片中的红线和红点是人直接设定这些线索的方式,而 CNN 则用滤波器自己找到同样的线索。
在第 3 节的表中,猫与人的灰度像素距离和猫与狗的距离处于相近的水平。对人来说这是最容易的一组对决,但像素距离却显示不出这种差异。这是像素距离不懂含义的又一个证据。
在上面的成对比较中,用本页的照片测得猫的中间边缘更大。但在代码 1 中用 scikit-image 的猫和人照片来测,结果却相反(脸部边缘强度:猫 101.5,人 123.6)。这是因为人像照片中的头发和笑着露出的牙齿形成了很强的边缘。
像“边缘多就是猫”这样人为设定的单一特征,照片一换就很容易翻转。所以我们需要的不是一个特征,而是多个特征的组合,而且要从数据中学习。这就是 4-3 的主题。
人为设定的特征容易解释“为什么这样判断”,数据少也能工作。但人必须事先知道,而且照片条件一变就容易失效。请在成对比较中切换到“边缘强度”视图,比较猫和人的边缘集中在哪里。
第一层的滤波器寻找线条和边缘。叠加层之后,线条组合成角,角组合成眼睛和耳朵,眼睛和耳朵组合成脸。
用池化逐步缩小照片并叠加层,后面层的一格就能看到原始照片中更大的区域。所以前面的层寻找小线条,后面的层寻找由线条组合成的眼睛和耳朵,更后面的层寻找整张脸。这张图把 Zeiler 和 Fergus(2014)可视化训练好的 CNN 各层反应时展示的趋势做了简化。
用池化逐步缩小照片并叠加层,后面层的一格就能看到原始照片中更大的区域。所以前面的层寻找小线条,后面的层寻找这些线条的组合 [R8]。在 4-3 中,我们会看到叠加这些层的 CNN 如何输出概率,以及为什么叠加层之后,原本一个平面分不开的东西就能分开了。
两段代码都只使用 Colab 默认安装的库和内置数据。点击“下载笔记本(.ipynb)”后,在 Colab 中通过文件 → 上传笔记本打开,或者复制后粘贴到新笔记本的单元格中。
查看 scikit-image 自带的猫和人照片的形状与像素值,计算灰度亮度、像素距离和边缘强度。想换成自己的数据,就用 io.imread 读取自己的照片,并把 small() 的(上、左、边长)改成脸的位置。
手算 3 × 3 竖直边缘滤波器的卷积并与 scipy 对照,再在把手写数字平移 1~2 格的测试照片上比较 MLP 和小型 CNN。
这是粘贴到 ChatGPT、Qwen、Claude 等 AI 助手中的提示词。点击“复制”,所选代码会一起附在提示词后面。把〔 〕里的内容换成你自己的情况即可。
AI 的回答只是起点。它推荐的论文·数值·库函数一定要对照原文和官方文档核实。如果在竞赛·论文中得到了 AI 的帮助,要按照主办方和期刊的规定说明使用的事实和范围。
与正文中黄色虚线下划线对应的词典。整个系列使用相同的写法。点击章节名可以跳到首次出现的位置。
类比是理解的第一步,但也可能成为误解的种子。人眼·人脑类比标注了对应程度。直接 有依据表明确实在做同样的事 · 部分 只有部分性质相似 · 无 尚未发现对应的东西
| 概念 | 日常类比 | 人眼·人脑类比 | 类比不成立的地方 |
|---|---|---|---|
| 像素 | 一块马赛克瓷砖 | 部分 眼睛的视网膜上也密布着感光细胞 | 视网膜上的细胞并不是均匀排成网格,而是集中在中央(中央凹),色觉细胞的种类和比例也各不相同 |
| 卷积滤波器 | 刻着花纹的印章 | 部分 视觉皮层的简单细胞会对特定方向的边缘产生强烈反应 | 大脑细胞的学习方式和连接要复杂得多。CNN 滤波器在所有位置重复使用同样的数字,而大脑并非如此 |
| 特征图 | 藏宝图上的 X 标记 | 无 | 地图只有一张,而实际的层里有和滤波器数量一样多的特征图层层叠在一起 |
| 池化 | 选班级代表 | 无 | 班级代表由人来选,而最大池化是机械地选出数字最大的那一格 |
| 人脸特征点 | 地图上的路标 | 无 | 路标由人来立,而特征点的位置是训练好的模型针对每张照片计算出来的。被遮挡时会标到错误的位置 |
E-1 作者简介 · E-2 学术参考文献 · E-3 图片·数据参考资料
这是给讲师、在职培训(OJT)负责人和辅导老师的运营指南。时间为预估值,请根据实际课堂进行调整。
| 对象 | 学完 4-1 的大学生和职场人士;想了解图像 AI“如何接收照片”的从业者 |
|---|---|
| 预备知识 | 4-1 的特征、目标值与加权和,乘法与加法 |
| 学习目标 | ① 计算彩色照片的形状(H × W × 3)和数字个数 ② 手算一格 3 × 3 卷积 ③ 举例说明像素距离和人为设定特征的局限 |
| 预计时间 | 阅读 40~50 分钟 · 实践演示 25 分钟 · Colab 实践 25 分钟(代码 1 10 分钟,代码 2 运行 1 分钟 + 解读 14 分钟) |
导入 5 分钟(第 1 节)→ 第 2 节像素放大镜 15 分钟 → 第 3 节平移实验 10 分钟 → 第 4 节卷积手算 15 分钟 → 小测验 5 分钟。
用第 2 节计算本单位业务照片(次品、文件扫描件等)的分辨率和数字个数 20 分钟 → 在第 4 节滤波器实验室里找出适合自己照片的滤波器 25 分钟 → 第 5 节讨论人为设定特征的局限 15 分钟 → 代码 2 运行与解读 30 分钟。
入门者只学第 1·2·4 节。中级者把第 4 节的输出尺寸公式改为含填充和步幅的形式来计算,并预测在代码 2 的 CNN 中把 GlobalMaxPooling 换成 Flatten 后,对平移的稳健性会怎样变化。
| 章节 | 停下来提的问题 | 操作技巧 |
|---|---|---|
| 1 问题 | “人是看到什么才知道这是猫的?” | 指出线条和点是人为设定的线索 |
| 2 像素 | “眼睛那一格的三个数字是什么?” | 在像素放大镜中把分辨率从 7 改到 56 |
| 3 像素距离 | “明明是同一只吉娃娃,为什么比松饼还远?” | 把平移滑块拖到 4 格以上 |
| 4 卷积 | “在平坦的毛发小块上盖竖直边缘滤波器,会怎样?” | 把动画停在“全部相加”,再动手算一遍核对 |
| 5 人为设定的特征 | “边缘多就是猫”总是对的吗? | 把成对比较的边缘强度视图和代码 1 的结果放在一起看 |
| 6 后面的层 | “找眼睛的滤波器在第几层?” | 从左到右逐一讲解分层图 |
| 误解 | 正确解释 | 要展示的画面 |
|---|---|---|
| 照片是图片文件,和数字不一样 | 对计算机来说,照片就是 H × W × 3 个 0~255 的数字 | 第 2 节像素放大镜 |
| 像素相近,拍到的就是同一个东西 | 只平移一格,距离就会大变。像素距离不懂含义 | 第 3 节平移实验 |
| 卷积是复杂的数学 | 只不过是把重叠的 9 对数相乘再相加。和感知机的加权和一样 | 第 4 节的数字示例 |
| 滤波器由人设计 | 实践中的滤波器只是示例。CNN 从数据中学习滤波器的数字 | 第 4 节小测验 Q4 |
| 人为设定的特征毫无用处 | 容易解释,数据少也能用。只是条件一变就不稳健 | 第 5 节与代码 1 中翻转的结果 |
彩色 56 × 56 × 3 = 9,408 个,灰度 56 × 56 = 3,136 个。
0.299×39 + 0.587×37 + 0.114×43 = 11.661 + 21.719 + 4.902 ≈ 38.3.
(174−92) + (137−38) + (176−55) = 82 + 99 + 121 = 302。这是右侧较亮的强边缘。
56 − 3 + 1 = 54,即 54 × 54。加填充 1 则保持 56 × 56。
一是在所有位置重复使用同一个滤波器的卷积(位置变了也能找到同样的花纹),二是丢掉位置、只保留最大反应的全局最大池化。
在代码 1 中读取自己的人脸照片(或宠物照片),输出形状和数字个数,并把平移 1·2·4 格时的像素距离整理成表格。
把代码 2 的 CNN 中的 GlobalMaxPooling2D 换成 Flatten 重新训练,用 3 个种子报告平移 1·2 格照片的准确率变化。结合第 4 节的解读写出原因。
| 入门者 | 第 3 节的距离表和第 6 节可以跳过。只要把第 2·4 节的实践扎实做一遍即可 |
|---|---|
| 进阶 | 让学生调查 Haar 特征和 HOG,并在第 4 节的滤波器实验室里做出类似的滤波器。调查到的论文要查阅原文确认 |
| 延伸学习 | 3-3 图像与 CNN · 4-3 猫 vs 狗(CNN 整体结构) |
| 讲师用资料 | 小测验的评分标准和作业参考答案可在教师用答案页(4-2)中查看 |
你已经读完了《4-2 猫 vs 人》这一篇。实验室的伙伴们各用一句话为你总结。