第 1 课:先认识输入、计算和输出。 本篇通过手算和示意性例子建立直观认识,不需要先写代码。文中的分数用于解释计算过程,不代表真实模型的训练成绩。
先看一个具体问题
假设我们想让程序判断一张图片里主要是汽车还是飞机。初学阶段先不考虑检测位置,也不考虑同时存在多个目标:输入一张图,输出这两个类别中的一个。这叫单标签图像分类。
人看到图片时会自然利用轮廓、部件和已有经验。计算机最初拿到的却只是文件里的数据。我们需要一条明确的处理链路,而不是一个写着“智能识别”的黑盒按钮。
|
本篇只要求理解这条链路。Python 语法、张量、卷积分别放到后面的课,不需要现在一次记住。
图片文件与模型输入不是同一个东西
JPEG 文件包含压缩编码。解码后得到的像素可以按行、列和颜色通道访问。模型一般处理已经整理好的数字数组,而不是直接对 JPEG 文件头做分类。
例如,一张宽 32、高 32 的 RGB 图片有 32 × 32 × 3 = 3072 个通道值。把它缩放、转换为浮点数或调换轴顺序,都是为了满足模型输入约定。这些操作不等于训练,也没有让图片自动变聪明。
训练时如果使用 RGB、固定尺寸和某种数值缩放,使用模型时也要一致。摄像头输出的是 BGR,如果仍按 RGB 解释,即使程序没有报错,也可能得到明显不同的结果。
模型可以先理解为结构加参数
结构规定数字经过哪些运算,参数规定这些运算中的可调数值。一个最小例子是 y = w × x + b:乘法和加法组成结构,w 与 b 是参数。
假设 x=2、w=3、b=1,输出就是 7。把 w 换成 4,输入没有变,输出变成 9。真实网络有许多参数和非线性运算,但“固定输入与参数,通过计算得到输出”的基本关系仍然存在。
参数不是人手工填写的“飞机规则表”。训练过程根据样本和目标调整参数,使模型在指定任务上减少误差。模型文件保存参数等信息,推理程序负责加载参数并按结构运行计算;只下载一个文件,还构不成一个完整的系统。
一次输出怎样变成类别
假设我们约定类别顺序是 [飞机, 汽车],模型给出两个分数 [1.2, 2.8]。第二个分数更大,程序便输出“汽车”。这只是一次示意计算,不是某个真实模型的预测记录。
若把类别表错误地改成 [汽车, 飞机],同一组分数就会被解释成“飞机”。所以模型正确不代表外围代码一定正确,类别顺序也是接口的一部分。
分数不一定落在 0~1 之间。后面会接触到 logits 和 Softmax;现在只需知道“输出原始分数”“转换分数”“选择类别”是可以分开的步骤。
训练与推理分别做什么
训练时提供图片和已知标签,比较预测与目标,计算误差,再更新参数。推理时使用已经确定的参数处理新输入,普通推理不会因为看了几张新图就自动学会新类别。
| 环节 | 是否需要目标标签 | 是否更新参数 |
|---|---|---|
| 训练 | 这里的监督分类训练需要 | 是 |
| 验证与测试 | 计算正确率时需要 | 否 |
| 实际推理 | 通常不知道正确答案 | 否 |
一个网络即使参数随机,也能产生分数;有输出不等于识别有效。训练集上的成绩好,也不保证陌生光照、背景和视角下仍然好,这就是后面学习数据划分与泛化的原因。
一个贯穿后续课程的任务
前几课用像素和横竖条纹建立计算基础。进入真实分类时,我们采用 CIFAR-10 中飞机和汽车的二分类子集,主要为了保持输入小、任务明确。小尺寸公开图片不能代替摄像头现场数据,这个实验也不是产品级模型。
整个系列逐步补齐输入、计算、学习、评估、保存和转换。检测、分割与 Transformer 在分类闭环之后再学习,最后回看历史总览。遇到新术语时先找它在链路中的位置,再学习具体实现。
自己解释一遍
- 参数随机的模型能输出分数吗?能否据此说它会识别?
- 模型输出不变,交换类别名称顺序会发生什么?
- 将像素除以 255 属于训练还是输入处理?
参考答案
能计算分数,但有效性要用有标注样本评估。交换名称会改变类别解释,可能把原本正确的结果解释成错误标签。对原本在 0~255 范围内的像素值,除以 255 会将其缩放到 0~1,属于输入处理中的归一化,不会更新模型参数。并非所有模型都统一采用这种处理方式,应遵循模型的输入约定。
下一课进入已有的《Python 起步》。本篇学完的标准是能用自己的话说清“图片经过什么、参数来自哪里、结果怎样解释”。
学习记录
2026-10-18:完成本篇阅读与三道练习。已经能够说明:随机参数可以产生分数,但不能据此认定模型具备识别能力;输出不变时,交换类别名称会改变结果解释;像素除以 255 属于输入归一化,不属于训练。
配套代码练习
实验:结构、参数与一次推理
查看完整代码:main.py
"""结构、参数与一次推理。运行方式与练习见 README.md。"""
classes = ['airplane', 'automobile']
# 构造的两个特征:天空比例、轮子响应;不是训练得到的视觉特征。
features = [0.8, 0.1]
weights = [[2.0, -1.0], [-1.0, 2.0]]
def predict(x, w):
scores = [sum(a*b for a,b in zip(row,x)) for row in w]
return scores, classes[max(range(len(scores)), key=scores.__getitem__)]
scores, name = predict(features, weights)
print('features:', features, 'scores:', scores, 'class:', name)
assert name == 'airplane'
changed = list(reversed(weights))
assert predict(features, changed)[1] == 'automobile'
print('同样的结构,更换参数后:', predict(features, changed))
在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。
cd 'content/posts/AI-深度学习/从零搭建视觉模型/01-图片进入模型后发生了什么/code' && python3 main.py
本篇已附独立实验包,在代码卡片中查看源码、下载或复制运行命令。解压后执行 python3 main.py;依赖安装见包内 README.md。
观察目标: 原始参数预测 airplane;交换两行权重后预测 automobile。
动手修改: 只改变输入特征为 [0.1, 0.8],预测如何变化?再交换类别名称,解释参数和类别映射为什么都要保存。
所有输入均在本篇代码中构造;运行范围和验证记录见包内 verification.md。
