机器学习实践项目(二)- 房价预测增强篇 - 额外知识
本来想把本项目结束掉的,在看代码的过程中发现没讲清楚StratifedKFold和KFold的区别,所以另开一贴讲讲,来,让爱老师上场总结。
涉及代码:
y_bins = pd.qcut(y_log, q=10, labels=False, duplicates="drop")
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
stratified_splits = list(skf.split(X, y_bins))
🧩 一、KFold 与 StratifiedKFold 的核心区别总结
| 对比项 | KFold | StratifiedKFold |
|---|---|---|
| 🔹 目标 | 随机平均划分数据 | 保持每折中目标分布一致 |
| 🔹 适用场景 | 一般任务(尤其是特征较平衡的回归) | 分类任务,或回归中目标分布极不均匀 |
| 🔹 是否考虑目标分布 | ❌ 否,只按样本顺序或随机划分 | ✅ 是,确保每折目标的比例/分布近似一致 |
| 🔹 连续目标能否直接用 | ✅ 可以直接用 | ❌ 不行,要先通过 pd.qcut() 分层(转成伪类别) |
| 🔹 优点 | 简单、速度快 | 更稳定、泛化更公平 |
| 🔹 缺点 | 各折目标分布可能差异大 | 需要额外的“分层”步骤(qcut) |
🧠 二、用“房价预测”例子来说明
假设我们有 10 套房子(房价单位:万元):
[50, 60, 70, 80, 100, 150, 200, 300, 400, 500]
房价显然分布不均:
大部分房子集中在 50–150 万,只有少量豪宅。
🧱 (1) 普通 KFold 的做法
比如 5 折划分(每折 2 套房):
Fold1: [50, 60] → 都是低价房
Fold2: [70, 80] → 仍是低价房
Fold3: [100, 150] → 中价
Fold4: [200, 300] → 稍高价
Fold5: [400, 500] → 豪宅
问题:
- 不同折的房价分布差异非常大;
- 模型在低价房上训练,在豪宅上验证,误差必然偏大;
- 每折验证结果差距大 → 模型评估不稳定。
📉 结果:CV 分数波动大,模型泛化性难判断。
🌈 (2) StratifiedKFold 的做法
第一步:用 pd.qcut() 按房价分层
import pandas as pd
y = [50, 60, 70, 80, 100, 150, 200, 300, 400, 500]
y_bins = pd.qcut(y, q=5, labels=False)
print(y_bins)
输出:
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
含义:
| 房价 | 分层(bin) |
|---|---|
| 50, 60 | 0(最低价) |
| 70, 80 | 1 |
| 100,150 | 2 |
| 200,300 | 3 |
| 400,500 | 4(最高价) |
第二步:用 StratifiedKFold 按层均衡切分
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for fold, (tr_idx, va_idx) in enumerate(skf.split(range(len(y)), y_bins)):print(f"Fold{fold+1} -> val_idx:", va_idx)
StratifiedKFold 会保证:
每一折中,都有一个“低价”“中价”“高价”“豪宅”的样本。
例如(示意):
| 折号 | 验证集(含各价位) |
|---|---|
| Fold1 | [50, 150, 400] → 低+中+高 |
| Fold2 | [60, 100, 500] → 低+中+高 |
| Fold3 | [70, 200] → 中价+高价 |
| … | … |
这样每折都包含了不同价格层的样本,房价分布均衡。
📈 结果:每折验证误差更接近真实泛化误差。
⚙️ 三、StratifiedKFold 的“均衡”原理
可以理解为三步:
-
先分层(Stratify):
把目标变量划分成若干层(bins)。
回归任务需要手动pd.qcut()实现。 -
再切分(KFold):
在每个层中平均分配样本到 K 折。 -
组合折:
每一折都由各层样本拼接而成。
→ 每一折中,目标分布都与总体分布相似。
📊 就像一盒混合水果(苹果🍎、香蕉🍌、橘子🍊、葡萄🍇),
KFold 可能随机拿到全是苹果,
而 StratifiedKFold 保证每盒都有一点苹果、香蕉、橘子、葡萄。
✅ 四、一张表总结 KFold vs StratifiedKFold
| 特性 | KFold | StratifiedKFold |
|---|---|---|
| 是否随机切分 | 是 | 是 |
| 是否保持目标分布 | 否 | 是(按分层信息) |
| 是否适用于连续目标 | 可以,但不分层 | 可以,需先分层(qcut) |
| 各折样本分布 | 可能不均衡 | 分布尽量接近总体 |
| 验证结果稳定性 | 波动大 | 稳定、可靠 |
| Kaggle 房价项目推荐 | ❌ 普通 KFold | ✅ StratifiedKFold(分层K折) |
💬 五、一句话总结
KFold:只是把数据平均切成几份,不管目标分布。
StratifiedKFold:会先按目标的分布(比如房价高低)分层,再在每层里平均抽样,确保每一折都“高低价都有”。
👉 对于像 Kaggle 房价预测这种 目标值分布偏斜的回归任务,
使用 pd.qcut() + StratifiedKFold 是更稳妥、更公平的做法。
最后,上一张图片来说明普通的KFold和StratiedKFold的区别。

我们来解析一下这张图。
🎯 整体思路
这张图是为了直观展示:
KFold 和 StratifiedKFold 在“划分房价数据”时的差别。
图分两部分:
- 左侧:KFold 随机划分(不均衡)
- 右侧:StratifiedKFold 分层划分(均衡)
🧩 左边:KFold(普通随机划分)
你会看到左边有几条彩色的“条带”,每一条代表一折(fold)。
这些彩色块代表房价区间,比如:
- 蓝色:低价房
- 橙色:中价房
- 红色:高价房
在左边的 KFold 部分:
- 每一折颜色分布不一样,有的几乎全是蓝色(低价房),
- 有的全是红色(高价房),
- 有的中间掺一点橙色。
这表示:
KFold 是随机切分,不管高价还是低价样本,
所以不同折之间房价分布差异非常大。
📉 结果:验证结果波动大,模型稳定性差。
🌈 右边:StratifiedKFold(分层均衡划分)
右边同样也有几条“条带”,表示 5 折。
但每一折都呈现:
蓝 + 橙 + 红 都有,比例差不多。
这表示:
StratifiedKFold 会在切分前先按房价区间(通过 qcut)分层,
确保每一折都有相似比例的低价、中价、高价房。
📈 结果:
模型每折训练/验证的数据分布更均匀,
→ 验证分数更稳定,模型泛化能力更可信。
📊 用文字总结图中的含义
| 对比点 | KFold 随机切分 | StratifiedKFold 分层切分 |
|---|---|---|
| 切分依据 | 仅按样本数量 | 按目标值(房价)分层 |
| 每折分布 | 随机、可能偏 | 均衡、接近总体分布 |
| 适用于 | 平衡数据集 | 分类任务、偏斜回归任务 |
| 房价预测效果 | 可能波动大 | 稳定、评估更可靠 |
🧠 一句话总结
这张图展示的是:
KFold 是“随机切片蛋糕”,有的全是奶油有的全是水果;
StratifiedKFold 是“每片都切一点奶油一点水果”,口味更均衡。
好啦,到了这里,大家应该对两者的区别有了认识了吧。
