这是 Kaggle 经典赛题 House Prices: Advanced Regression Techniques 的完整实验记录。用艾姆斯(Ames, Iowa)的 79 个住宅特征预测售价,评估指标是 log(SalePrice) 的 RMSE。
整个项目从一套朴素的基线出发,逐步迭代到 CV log-RMSE = 0.11073(加权集成,25 折重复评估),较最初版本提升了 14.2%。过程中踩过目标泄漏的坑、验证过不少"看起来有用"但实际无益的特征,最终留下这份可复现的 notebook。
核心发现:小样本 + 高维稀疏特征的场景下,精心构造的线性模型能打败调参后的 XGBoost。 这不是反直觉的结论,但值得亲手验证一次。
# 1. 安装依赖
pip install -r requirements.txt
# 2. 运行 notebook(自动检测库:有 xgb/lgb/optuna 时全量增强)
jupyter notebook ames-price-perspective.ipynb
# 或命令行执行:
jupyter nbconvert --to notebook --execute --inplace ames-price-perspective.ipynb
# 3. 生成提交(notebook 第 6 节自动写出 output/submission.csv)💡 两种运行模式:本机只装了 sklearn 也能跑——XGB/LGB/Optuna 相关章节会自动跳过,流程照样通;服务器环境齐全时则自动开启全量增强(完整结果见
ames-price-perspective.kaggle.ipynb)。
Ames price prediction-kaggle/
├── ames-price-perspective.ipynb # 主 notebook(推荐从这里开始)
├── ames-price-perspective.pre-batchA.ipynb # batch A 前的对照版本
├── prices-pretidict-by-LightGBM.ipynb # LightGBM 单模型实验
├── data/ # 原始数据与字段说明
├── output/ # 历史提交文件(按日期归档)
├── score/ # Kaggle Leaderboard 截图
├── report/ # 实验报告(Markdown / HTML / PDF)
├── requirements.txt
└── README.md / README.en.md
- 训练集:1 460 条,81 列(含目标
SalePrice) - 测试集:1 459 条,80 列(需预测
SalePrice) - 特征构成:23 个数值型 + 23 个有序品质型(如
Ex > Gd > TA > Fa > Po)+ 23 个纯类别型 + 若干标识/日期列
数据的一个特点是 "缺失"本身携带语义:PoolQC 为空代表"没有游泳池",Bsmt* 为空代表"没有地下室"。直接把这类缺失当成普通 NaN 用均值插补,会损失大量信息。
以下按迭代顺序记录关键决策,而不是罗列所有尝试。
| 环节 | 做法与取舍 |
|---|---|
| 目标变换 | log1p(SalePrice) 消除右偏(skew 从 1.88 降至 0.12),这是所有后续模型的基础 |
| 缺失语义化 | 将"无设施"类 NA 编码为特殊值;品质字段中"无设施" =-1,与"质量极差(Po = 1)"区分开;LotFrontage 按社区中位数插补 |
| 有序编码 | Ex/Gd/TA/Fa/Po → 5/4/3/2/1,保留自然序关系 |
| 目标编码(关键修复) | Neighborhood、Exterior1st 等高基数类别,改为每折 Pipeline 内平滑目标编码(m=20),仅用训练折的 y 计算。这修复了旧版用全量 y 排名导致的 P0-1 目标泄漏 |
| 组合特征 | 总面积、总浴室、房龄、翻新间隔、质量汇总等15 个 |
| 面积比值(Batch A) | 面积类变量取对数 + 地上/地下/车库占比、每房间地块面积等8 个。这是 v2.1 最大的单点增益(Lasso 约 -0.0025) |
| 交互特征 | 质量×面积、目标编码×面积/房龄、面积×房间数等12 个+,经 CV 筛选保留 |
| 离群处理 | 对GrLivArea > 4000 的两条"大而便宜"样本做了 drop / winsorize / keep 对照,选定 drop。增益显著且稳健 |
| 建模 | 线性族:LassoCV / ElasticNetCV / Ridge;树族:GB / HistGB / RF / XGBoost / LightGBM,共8 个基模型 |
| 调参 | Optuna TPE 贝叶斯搜索(XGB / LGB / HistGB 各 30 trials × 3 折),配合折内 early_stopping |
| 评估 | 多 seed(5×5=25 折)重复评估,报告 mean±std,避免单 seed 乐观偏差 |
| 集成 | OOF 权重精化加权平均(爬山法 + bootstrap 稳定性校验),以及 Stacking(meta=RidgeCV) |
| 后处理 | 提交前将 log 预测值 clip 到训练集的 [1%, 99%] 分位,抑制极端外推 |
弃用的尝试:缺失计数特征、m 调优、目标编码扩展列、树模型原生类别处理、模型级离群策略、伪标签半监督——均经对照实验验证无稳定增益,未纳入最终流程。
在 25 折重复评估下,各模型的 log-RMSE 如下:
| 模型 | OOF log-RMSE (mean ± std) | 备注 |
|---|---|---|
| LassoCV | 0.11211 ± 0.00662 | 🏆 最佳单模型 |
| ElasticNetCV | 0.11254 ± 0.00682 | |
| Ridge | 0.11403 ± 0.00747 | |
| GradientBoosting | 0.11957 ± 0.00691 | |
| XGBoost | 0.11919 ± 0.00815 | 树族最优(调参后) |
| HistGB | 0.12265 ± 0.00823 | |
| LightGBM | 0.12456 ± 0.00711 | |
| RandomForest | 0.13256 ± 0.00679 |
一个有趣的观察:即使给 XGBoost 上了 Optuna 贝叶斯搜索(30 trials × 3 折 + early stopping),它的 25 折 OOF(0.11919)仍然追不上 LassoCV(0.11211)。在 1,460 条样本、数百维稀疏特征的场景里,线性模型的特征选择优势反而更占主导。
| 模型 | 调参前(seed42, 5 折) | 调参后(25 折) | 提升 |
|---|---|---|---|
| XGBoost | 0.12152 | 0.11919 | −0.0023 |
| LightGBM | 0.12689 | 0.12456 | −0.0023 |
| HistGB | 0.12452 | 0.12265 | −0.0019 |
| 方案 | CV log-RMSE |
|---|---|
| v1 基线 Stacking(原始特征) | 0.12909 |
| 旧版加权集成(含目标编码泄漏,5 折 seed42) | 0.11146(偏乐观) |
| 最佳单模型 LassoCV(25 折) | 0.11211 ± 0.00662 |
| Stacking(seed42) | 0.11177 |
| 加权平均(OOF 权重精化,25 折,8 模型) | 0.11073 ✅ |
权重结构的变化值得注意:修复目标编码泄漏后,集成权重从旧版"Lasso 0.536 + XGB 0.322 两极主导"变成了更均衡的分布——线性三兄弟(Lasso/EN/Ridge)合计约 0.62,五个树模型各分到 0.07 左右互补。Bootstrap 100 次重采样下权重标准差 0.004~0.046,整体稳定。
多 seed 评估会戳破单 seed 的乐观泡沫。 同一套 Lasso 特征,单 seed 5 折报 0.11245,换成 5×5=25 折后就变成 0.11402——偏乐观约 0.002。这个差距在排行榜上可能就是几十名的区别。如果只看单 seed 结果,很容易误判某个特征或模型的真实价值。
面积比值(Batch A)是性价比最高的特征工程。 仅增加 8 个比值/对数特征,Lasso 的误差就从 0.1152 降到 0.1128(-0.0025),而且不需要调参、不需要额外库。相比之下,花了不少时间的缺失计数特征和 TE 扩展列,对照实验显示无益,最终弃用。这提醒我们:特征工程里"看起来合理"不等于"验证有效"。
加权集成优于 Stacking,而且更简单。 在这个数据集上,精心调权的平均(0.11073)比 Stacking(0.11177)更好。Stacking 的 meta-learner 似乎过拟合了基模型之间的共变关系,而直接优化 OOF 权重反而更稳健。
按预测价格分段回检 OOF 误差,模型在不同价位表现差异明显:
| 价格段 | 误差特征 |
|---|---|
| < 12 万美元 | 误差最大(log-RMSE ≈ 0.164),且系统性高估 |
| 12–16 万美元 | 中等误差 |
| 16–20 万美元 | 最优区间(log-RMSE ≈ 0.083) |
| 20–30 万美元 | 中等误差 |
| > 30 万美元 | 系统性低估 |
低价段的问题可能是样本少 + 异质性高(老旧房、 foreclosure、特殊卖家动机),而高价段则受限于顶部样本稀疏和特征天花板。中价段(16–20 万美元)因为样本充足、特征区分度好,模型表现得最舒服。如果要继续优化,分位数回归或针对极端价格段的两阶段建模可能是值得尝试的方向。
| 方向 | 思路 |
|---|---|
| CatBoost | 原生有序目标统计(Ordered Target Statistics),对 Ames 大量有序品质型特征可能更友好 |
| 自动化特征搜索 | featuretools 或遗传算法,系统挖掘高阶交互,减少手工尝试的盲目性 |
| 深度学习基线 | TabNet / FT-Transformer,验证非线性架构在小样本结构化数据上的真实价值 |
| 分位数回归 / 两阶段建模 | 针对误差分析中暴露的极端价格段偏差 |
- 代码:MIT
- 数据与赛题:版权归 Kaggle / Dean De Cock