从真实表格分类数据开始,先跑通 data -> model -> loss -> optimizer -> metrics。
uv run python -m llm_tutor.experiments.train_linear_classifier --epochs 20训练型脚本通常支持 --output-dir,可以把配置、指标、日志和模型产物保存到 runs/ 下,便于复盘。
本章学习契约
- 新增概念:监督学习、输入特征、标签、线性分类器、训练/验证/测试拆分。
- 实验要验证:一个很简单的模型也能通过 loss 和优化器,从表格数据里学到可复用规律。
- 实验不验证:它不是医学模型评测,也不能说明高测试分数就能直接用于真实诊断。
- 跑完重点看:
train_loss是否下降,val_acc/val_f1是否高于随机猜测,最后的 malignant precision/recall/F1 是否暴露不同错误类型。
机器学习最朴素的说法是:我们给模型一些样本,让它从样本里找到一个可以复用的规律。
在监督学习里,一个样本通常长这样:
输入特征 x -> 真实标签 y模型要学习的是一个函数:
model(x) ≈ y这里的“学习”不是把训练集答案背下来,而是不断调整模型内部的参数,让模型在训练样本上的错误变小,同时希望它在没见过的新样本上也表现不错。
一个表格分类例子
第一章使用 Breast Cancer Wisconsin 数据集。它包含一组肿瘤细胞测量指标,任务是预测样本属于 malignant 还是 benign。
这不是因为医学分类是本课程重点,而是因为它非常适合做第一个实验:
- 数据量小,CPU 可以快速训练。
- 特征是普通数字,方便理解“输入指标 -> 输出类别”。
- 不需要下载大型文件,适合作为稳定 smoke test。
线性分类器
我们先训练一个最小模型:
logits = x @ W + b其中:
x是输入特征。W和b是模型要学习的参数。logits是模型对每个类别给出的原始分数。
分类时,我们取分数最高的类别作为预测结果。
logits 不是概率,而是模型还没有归一化的原始分数。例如:
logits = [2.0, 0.5]它只表示第一个类别的分数比第二个类别高。经过 softmax 之后,才会变成两个和为 1 的概率。一个小但重要的结论是:argmax(logits) 和 argmax(softmax(logits)) 会得到同一个类别,所以训练和预测代码通常直接使用 logits。下一章会解释为什么 PyTorch 的 CrossEntropyLoss 也直接接收 logits。
这一章暂时不细拆分类 loss。你可以先把它理解成“模型预测和真实标签之间的差距”。下一章会把 MSE、softmax、交叉熵和 PyTorch 的 CrossEntropyLoss 拆开讲清楚。
为什么要分训练集、验证集、测试集
如果只看训练集表现,模型可能只是记住了训练样本。为了知道它能不能泛化,我们把数据拆成三份:
- 训练集:用来更新参数。
- 验证集:用来观察训练过程、调超参数。
- 测试集:最后才看,用来估计最终效果。
运行实验
uv run python -m llm_tutor.experiments.train_linear_classifier --epochs 20你会看到每个 epoch 的训练 loss、验证 loss、验证 accuracy 和 F1。最后会输出测试集指标。输出里的 malignant_precision、malignant_recall、malignant_f1 表示我们把 malignant 当作正类来计算指标。
样例输出大致会长这样:
epoch=01 train_loss=... val_loss=... val_acc=... val_f1=...
...
test loss=... acc=... malignant_precision=... malignant_recall=... malignant_f1=...不同机器、不同随机种子下数值会略有波动。你更应该观察趋势:loss 是否下降,验证集指标是否比随机猜测好。
有时你会看到 loss 下降,但 accuracy 或 F1 暂时没动,甚至小幅波动。这并不矛盾。loss 关注的是模型给真实类别的概率有多高,所以即使最终预测类别还没变,置信度变得更合理也会让 loss 下降。accuracy/F1 只看最后分类结果,对“预测对了但不够自信”或“预测错了但接近改对”不敏感。
二分类指标最好放到混淆矩阵里理解。这里把 malignant 当作正类:
| 真实/预测 | 预测 malignant | 预测 benign |
|---|---|---|
| 真实 malignant | true positive | false negative |
| 真实 benign | false positive | true negative |
malignant_recall 关心真实 malignant 里有多少被找出来;malignant_precision 关心预测为 malignant 的样本里有多少是真的。真实医学场景里哪个错误更严重,必须由业务和伦理约束决定,不能只交给一个指标。
这个实验能说明什么
它能说明:
- 一个简单线性模型也可以通过数据学习有用规律。
- 训练过程可以用 loss 曲线和验证指标观察。
- accuracy 不是唯一指标,precision、recall、F1 能帮助观察不同错误类型的比例和取舍。
它不能说明:
- 线性模型足够解决所有问题。
- 测试集高分就代表真实业务场景一定可靠。
- 模型真的理解了医学概念。
- 指标天然知道哪个错误更严重。真实医学任务必须先明确更关心 malignant 还是 benign。
这章最重要的是建立第一个闭环:数据进入模型,模型输出预测,损失函数衡量错误,优化器更新参数。
常见失败
- 如果命令找不到
llm_tutor,先运行uv sync --python 3.12。 - 如果 loss 完全不下降,先检查学习率、数据标准化和标签 shape。
- 如果只看 accuracy,可能会忽略某一类被系统性预测错的问题。