📑 本页目录(点开跳转)
01 / 先运行,再对照
先跑出第一个结果,
再问模型怎么学会的。
这一遍只要认出:准备数据、训练模型、用没参与训练的数据检查结果。
先抓住一个具体结果
先比较两个数字
如果训练集表现很好,测试集却明显变差,先记录差距。这个差距比“训练准确率很高”更值得关注;具体数值以你的运行结果为准。
接下来,按需要选一项
你现在想看什么?
这些入口是选择,不是必须按顺序完成的任务。
可以停在这里
这一遍只要认出:准备数据、训练模型、用没参与训练的数据检查结果。
需要更多细节时,继续看完整正文 →原有正文、图解和例子都在下方。按需跳转,不必一次读完。
01 · 10 分钟训练你的第一个模型
⏱ 24 分钟(读完全章;其中动手那段约 10 分钟)| ⭐ 核心 | 🔨 必须动手 | 不用下载任何数据
🎯 一句话
机器学习的完整流程只有四步:拿数据 → 切分 → 训练 → 考试。这一节你把它跑一遍,并且亲眼看到「过拟合」长什么样。
🔨 动手:复制这段代码跑
pip install numpy scikit-learn
# -*- coding: utf-8 -*-
"""10 分钟训练你的第一个模型 —— 不用下载任何数据"""
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.preprocessing import StandardScaler
# ===== 第 1 步:拿数据(sklearn 自带,569 个肿瘤样本,30 个特征)=====
X, y = load_breast_cancer(return_X_y=True)
print(f"数据形状:{X.shape} → {X.shape[0]} 个样本,每个 {X.shape[1]} 个特征")
print(f"标签:{set(y)} (0=恶性, 1=良性)")
# ===== 第 2 步:切分 —— 训练集用来学,测试集用来考试 =====
X_tr, X_te, y_tr, y_te = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y)
print(f"训练集 {len(X_tr)} 个,测试集 {len(X_te)} 个")
# ===== 第 3 步:训练两个模型 =====
# 模型A:逻辑回归(线性模型,需要标准化)
scaler = StandardScaler().fit(X_tr)
lr = LogisticRegression(max_iter=1000)
lr.fit(scaler.transform(X_tr), y_tr)
# 模型B:决策树,故意不限制深度
tree = DecisionTreeClassifier(random_state=42)
tree.fit(X_tr, y_tr)
# ===== 第 4 步:看结果 =====
print("\n" + "=" * 46)
print(f"{'模型':<16}{'训练集':>10}{'测试集':>10}{'差距':>10}")
print("=" * 46)
for name, m, Xa, Xb in [
("逻辑回归", lr, scaler.transform(X_tr), scaler.transform(X_te)),
("决策树(无限制)", tree, X_tr, X_te),
]:
tr = m.score(Xa, y_tr)
te = m.score(Xb, y_te)
print(f"{name:<16}{tr:>9.1%}{te:>10.1%}{tr-te:>10.1%}")
print("=" * 46)
# ===== 第 5 步:给决策树限制深度,再看 =====
print("\n决策树深度对效果的影响:")
print(f"{'最大深度':<10}{'训练集':>10}{'测试集':>10}{'差距':>10}")
for d in [1, 2, 3, 5, 10, None]:
t = DecisionTreeClassifier(max_depth=d, random_state=42).fit(X_tr, y_tr)
tr, te = t.score(X_tr, y_tr), t.score(X_te, y_te)
label = str(d) if d else "不限制"
print(f"{label:<10}{tr:>9.1%}{te:>10.1%}{tr-te:>10.1%}")
🎉 你应该看到这个
先看数据规模:形状为 (569, 30),即 569 个样本、每个 30 个特征。其中训练集 398 个,测试集 171 个。
再比较两种模型。下面保留示例运行记录,具体分数以你的环境输出为准;差距为训练准确率减测试准确率。
| 模型 | 训练集准确率 | 测试集准确率 | 差距(百分点) |
|---|---|---|---|
| 逻辑回归 | 98.7% | 98.8% | −0.1 |
| 决策树(无限制) | 100.0% | 91.8% | 8.2 |
观察决策树深度:训练集越来越好,不代表新样本上的表现同步变好。
| 最大深度 | 训练集准确率 | 测试集准确率 | 差距(百分点) |
|---|---|---|---|
| 1 | 92.7% | 91.2% | 1.5 |
| 2 | 96.5% | 91.8% | 4.7 |
| 3 | 98.0% | 92.4% | 5.6 |
| 5 | 99.5% | 93.0% | 6.5 |
| 10 | 100.0% | 91.8% | 8.2 |
| 不限制 | 100.0% | 91.8% | 8.2 |
这里逐个展示测试分数是教学观察。正式项目不能据此选择深度:应在训练集内部划出验证集或交叉验证,最后只用保留测试集评估选定方案。 恭喜,你训了两个模型,而且已经撞上了机器学习最重要的问题。
🔍 盯着这三行看
① 决策树训练集 100%,测试集只有 91.8%
对照
训练集 100% = 它把 398 个样本的答案「全背下来了」
测试集 91.8% = 遇到没背过的,就露馅了
这就是【过拟合 Overfitting】——
学会了「记住」,没学会「理解」
💡 人话类比:一个学生把往年真题答案全背了(训练集满分),但一考新题就不会(测试集拉胯)。他没学到规律,只记住了答案。
② 逻辑回归训练 98.7%、测试 98.8%,几乎没差距
它能力弱(画不出复杂的分界线),反而被迫去找真正的规律——所以泛化得好。
🔑 第一个反直觉结论:模型不是越强越好。 强到能背下全部数据,它就懒得去理解了。
③ 深度表格里那个「拐点」
流程图
这张表的形状,是整个机器学习的缩影。 第 5 章会把它讲透。
🧩 顺便认识了四个核心概念
| 概念 | 在代码里 | 什么意思 |
|---|---|---|
| 特征 Feature | X,形状 (569, 30) |
用来做判断的输入。每行一个样本,每列一个特征 |
| 标签 Label | y,值是 0/1 |
要预测的答案 |
| 训练/测试切分 | train_test_split |
留一部分不给模型看,用来当考卷 ⭐ |
| 过拟合 | 那个 8.2% 的差距 | 训练集好、测试集差 |
⚠️ test_size=0.3 那行是全代码最重要的一行。
不切分、拿训练集当考卷,你会得到 100% 的假象——这是新手第一大坑。
🔗 和站内其他章的关系
| 相关的地方 | 根因在这 |
|---|---|
| 推荐算法第 3 章「按时间切分,别随机切」 | 就是这里的切分,只是推荐场景要防未来信息泄漏 |
| Kaggle 第 2 章「训练策略与正则化」 | 正则化解决的就是这个过拟合 |
| Kaggle 「CV 分数和 LB 分数对不上」 | 同一个问题的竞赛版 |
🎮 玩一下(改代码比读文字有用)
- 换个模型:加一行
from sklearn.ensemble import RandomForestClassifier,试试随机森林,差距变小了吗? - 改切分比例:
test_size从 0.3 改成 0.5,训练数据变少后过拟合更严重还是更轻? - 换随机种子:
random_state改成 0、1、2,分数波动有多大?——这个波动幅度,决定了「涨 0.5% 算不算真的涨」
🔗 这一章连到哪里
| 去哪 | 为什么 |
|---|---|
| 推荐算法 01 | 同一套「先跑通再问为什么」,那边 10 分钟做出一个推荐系统 |
| 智能体 01 | 同一套节奏的 Agent 版,不用 API Key 也能跑 |
| Kaggle 25 | ⭐ 这一章那段代码的工业版:同样是先有能跑的最小闭环,再逐环替换 |
✅ 检查点
- 机器学习的四步流程是什么?
- 决策树训练 100%、测试 91.8%,说明什么?
- 为什么能力更弱的逻辑回归反而泛化更好?
- 为什么必须切出测试集?
- 深度表格里的「拐点」意味着什么?
👀 答案
- 拿数据 → 切分(训练/测试)→ 训练 → 在测试集上考试。
- 过拟合——它背下了训练数据而没学到规律,遇到没见过的就不行。
- 它画不出太复杂的分界线,没能力去"背",只能去找真正的规律,所以泛化好。模型不是越强越好。
- 不切分就只能拿训练集评估,模型背下答案就是 100%,你会得到完全虚假的信心。
- 拐点之前模型在学真规律(训练测试同涨),之后开始背答案(训练涨测试跌)。拐点就是最优复杂度。
🛑 可以停在这里
⚡ 走神救援
先记住这几件事
- 一次训练包括划分数据、拟合模型和在留出数据上评估。
- 模型见过的训练数据不能替代测试集,比较时保留一致的数据划分。
- 先保留能跑通的基线,再一次改变一个因素、记录分数变化。
下一节 👉 02-机器学习到底在干什么.md