MIT深度学习课程第三讲:Keras训练实践与图像分类入门
本节课分为两部分:
- 使用
Keras和Colab实际训练一个心脏病预测模型。 - 转入计算机视觉,介绍图像如何表示,并开始搭建图像分类模型。
老师强调,本节课会真正进入 Colab 实操。前半部分承接上一节神经网络训练的理论,后半部分为后续图像分类和彩色图像处理做准备。
一、本节课安排
本节课计划做两个 Colab:
- 第一个
Colab:训练一个用于心脏病预测的Keras模型。 - 第二个
Colab:开始处理图像分类问题。
心脏病预测问题来自前面课程已经介绍过的数据集。图像分类部分会从数字图像的表示讲起,再进入 Fashion-MNIST 数据集。
二、神经网络训练流程回顾
老师先回顾上一节课的核心思想:训练神经网络,本质上和训练其他机器学习模型没有根本区别。
神经网络中有一组参数:
weightsbiases
训练的目标是使用数据找到一组好的参数。
这里的“好”通常指:
模型预测值与真实答案之间的差异尽可能小。
这个差异由 loss function 衡量。
整体训练流程可以概括为:
- 定义一个网络结构。
- 输入数据经过多层网络。
- 网络输出预测值。
- 将预测值与真实值一起送入
loss function。 - 得到一个
loss score。 optimizer计算 loss 对所有参数的梯度。- 使用梯度更新
weights和biases。 - 重复这个过程。
因此,训练循环中的核心对象是:
networkpredictionground truthloss functionoptimizergradientparameter update
三、Gradient Descent 与 Stochastic Gradient Descent
上一节课介绍过 gradient descent。
在普通 gradient descent 中,每次迭代会使用所有训练样本:
- 所有数据点都通过网络。
- 对所有数据点计算预测值。
- 计算整体 loss。
- 计算 loss 对参数的梯度。
- 用梯度更新参数。
老师指出,实际训练中更常使用 stochastic gradient descent,简称 SGD。
SGD 的思路是:
不一次使用全部数据,而是随机选择一小部分样本,把它们暂时当成当前拥有的全部数据,基于这部分样本计算预测、loss、gradient,并更新参数。
这种小批量样本在技术上叫 minibatch。老师说明,后面会直接把它称为 batch,这也是文献和实践中常见的简化说法。
四、Epoch 的定义
epoch 指的是:
对整个训练集完成一次完整遍历。
也就是说,所有训练样本都至少被送入网络一次。
在普通 gradient descent 中:
- 一个
epoch使用所有训练样本。 - 在这个
epoch结束时计算一次梯度。 - 参数只更新一次。
老师提到,梯度可以写成:
d loss / dW也可以用 nabla 符号表示。这些都是表示 loss 关于参数的梯度。
如果数据集有 10 billion 个样本,普通 gradient descent 会让所有样本都通过网络,得到所有输出后,再在 epoch 末尾进行一次参数更新。
五、SGD 中的 Batch 与 Epoch
在 SGD 中,训练数据会被分成多个 batches。
一个 epoch 的过程是:
- 将训练集分成
batch 1、batch 2,直到最后一个 batch。 - 对
batch 1做一次前向传播,得到预测值。 - 计算 loss 和 gradient。
- 更新参数。
- 用更新后的参数处理
batch 2。 - 持续处理所有 batches。
- 所有训练数据都被处理一遍后,一个 epoch 结束。
因此,在 SGD 中:
一个 epoch 内会发生多次参数更新,更新次数等于 batch 数量。
老师举例:
- 如果一个 batch 有
32个样本。 - 处理完第一个 batch 后,网络参数已经更新。
- 第二个 batch 使用的已经是更新后的参数。
这也是 SGD 的重要优势:不必等所有数据都处理完才更新,而是边看数据边更新。
六、Batch 数量如何计算
在一个 epoch 中,batch 数量由训练集大小和 batch size 决定。
公式可以理解为:
number_of_batches = ceil(training_set_size / batch_size)老师强调,batch size 是建模者选择的。
常见默认值包括:
3264
这些值常用的原因之一是它们与并行硬件的计算方式比较匹配。
Keras 会自动计算实际 batch 数量,建模者不需要手动管理每个 batch。但老师强调,仍然应该理解细节,因为只有概念足够清楚,后续遇到新问题时才能真正操作这些概念,而不是只会运行默认代码。
课堂示例:
- 训练集大约有
194个患者。 batch size = 32194 / 32约等于6.x- 向上取整后得到
7个 batches。
于是:
- 前
6个 batch 各有32个样本。 - 最后一个 batch 只剩下少量样本,例如
2个。
老师指出,最后一个 batch 不需要和前面的 batch 一样大。
七、关于 Batch 与 Epoch 的课堂问答
7.1 Batch 是取部分变量还是部分数据
学生问:SGD 中只取一部分,是取部分变量,还是取部分数据?
老师回答:
取的是部分 rows,也就是部分 data points。
例如:
1000个患者样本中取32个患者。1000张图片中取32张图片。
这 32 个样本构成一个 batch。
不是只取部分特征列,也不是只取网络的一部分。
7.2 每个 Batch 是否都会更新权重
学生问:每次处理 batch 时,是否都会更新当前权重?
老师回答:会。
处理每个 batch 后,都会根据该 batch 计算出的 gradient 更新参数。
因此,训练过程是在不断“边走边修正”。
7.3 Epoch 不是 Loss Function
学生把 epoch 理解成正在求的 loss function。
老师纠正:
epoch不是 loss function,而是对训练数据完成一次完整遍历。
在 SGD 中,一个 epoch 内有多个 batches,也就有多次参数更新。
7.4 每个 Batch 是否经过整个网络
学生问:一个 batch 是经过整个网络,还是只经过某一层?
老师回答:
每个 batch 都要经过整个网络。
原因是:
- 不经过整个网络,就得不到预测值。
- 没有预测值,就无法计算 loss。
- 没有 loss,就无法计算 gradient。
- 没有 gradient,就无法更新 weights。
7.5 普通 Gradient Descent 与 SGD 的更新次数
在普通 gradient descent 中:
- 一个 epoch 是一次完整遍历。
- 一个 epoch 只做一次权重更新。
在 SGD 中:
- 一个 epoch 仍然是一次完整遍历。
- 但每个 batch 之后都会更新一次。
- 更新次数等于
ceil(training_set_size / batch_size)。
7.6 SGD 的优势
学生总结:使用 SGD 的优势是,处理完第一个 batch 后,第二个 batch 已经可以使用更好的系数。
老师确认这个理解是正确的。
虽然单个 batch 只是数据的一小部分,梯度估计不如全量数据精确,但通常仍能朝着正确方向更新。这样可以避免等待整个数据集处理完再更新。
学生问:SGD 是得到更好的解,还是节省计算?
老师回答:两者都有。具体原因已在上一讲中讨论。
八、Overfitting、Underfitting 与 Regularization
进入 Colab 前,老师补充了 overfitting 和 regularization。
当模型越来越复杂时,训练集误差通常会下降。
例如:
- 简单回归模型有一定误差。
- 加入 interaction terms、logarithms 等复杂变换后,训练集误差通常下降。
但模型复杂度继续增加时,验证集或真实泛化表现可能会先变好,再变差。
这对应三个区域:
underfitting:模型还太简单,仍有明显改进空间。- 合适区域:模型复杂度与数据模式匹配。
overfitting:模型开始拟合训练数据中的偶然性和特殊细节,而不是可泛化规律。
目标是找到中间的 sweet spot。
九、神经网络为什么容易 Overfit
在神经网络中,模型需要学习输入数据的 representations。
为了学习复杂 representation,通常会增加网络层数和参数数量。
老师举例,GPT-3 大约有 96 层。
一般来说:
- 层数越多,表达能力越强。
- 层数越多,参数越多。
- 参数越多,模型复杂度越高。
- 模型复杂度越高,
overfitting风险越大。
因此,神经网络训练中特别需要考虑 regularization。
regularization 的目标是:
降低过拟合风险,让模型既能拟合数据,又不过度贴合训练集中的噪声。
十、Early Stopping
本节课会用到的第一种 regularization 方法是 early stopping。
老师提到,Geoff Hinton 将 early stopping 称为一种 “beautiful free lunch”。Geoff Hinton 是深度学习先驱之一,也获得过图灵奖。
early stopping 的基本方法是:
- 将训练数据拆成训练集和验证集。
- 持续训练模型。
- 训练过程中,训练集 loss 通常会继续下降。
- 同时监控验证集表现。
- 如果验证集表现开始停滞甚至变差,就停止训练。
关键点是:
验证集只用于评估,不用于计算梯度。
也就是说,验证集不会参与参数更新。
老师说明,Colab 中会先完整跑一遍,观察验证集曲线在哪里变平或变差,再判断应该在哪里停止。实际使用中,Keras 有更高效的方式,不一定要训练到最后再手动回退。
十一、Dropout
另一种 regularization 方法是 dropout。
老师说明,dropout 是一种非常巧妙的策略,但本节课不会使用。
本节课主要使用 early stopping。dropout 会在后续课程第一次使用时再详细解释。
十二、训练神经网络的实践清单
老师将训练流程总结为:
- 准备数据。
- 设计网络结构。
- 决定隐藏层数量。
- 决定每层神经元数量。
- 选择合适的输出层。
- 选择与输出类型匹配的
loss function。 - 选择
optimizer。 - 选择 regularization 方法,例如
early stopping或dropout。 - 用
Keras和TensorFlow启动训练。
优化器方面,SGD 有很多变体。
类似隐藏层中常把 ReLU 作为默认激活函数,优化器中常把 Adam 作为默认选择。老师说明,本节课会使用 Adam。
十三、什么是 Tensor
进入 TensorFlow 和 Keras 前,老师先解释 tensor。
学生最初回答 tensor 是输入数据,可以表示图像、时间序列等。老师指出这个方向接近,但 tensor 的概念更基础。
更准确地说:
tensor是对 number、vector、table 等对象的统一推广。
不同 rank 的 tensor 可以这样理解:
| 对象 | Tensor rank | 含义 |
|---|---|---|
| 单个数字 | rank 0 | 没有维度 |
| 向量 | rank 1 | 一维数字列表 |
| 表格 / 矩阵 | rank 2 | 二维数字表 |
| 一组表格 | rank 3 | 可以理解为很多张表叠在一起 |
| 视频 | rank 4 | 一串彩色图片 |
老师强调,tensor 不一定比矩阵复杂。单个数字本身也是 tensor。
十四、Tensor 的 Rank 与嵌套结构
每个 tensor 都有 rank。
可以从嵌套列表角度理解 tensor:
rank 1 tensor是数字列表。rank 2 tensor是列表的列表,也就是表格。rank 3 tensor是很多张表构成的列表。rank 4 tensor可以是很多彩色图片构成的序列。
例如,形状为 (7, 3) 的 rank 2 tensor 可以理解为 7 行、3 列的表格。老师还建议把 tensor 想成由方括号包起来的嵌套数组:外层每向内取一个元素,就进入低一阶的 tensor。
老师给出一个重要理解:
rank n tensor可以看作一组rank n-1 tensors。
例如:
- 一个视频是
rank 4 tensor。 - 一组视频就是
rank 5 tensor。 - 一个
rank 10 tensor可以看作一组rank 9 tensors。
因此,对于任意 tensor,都可以沿第一个维度进行迭代。每取出一个元素,就得到低一阶的 tensor。
老师提到,tensor 概念来自 Einstein,它既直观又容易让人觉得滑。建议阅读教材 2.2 中关于 tensor 的讨论,并通过练习熟悉。
十五、图像与 Tensor 的关系
老师提前指出,后面会看到:
- 灰度图像通常表示为一张数字表,也就是
rank 2 tensor。 - 彩色图像通常表示为三张数字表,对应颜色通道。
- 视频可以看作一串彩色图像,因此是更高 rank 的 tensor。
这为后面计算机视觉部分做铺垫。
十六、TensorFlow 的作用
TensorFlow 是一个深度学习库。
名字中的 TensorFlow 可以这样理解:
神经网络中流动的是 tensors,tensors 从输入端进入网络,经过层层计算,再从输出端流出。
TensorFlow 提供几个关键能力:
- 自动计算任意复杂 loss function 的 gradients。
- 提供各种 optimizers,包括
SGD及其变体。 - 支持将计算分布到多个服务器。
- 自动组织计算以利用
GPU。
老师强调,手动计算复杂网络的梯度非常痛苦。TensorFlow 可以自动处理链式法则和梯度计算,这是它非常重要的价值。
并行计算方面,老师指出,不是所有计算都容易并行化。TensorFlow 会帮助处理这些复杂性。
GPU 是 Graphics Processing Unit,适合并行计算。即使只有一台有 GPU 的机器,也需要以特定方式组织计算才能充分利用硬件,TensorFlow 会自动完成很多工作。
老师还提到 TPU:
TPU是Tensor Processing Unit,可以理解为 Google 设计的类似 GPU 的硬件。
十七、Keras 与 TensorFlow 的关系
Keras 位于 TensorFlow 之上。
可以理解为:
hardware → TensorFlow → KerasTensorFlow 负责底层计算、梯度、优化和硬件利用。
Keras 提供更方便的高层抽象,例如:
layersactivation functions- 数据预处理工具
- 模型训练接口
- 指标报告
training lossvalidation lossvalidation accuracy- 预训练模型库
老师之前用过的 keras.Dense 就是一个 dense layer。
十八、为什么课程选择 TensorFlow/Keras
老师提到,很多学生可能熟悉 PyTorch。PyTorch 也是非常优秀的深度学习框架。
本课程选择 TensorFlow 和 Keras 的原因是:
- 希望课程对编程背景较少的学生更友好。
PyTorch从计算机科学角度要求更高。PyTorch更依赖对面向对象编程的理解。TensorFlow/Keras在能力上足够强,同时更容易上手。
老师认为,Keras 很像一个设计良好的 LEGO 积木环境,可以用相对简单的方式搭建复杂模型。
十九、Keras 的三种 API
Keras 有三种主要 API:
Sequential APIFunctional APISubclassing API
本课程几乎都会使用 Functional API。
心脏病预测模型也是用 Functional API 搭建的。
老师建议阅读教材 7.2.2,理解 Functional API 的具体工作方式。
老师还提到,相关网站上有许多 Keras 和 Colab 示例资源,可以作为课后练习材料。
二十、心脏病预测模型回顾
回到上一节课设计的心脏病预测模型。
模型结构是:
- 输入层。
- 一个 dense hidden layer。
- hidden layer 有
16个ReLUneurons。 - 输出层使用
sigmoid。
因为这是二分类问题,所以输出是一个概率。
训练设置:
- loss function:
binary_crossentropy - optimizer:
Adam - regularization:使用
early stopping思路监控过拟合
老师提醒:
- 如果预测任意连续数值,可以用
mean squared error。 - 如果预测二分类概率,并与
0/1标签比较,应使用binary_crossentropy。
二十一、Colab 使用建议
进入 Colab 前,老师给出实践建议:
- 不必在课堂上立刻理解每一行代码。
- 课后应逐行阅读和运行 notebook。
- 学习新代码时,尽量不要直接复制粘贴。
- 更推荐手动重打一遍代码,这样更容易理解。
对于课程发布的 Colab:
- 先使用
Copy to Drive建立自己的副本。 - 如果 notebook 涉及自然语言处理或视觉任务,通常应该使用
GPUruntime。 - 之后再次打开同一个 notebook 时,可以直接从 runtime 设置开始。
老师也提到,网上有很多关于 Colab 的短教程,可以自行查看。
二十二、心脏病数据集
心脏病预测 Colab 使用前面介绍过的数据集。
数据集包含:
303名患者。- 多个变量,包括年龄、人口统计信息、生物标志物等。
- 目标变量是
0或1,表示是否有心脏病。
老师说明,课堂中不会实时运行每个 cell,因为运行完整 notebook 会占用课堂时间。他已经提前运行过,会逐步解释每部分代码的含义。
二十三、常用 Python 包
每次训练深度学习模型时,通常会加载一组常见包。
本节课中包括:
tensorflowkerasNumPyPandasMatplotlib
用途分别是:
TensorFlow/Keras:构建和训练深度学习模型。NumPy:处理矩阵、数组和 tensors。Pandas:清洗、整理和转换表格数据。Matplotlib:绘制 loss 曲线和 accuracy 曲线,辅助观察是否需要 early stopping。
老师特别指出,通常会先导入 TensorFlow,再从 TensorFlow 中导入 Keras。
二十四、训练中的随机性与 Random Seed
深度学习训练中存在多个随机性来源:
- 初始权重通常随机初始化。
SGD中会随机打乱数据,再形成 batches。- 拆分
train、validation、test时也可能涉及随机抽样。 dropout本身也带有随机性。
如果希望别人能复现结果,就需要设置 random seed。
课堂中使用:
set_random_seed(42)老师说明,42 是对《The Hitchhiker's Guide to the Galaxy》的流行文化引用。
不过,即使设置 seed,也不保证完全得到相同数字。由于硬件、设备驱动等原因,bitwise reproducibility 并不总是有保证。
二十五、读入数据与查看类别比例
老师提到,Francois Chollet 将这个数据整理成了 Pandas dataframe,可以从 CSV 读入。
读入后数据形状是:
303 rows, 14 columns第一步通常查看前几行,理解变量含义和目标列。
对于二分类问题,老师会先检查正负类比例。
本数据中:
72.6%的患者没有心脏病。27.4%的患者有心脏病。
这不是 50/50 的平衡数据集,而是负类明显更多。
二十六、Baseline Model
老师提出问题:如果不使用复杂模型,最简单的 baseline 是什么?
学生回答:
永远预测
0,也就是预测所有人都没有心脏病。
因为 72.6% 的样本属于 0 类,所以这个 baseline 的 accuracy 是:
72.6%任何更复杂的模型都应该超过这个 baseline。否则,就没有使用复杂模型的价值。
二十七、数据预处理:分类变量与数值变量
该数据集同时包含:
- categorical variables
- numeric variables
因此,通常先把两类变量分开处理。
27.1 Categorical Variables
神经网络不能直接处理类别输入。
与某些模型不同,例如 decision tree,神经网络需要数值输入。
因此,类别变量必须先数值化。
标准做法是:
one-hot encoding在 Pandas 中,可以使用:
get_dummies例如变量 thal 原来可能有:
fixednormalreversible
经过 one-hot encoding 后,会变成多个列:
thal_fixedthal_normalthal_reversible
27.2 Numeric Variables
神经网络通常在输入数值范围较小、尺度相近时训练效果更好。
因此,数值变量需要标准化:
standardized_value = (value - mean) / standard_deviation也就是:
- 减去均值。
- 除以标准差。
标准化后,数值大多落在 0、1、-1 附近的范围,更适合神经网络训练。
二十八、为什么先划分 Test Set,再标准化
老师强调,标准化之前应该先划分测试集。
流程应是:
- 先将数据划分为 training set 和 test set。
- 将 test set 锁起来,不参与建模过程。
- 只基于 training set 计算 mean 和 standard deviation。
- 用 training set 的 mean/std 标准化 training set 和 test set。
原因是:
如果在划分之前用全数据计算 mean/std,标准化过程就已经使用了 test set 的信息。
这样会导致数据泄漏。测试集就不再是完全独立的最终评估数据。
课堂中使用约 80% / 20% 的划分:
- training set:
242rows - test set:
61rows
老师提到,dataframe.shape 可以查看数据维度。
二十九、转换为 NumPy Array
完成 one-hot encoding、标准化和 train/test split 后,数据已经全部是数值。
此时需要将 Pandas dataframe 转成 NumPy array,因为 Keras 可以直接接收 NumPy 数据。
使用方法:
to_numpy老师指出,to_numpy 的名字非常直观。
转换后,train 和 test 就是 NumPy arrays,保存了同样的信息,但格式更适合送入 Keras。
三十、拆分 X 与 Y
原始 dataframe 中包含:
- 输入特征 columns。
- 目标变量 column。
训练时必须把两者分开:
X:输入特征。Y:真实标签。
原因是:
- 模型只接收
X做预测。 - 预测结果再与真实
Y比较。 - 根据差异计算 loss。
课堂中,目标列是左起第 6 列。
处理后:
train_x是242 x 29。test_x是61 x 29。train_y是长度为242的向量。test_y是长度为61的向量。
这也解释了上一节课中模型为什么有 29 个输入节点。
三十一、搭建心脏病预测模型
数据预处理完成后,开始搭建模型。
模型是上一节课设计过的结构:
- 输入:
29个 features。 - hidden layer:
16个ReLUneurons。 - output layer:
1个sigmoid输出。
这是一个二分类问题,因此输出层用 sigmoid。
代码中老师给 layer 加了名字。layer name 是可选的,主要用于后续解释和查看模型结构。
三十二、model.summary() 与参数数量
老师建议,模型建好后应立即运行:
model.summary()model.summary() 会显示:
- 每一层是什么类型。
- 输入该层的 tensor shape。
- 该层输出的 tensor shape。
- 每层参数数量。
课堂模型总共有 497 个参数。
参数数量计算如下:
hidden layer:
29 * 16 + 16其中:
29 * 16是输入到 hidden layer 的 weights。16是 hidden layer 的 biases。
output layer:
16 * 1 + 1其中:
16 * 1是 hidden layer 到 output layer 的 weights。1是 output bias。
总数:
29 * 16 + 16 + 16 * 1 + 1 = 497老师再次提醒,初学时应手动验证参数数量,确保理解网络结构。
也可以使用 plot_model 可视化网络拓扑。后面网络更大时,图形化结构会更有帮助。
三十三、compile:选择 Loss、Optimizer 与 Metrics
模型训练前需要调用 compile。
本例设置:
- loss function:
binary_crossentropy - optimizer:
Adam - metrics:
accuracy
老师强调,metrics 只用于报告,不用于优化。
例如 accuracy 会显示出来,方便观察模型表现,但不会直接参与梯度计算。
compile 的作用是:
将模型、loss、optimizer、metrics 等信息组织起来,使模型适合后续训练、并行计算和分布式计算。
这也是为什么在 Keras 中训练前需要一个 compilation step。
三十四、model.fit():开始训练
真正训练模型使用:
model.fit(...)需要传入:
xtensor。ytensor。epochs。batch_size。verbose。validation_split。
本例选择:
batch_size = 32epochs = 300validation_split = 0.2verbose = 1
其中,verbose = 1 表示训练时输出较多描述性日志,方便观察训练过程。
老师说明,32 是一个很常见的 batch size 默认值。实践中可以尝试 32、64、128 等。
有研究者的经验说法是:
使用机器内存能承受的最大 batch size 往往是一个可以尝试的方向。
但本例数据很小,从 32 开始即可。
关于 epoch 数,老师说:
20到30个 epochs 通常是不错的起点。- 本例为了观察是否会过拟合,特意跑
300个 epochs。
validation_split = 0.2 表示:
从 training data 中拿出
20%作为 validation set,不用于训练,只用于观察 validation loss 和 validation accuracy。
三十五、训练输出如何阅读
model.fit 运行后会输出很多行。
每个 epoch 的输出中包含:
- 当前 epoch 使用了多少 batches。
- 每个 epoch 运行时间。
- training loss。
- training accuracy。
- validation loss。
- validation accuracy。
本例中,老师用第 300 个 epoch 的一行输出做解释:它显示 7/7 batches,表示该 epoch 使用了全部 7 个 batches;同一行还会显示 training loss、training accuracy,以及 epoch 结束后在 validation set 上计算出的 validation loss 和 validation accuracy。
课堂示例中,该 batch 的 training accuracy 显示为 98.5%。老师强调,这些数字都只是日志输出中的不同字段,直接盯着一大段数字不容易理解,因此通常会画成曲线。
这与前面的 batch 计算一致:
- 从 training set 中再拿出
20%做 validation 后,剩余训练样本约为193或194。 batch_size = 32。- 向上取整后是
7个 batches。
老师解释,前 6 个 batches 大约各有 32 个样本,最后一个 batch 只剩很少样本。
三十六、history 对象与绘图
老师将训练结果保存为:
history = model.fit(...)history 对象包含训练过程中的诊断信息。
其中:
history.history是一个 dictionary,保存了各个 epoch 的:
- loss
- accuracy
- validation loss
- validation accuracy
这些值可以用 Matplotlib 绘制曲线,用于判断训练趋势和过拟合。
三十七、Validation Set 与 Test Set 的区别
学生问:已经划分过 test set,为什么 model.fit 还要留出 validation set?
老师解释:
三类数据集的角色不同:
- training set:用于训练和更新参数。
- validation set:用于 early stopping 和 hyperparameter tuning。
- test set:最终模型确定后,只使用一次,用于估计真实部署表现。
validation set 用来回答:
- 是否应该 early stop。
- 哪组 hyperparameters 更好。
- 模型是否开始过拟合。
test set 则要一直锁起来,直到最终模型确定。
最后评估 test set 的目的不是改模型,而是了解模型部署到真实世界后的可能表现。
三十八、关于 Metrics 的问答
学生问:能否不用 accuracy,而使用其他指标,例如 confusion matrix 相关指标?
老师回答:可以。
可用指标包括:
- error rate
- accuracy
F1F-beta- 其他基于 confusion matrix 的指标
关键点是:
metrics 只是报告给建模者看的,不参与训练优化。
Keras 提供了很多可选 metrics。
三十九、Validation Split 的具体含义
学生问:validation_split = 0.2 是从训练集中拿出 20%,还是从每个 batch 中拿出 20%?
老师回答:
从 training set 中拿出
20%。
拿出 validation set 后,剩下的数据才被分成 batches 进行训练。
因此,可用于计算 batch 数量的训练数据会减少。
老师进一步说明:
- validation set 在训练开始前固定下来。
- 每个 epoch 使用同一个 validation set。
- 这不是 cross-validation。
- 每个 epoch 不会重新抽一个新的 validation set。
另一个学生用具体数值确认:如果 training loss 已经到 0.0860,而 validation loss 是 0.660,是否说明已经越过较合适的停止点,最终部署时应使用前面那个更好的模型。老师确认这个判断方向,并说明后面会讲如何拿到对应的模型,例如是否需要重新从头训练到某个 epoch,或用更智能的方法保存最佳模型。
学生问:每个 epoch 有什么不同?
老师回答:
不同的是 weights 已经改变。
在一个 epoch 内,每个 minibatch 后 weights 都会更新。一个 epoch 结束后,模型已经经历了所有训练样本,然后再从头开始下一轮。
四十、观察 Loss 曲线
老师用 Matplotlib 绘制:
- training loss
- validation loss
横轴是 epochs。
观察结果:
- training loss 稳定下降。
- validation loss 一开始下降。
- 到某个阶段后变平。
- 后面可能轻微上升。
这说明模型可能出现了一定程度的 overfitting。
不过,老师提醒:
binary_crossentropy是一个数学上方便的 proxy,它能衡量预测与真实标签的差异,但实际部署时可能更关心 accuracy 或 error rate。
因此,不能只看 loss,也要看 accuracy。
四十一、观察 Accuracy 曲线
老师继续绘制:
- training accuracy
- validation accuracy
观察结果:
- training accuracy 随 epoch 增加而上升。
- training accuracy 可以达到低到中
90%的水平。 - validation accuracy 大约在
50个 epochs 附近变平。 - 后面 validation accuracy 甚至又有所上升。
因此,虽然 validation loss 显示出一些 overfitting,但 validation accuracy 最后仍然变好。
老师的判断是:
这种 overfitting 可能可以接受,不一定需要立刻停止。
可以选择:
- 严格按照 validation loss,在约
50个 epochs 处停止。 - 或者接受当前结果,因为 accuracy 后续仍有改善。
老师更倾向于关注与真实部署目标更接近的指标。如果真实世界中关心的是错误率或准确率,那么 accuracy 的信号也很重要。
四十二、Epoch 数量如何决定
学生问:老师前面说 20 到 30 个 epochs 是起点,但这里跑了 300 个。如果只跑 20 到 30,可能还看不到过拟合,怎么办?
老师回答:
20 到 30 是起点,不是固定规则。
做法是:
- 先训练一段,例如
20或30个 epochs。 - 查看 validation loss 是否仍在下降。
- 如果还在下降,就继续训练。
- 可以再运行
fit继续训练10个 epochs。 - 如果 validation loss 开始上升,再停止或回退。
Keras 的特点是:
再次调用
fit时,会从当前权重继续训练,而不是从头开始。
老师说明,手动观察曲线是为了建立直觉。实际中可以使用 callbacks。
callbacks 可以设置:
- 当 validation loss 不再改善时自动停止。
- 当 validation loss 不再改善时保存最佳模型。
这样就不必手动回到某个 epoch 重新训练。
四十三、为什么 Loss 变差时 Accuracy 还可能变好
学生问:为什么 validation loss 变高时,accuracy 还能变好?
老师回答:
accuracy 和 loss 相关,但不是同一个东西。
accuracy 是离散指标。
例如二分类中:
- 预测概率
0.49可能被判为0。 - 预测概率
0.51可能被判为1。
从 0.49 到 0.51:
binary_crossentropy变化可能很小。- 但 accuracy 会从错变成对,发生跳跃式变化。
因此,accuracy 是一个比较跳跃、离散、粗糙的指标,而 loss 是连续的优化目标。
老师还提到,可以尝试取某个 epoch 的权重,例如 epoch 50,并比较其验证表现。最终仍要看哪个指标更接近真实部署目标。
四十四、最终 Test Set 评估
模型训练并完成判断后,使用:
model.evaluate(test_x, test_y)此时才使用最开始保留的 test set。
老师运行结果显示,模型在 test set 上达到:
83.6% accuracy前面的 baseline 是:
72.6% accuracy因此,这个小型神经网络明显超过了简单 baseline。
老师提醒,许多 preprocessing 步骤也可以放进 Keras 内部完成,Keras 有相应的 preprocessing layers。
四十五、课后如何学习这个 Colab
老师建议课后:
- 逐行阅读 notebook。
- 修改每一行。
- 重新运行。
- 观察输出如何变化。
这种方式有助于建立训练模型的直觉。
四十六、关于 False Positive 与 False Negative 的问答
学生问:是否可以构建一个模型,让它更少产生 false positives 或 false negatives?
老师回答:可以。
可以做两件事:
- 报告这些指标,例如 false positive rate、false negative rate。
- 使用更复杂的 loss functions,将 false positive 和 false negative 的不对称代价纳入训练。
老师没有在本节课展开细节,只说明这是可行的。
四十七、灰度图像如何表示
进入计算机视觉部分后,老师先讲数字图像表示。
灰度图像,也就是黑白图像,可以表示为一张数字表。
图像中的每个位置叫 pixel。
每个 pixel 有一个光强值:
0表示没有光,对应黑色。255表示非常亮,对应白色。- 中间数值表示不同灰度。
老师用数字 5 的图像举例:
- 黑色区域通常是
0。 - 白色笔画区域是更大的数。
- 数值越接近
255,越亮。
如果离远一点看这些数字表,甚至可以看出数字 5 的形状。
四十八、像素光强的单位
学生问:光强的单位是什么?
老师回答,本课程中只需要把它理解为一个归一化尺度。
真实世界中的模拟图像会经过数字化过程,被映射到 0 到 255 的范围。
这里不需要关心具体物理单位或 lumens 到数值的精确映射。不同设备和处理方式可能有很多变化。
对本课程来说,理解为:
每个 pixel 的光强被映射为
0到255的相对数值。
即可。
四十九、彩色图像如何表示
彩色图像中,每个 pixel 不再只有一个数字,而是有三个数字。
这三个数字表示颜色通道的强度:
redgreenblue
每个通道仍然是 0 到 255 之间的数。
因此,一张彩色图像可以表示为三张数字表:
- red channel table
- green channel table
- blue channel table
在深度学习中,这些颜色维度通常称为 channels。
老师以 Killian Court 图片为例,说明一张彩色图片对应三张表,因此可以看作一个 rank 3 tensor。
五十、计算机视觉中的主要任务
老师介绍了几类常见图像处理任务。
50.1 Image Classification
image classification 是最基础的任务。
问题形式是:
给定一张图片,判断它属于哪个类别。
经典例子是:
- dog vs cat
也可以是多类别分类。
本节课后面会处理图像分类问题。
50.2 Localization
localization 不只判断图片中有什么,还要判断目标在图片中的位置。
例如:
- 判断图片中有 sheep。
- 同时输出 sheep 的位置。
通常用一个 bounding box 表示位置。
模型输出不仅包括类别,还包括 box 的坐标,例如:
- top-left coordinate
- bottom-right coordinate
50.3 Object Detection
object detection 处理更复杂的情况:
一张图片中可能有多个对象,需要识别每个对象并定位它们。
例如图片中有多只 sheep,需要分别框出:
- sheep 1
- sheep 2
- sheep 3
老师提到,自动驾驶系统会不断进行 object detection。
摄像头系统会每秒多次识别和定位:
- pedestrian
- zebra crossing
- dog
- stroller
- 其他道路对象
50.4 Semantic Segmentation
semantic segmentation 是对每个 pixel 进行分类。
它不是给整张图片一个类别,而是给每个像素一个类别。
例如:
- 这些 pixels 是 road。
- 这些 pixels 是 sheep。
- 这些 pixels 是 grass。
因此,semantic segmentation 可以理解为:
对每个 pixel 做 multi-class classification。
50.5 Instance Segmentation
instance segmentation 更进一步。
它不仅要给每个 pixel 分类,还要区分同一类别中的不同实例。
例如:
- 这些 pixels 属于 sheep 1。
- 那些 pixels 属于 sheep 2。
- 另一些 pixels 属于 sheep 3。
老师指出,这些都是非常常见且有用的计算机视觉任务,都适合用 deep learning 系统处理。
五十一、Fashion-MNIST 数据集
接下来,老师进入图像分类示例:Fashion-MNIST。
Fashion-MNIST 包含:
70,000张服装图片。10个类别。- 类别包括 boots、sweaters、T-shirts 等。
这是一个平衡数据集:
- 每个类别大约占
10%。
因此,最简单的 naive baseline 是随机或固定预测某一类,其 accuracy 约为:
10%老师说明,一个简单神经网络可以在这个任务上接近:
90% accuracy五十二、图像输入为什么需要 Flatten
Fashion-MNIST 中每张图片是:
28 x 28也就是一张 rank 2 tensor,一张数字表。
而前面构建的普通 dense neural network 接收的是向量。
因此,需要把 28 x 28 的表格转换成一个长向量。
这个过程叫:
flattening具体做法可以理解为:
- 取第一行像素值。
- 接在向量开头。
- 取第二行像素值。
- 接在第一行后面。
- 持续把所有行串起来。
结果是:
28 * 28 = 784因此,每张图片会变成长度为 784 的向量。
老师强调,flattening 本身没有做复杂学习,只是重新组织数据形状。
五十三、Fashion-MNIST 的简单网络结构
flatten 后,就回到了熟悉的向量输入场景。
本节课中的简单网络结构是:
- 输入:长度为
784的向量。 - hidden layer:
256个ReLUneurons。 - output layer:处理
10个类别。
老师说明,他尝试过几个不同 hidden layer 大小,256 个 neurons 表现不错,因此示例中使用 256。
五十四、多类别输出问题
心脏病预测是二分类:
- 输出
0或1。 - 用一个
sigmoid输出概率。
Fashion-MNIST 是 10 分类:
- 类别包括
T-shirt、trouser、ankle boot等服装类别。 - 具体编号到类别名称的映射可以查看
Fashion-MNIST的说明页面。
一张图片只能属于其中一个类别。
因此,模型输出应该是 10 个概率,并且这些概率需要满足:
sum(probabilities) = 1五十五、为什么不能用 10 个 Sigmoid
学生回答了关键原因:
10个独立sigmoid的输出不一定加起来等于1。
sigmoid 可以把每个数压到 0 到 1,但如果独立使用 10 个 sigmoid,它们之间没有约束。
在 Fashion-MNIST 这种互斥分类中:
- 只有一个类别是正确答案。
- 模型需要输出一组彼此竞争的概率。
- 所有类别概率应加起来为
1。
因此,需要使用 softmax。
五十六、Softmax Function
softmax 的作用是:
将任意一组数转换成一组非负概率,并保证它们加起来等于
1。
对于 10 分类:
- 网络最后先输出
10个线性数值。 - 对每个数取指数,例如
e^a。 - 用每个指数值除以全部指数值之和。
形式可以理解为:
softmax(a_i) = exp(a_i) / sum(exp(a_j))这样会带来两个结果:
exp(a_i)一定为正。- 每个值都除以总和,所以所有输出加起来等于
1。
因此,softmax 可以把网络输出的任意 10 个数变成 10 个类别概率。
五十七、Softmax 与 GPT-4 的关系
老师特别提醒,softmax 很重要,因为大型语言模型也使用类似思想。
他用 GPT-4 做类比:
- 当模型生成输出时,每次发出的严格来说不是 word,而是
token。 - 可以暂时把它想象成 word。
- 每一步生成时,模型需要在大量可能 tokens 中选择下一个。
- 老师举例说,这是一个大约
52,000维的softmax。
也就是说:
可以把语言模型的下一 token 预测理解为一个非常大的多分类问题。
每个 token 都是可能输出,模型通过 softmax 得到概率分布,再选择合适的输出。
五十八、输出层与 Loss Function 的对应关系
老师总结了输出层和 loss function 的匹配关系。
| 任务输出 | 输出层形式 | 常用 loss |
|---|---|---|
| 任意单个数值 | linear output | mean squared error |
| 单个概率 | sigmoid | binary_crossentropy |
| 多个任意数值 | 多个 linear outputs | mean squared error |
| 多个互斥类别概率 | softmax | categorical_crossentropy 或 sparse_categorical_crossentropy |
选择 loss function 时,要看标签数据如何编码。
五十九、为什么输出概率而不是直接输出 0 或 1
学生问:既然最终只有一个正确类别,为什么要输出概率,而不是直接输出 0 或 1?
老师回答:
不能强迫网络精确输出
0或1。
网络会产生它能产生的数值。建模者能做的是使用合适的输出层,把这些数值约束到需要的范围。
例如:
sigmoid将输出约束在0到1。softmax将多个输出约束为总和为1的概率分布。
六十、标签编码方式与 Cross-Entropy Loss
多分类标签可以有不同编码方式。
60.1 Binary Classification
心脏病预测中,标签是:
0 or 1对应 loss:
binary_crossentropy60.2 Sparse Encoding
Fashion-MNIST 中,标签可以是整数:
0, 1, 2, ..., 9这种形式称为:
sparse encoded对应 loss:
sparse_categorical_crossentropy60.3 One-Hot Encoding
同样的 10 分类标签也可以写成 one-hot vector。
例如某一类对应:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]对应 loss:
categorical_crossentropy老师说明,这些方式表达的是同一个分类任务,只是标签编码不同。应根据数据实际编码选择正确的 Keras loss function。
categorical_crossentropy 可以看作 binary_crossentropy 的多类别推广。老师没有展开数学细节,但直觉类似。
六十一、Fashion-MNIST Colab:加载数据
进入第二个 Colab 后,老师沿用类似设置:
- 导入
TensorFlow和Keras。 - 导入常用的
NumPy、Pandas、Matplotlib。 - 设置
random_seed保证尽量可复现。
Fashion-MNIST 是 Keras 内置标准数据集,因此不需要另找数据文件。
使用:
load_data即可加载。
六十二、为什么数据集自带 Train/Test Split
Keras 提供的 Fashion-MNIST 已经预先划分好了 training set 和 test set。
原因是:
这样不同研究者或学习者可以在同一个 test set 上比较模型表现。
如果每个人自己随机划分测试集,模型准确率之间就不一定可比。
六十三、Fashion-MNIST 的 Tensor Shape
训练输入数据是一个 rank 3 tensor。
可以理解为:
一组
rank 2 tensors。
具体形状是:
60,000张训练图片。- 每张图片是
28 x 28的数字表。
因此:
train_x: 60000 images, each 28 x 28输出标签是一个长度为 60,000 的向量:
train_y: 60000 labels测试集是:
10,000张测试图片。- 每张同样是
28 x 28。 - 对应
10,000个标签。
六十四、类别编号与类别名称
如果查看 train_y 的前几个值,会看到类似:
9, 0, 3, ...这些数字是类别编号。
Fashion-MNIST 的类别映射可以从 GitHub 页面查看,例如:
0:T-shirt1:trouser9:ankle boot
老师通常会创建一个类别名称列表,把数字标签映射成人类可读的类别名。
这样查看结果时,不必反复记忆数字和类别之间的对应关系。
六十五、查看原始图像数据
老师查看第一张图片:
- 它的标签对应
ankle boot。 - 原始图像数据是一个
28 x 28数字表。 - 表中可以看到很多
0,也能看到250、233等较大的像素值。
这些数字就是灰度像素强度。
老师使用 Matplotlib 可视化前 25 张图片。
图片看起来比较小、模糊,但仍能看出服装轮廓。例如第一张是 ankle boot。
老师在本节课末尾暂停,说明下一次课会继续这个图像分类流程,并进一步进入彩色图像。
六十六、本节课核心总结
本节课的知识链条可以概括为:
- 神经网络训练通过
loss function衡量预测与真实值差异。 optimizer根据 gradient 更新weights和biases。epoch是对训练集的一次完整遍历。- 普通
gradient descent每个 epoch 更新一次。 SGD将训练集分成 batches,每个 batch 后更新一次。batch size是建模者选择的,常见起点是32。- 复杂神经网络容易
overfit,因此需要 regularization。 early stopping通过 validation set 判断何时停止训练。dropout是另一种 regularization 方法,本节课只预告。tensor是 number、vector、matrix/table 及更高维数组的统一表示。TensorFlow负责 tensors 的计算流、自动梯度、优化器、分布式计算和 GPU 利用。Keras在TensorFlow之上提供 layers、training、metrics、preprocessing 和预训练模型等高层接口。- 心脏病预测模型使用
29个输入、16个ReLUhidden neurons、sigmoid输出,共497个参数。 - 二分类任务使用
binary_crossentropy,优化器使用Adam。 - validation set 用于调参和 early stopping,test set 只在最终评估时使用。
- 本例神经网络 test accuracy 为
83.6%,超过72.6%baseline。 - 灰度图像是
0到255的像素强度表。 - 彩色图像由
RGB三个 channels 构成,可视为rank 3 tensor。 - 计算机视觉任务包括 classification、localization、object detection、semantic segmentation、instance segmentation。
Fashion-MNIST是70,000张服装图片的10分类任务,baseline 为10%。28 x 28图像可以 flatten 成长度为784的向量。- 多类别互斥分类需要
softmax,而不是多个独立sigmoid。 softmax将任意一组数转换成总和为1的概率分布。- 根据标签编码不同,多分类任务可使用
sparse_categorical_crossentropy或categorical_crossentropy。
本节课最重要的实践结论是:
训练神经网络不仅是搭建网络结构,还包括数据预处理、batch/epoch 设置、validation/test 划分、loss 与 metrics 的选择,以及对训练曲线的诊断。
理解这些细节后,Keras 训练流程就不只是运行几行代码,而是一个可以被分析、调试和改进的建模过程。