清单:本课共出现 9 处数学
| # | 数学 | 对应代码 | 一句话 |
|---|---|---|---|
| 1 | 归一化 | images / 255.0 | 把 0~255 压到 0~1,只换刻度 |
| 2 | 加权求和 | y = w·x + b | 话语权×输入+保底分 |
| 3 | 多分类输出 | Dense(10)、logits | 十个各报一分,最高者当选 |
| 4 | 数参数 | summary 7850 | 784×10+10,手算可验证 |
| 5 | 交叉熵 | SparseCategoricalCrossentropy | 打分尺:−log p |
| 6 | 准确率 | metrics=['accuracy'] | 猜对比例,顺带看 |
| 7 | 训练循环 | fit / epochs=5 / adam | 刷 5 遍,每批调一次权重 |
| 8 | 学习曲线 | history 双线图 | 训练降、验证升 = 背答案 |
| 9 | 变体 | Dense(64, relu) | 多一层,参数到 50890 |
形状口径:输入 (60000,28,28)/(10000,28,28),展平后 784 维;输出 (batch,10)。参数口径:7850 / 约80% / 50890→约87%。
1 · 归一化:为什么除以 255
物理意义:7 万张灰度图,每个像素记录一点的光强。imshow(..., cmap='gray') 按“数字越大、图上越白”的约定回译为黑白:0~255 是光的强度刻度,不是抽象编号。
在干什么:等比压缩刻度。0 还是 0,255 变成 1,中间灰落进 0~1。亮暗顺序不变——原来更亮的,压缩后依然更亮。模型看到的从“第几级灰”变成“几成白”。
为什么必须做(三层):
- 输入大 → 输出大。模型算
y = w·x + b,w初始约 0.1 量级。若x最大 255,y可达数十;归一化后y落在个位数以内。 - 输出大 → loss 大。loss 核心是
−log p。logits 相差数十时 softmax 饱和,初始损失可爆到十几(随机猜测的理论初值约为 −log(0.1)≈2.3,训练后降至 0.4 左右)。看到“十几”即未归一化的信号。 - loss 大 → 更新乱。梯度范数随输入同比例放大,默认学习率(约 1e-3)下单步过大,来回震荡、收敛困难。
为什么是 255:255 是该亮度刻度的天花板。除以天花板即算出“几成白”:0→0,255→1,约127→约0.5。除以 127.5 再减 1 可得 −1~1(另一种合法刻度);按均值方差标准化有时更好,但多两步。本课取最省且够用的。关键是训练与验证除以同一个数,否则为分布偏移。
2 · 神经元:y = w·x + b
投票直觉:784 个像素是 784 个证人,各看一点。领口发白的喊“像上衣!”,边缘全黑的说“我没看见”——其 x=0,乘以任何权重仍为 0,天然弃权。w 是话语权(关键部位大、背景趋近 0),b 是保底分(闭眼先垫的类别先验)。
这是线性回归 y = mx + b 的 784 维版本。正因输入已压到 0~1,“几成白×话语权”才量级合理;否则一个纯白点(255)一票顶几百票。
学习是什么:猜错即查谁误导判决:误导者调小、说对者调大,偏置同步校准。6 万样本 ×5 轮 ≈ 30 万次样本级梯度贡献(按 batch 聚合为每轮 1875 次参数更新,以 batch=32 计),全部围绕这一公式反复修正。
3 · 十个神经元并排:logits、argmax 与 softmax
十个评委:输出是数字、任务是分类,中间差一步拍板。设十个评委一类一个,各按自己的一套权重打分,最高者当选。这就是 Dense(10)——十路并排,各算各的 y。单张输入 (28,28) 须带 batch 维 (1,28,28) 方可预测。
logits:十个原始分数,可正可负。柱状图摆在一起,最高柱即判决。要概率则过 softmax:
4 · 数参数:784×10 + 10 = 7850
大脑有多重:每参数 float32 约 4 字节,7850 个 ≈ 30.66KB——比一张手机照片轻一百多倍。整个能力载体就是这 7850 个小数。
每个像素对十类各一份权重,故 784×10;每类各一个偏置,故 +10。权重就是学到的全部东西——“70 亿参数”与此处同一概念、不同量级。
总数 = ≈ 30.7KB
5 · 损失函数:−log p,越自信的错越贵
| 赋予正确的概率 p | loss | 含义 |
|---|---|---|
| 0.9 | 约 0.11 | 接近答对,梯度小 |
| 0.5 | 约 0.69 | 不确定,中等梯度 |
| 0.1 | 约 2.3 | 确信错误,大梯度强修正 |
| → 0 | → +∞ | 以全确信答错,惩罚无上界 |
严格性质:交叉熵对 logits 的梯度为 p − y_true(预测分布减真实独热)。分错的概率质量越多,回传信号越大——即“越自信的错越贵”的严格形式。概率总和为 1 决定了给错类一分即从正确类抢走一分。衬衫认成 T 恤时两类概率双高,损失照样重罚:只计量分错,不问缘由。
6 · 准确率 accuracy:人类可读的顺带指标
两本账:loss 是精密量尺(小数点后两位),accuracy 是门口光荣榜(百分之几)。优化器只认量尺。若量尺下降而榜单不动,表明概率校准改善但决策边界未移动(阈值或数据问题),应停查。以验证集 accuracy 为准(约 80%,±2% 正常):人类约 83~85%,衬衫/T恤本就易混,80% 已是线性模型的合理位置。
7 · 训练:epoch、梯度与 Adam
刷题与改错:梯度是错题批注(每个权重该调大还是调小);学习率是步子。输入未归一化时步子相对过大,来回震荡;Adam 对难改的慢改、好改的快改。归一化正是为了让笔的力度合适。
epoch:完整遍历 6 万样本一次为 1 epoch,本课 5 轮。每轮后用 1 万验证样本前向评估一次,只打分、不产生梯度——即“考试不讲评”的严格实现。以 batch=32 计,每轮约 1875 次更新。
seed = 42:初始权重与样本 shuffling 的固定取值。全场同一种子,结果可比;不固定则期望相近、单次方差稍大。课堂演示要的是可比,不是运气。初始权重常用 Glorot 均匀,量级约 0.1。
# 编译:绑定优化器 + 损失 + 监控;fit:前向→算损→反向→更新
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(train_images, train_labels, epochs=5, verbose=2,
validation_data=(valid_images, valid_labels))
8 · 学习曲线:怎么看出“背答案”
真学会还是背答案:两种拿高分法——搞懂规律,或背下练习册。区分唯有出新题。训练线是练习分,验证线是新题分:
| 现象 | 解读 |
|---|---|
| 两条线都向好(损失降、准确率升) | 有效泛化 |
| 训练 loss 降、验证 loss 升 | 过拟合:在背练习题 |
| 两条线都不动 | 欠拟合:检查归一化、学习率、结构 |
# history.history 含 loss / val_loss / accuracy / val_accuracy 四条序列,须对照看
plt.plot(history.history['loss'], label='训练'); plt.plot(history.history['val_loss'], label='验证')
9 · 变体:加一层 Dense(64, relu),参数量 50890
从直线到折线:原模型决策边界为线性,袖子拐弯即跟不上。加 64 个中间单元:各先对 784 维加权求和,再过 ReLU——为负归零(当没看见),为正保留。这相当于 64 个初审:只上报“有点像”,最后十类只看初审意见拍板。非线性即源于此;其导数为阶跃函数(正区间 1、负区间 0),反向可传导。
参数多约 6.5 倍(仍不足 1MB),CPU 数分钟,分数上涨——数据与规则不变,仅假设空间扩大。再往上需卷积(利用平移不变性),此处不展开。