Skip to content

Repository files navigation


这是 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,保留自然序关系
目标编码(关键修复) NeighborhoodExterior1st 等高基数类别,改为每折 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 调优、目标编码扩展列、树模型原生类别处理、模型级离群策略、伪标签半监督——均经对照实验验证无稳定增益,未纳入最终流程。


📊 实验结果

8 个基模型的 OOF 表现

在 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 条样本、数百维稀疏特征的场景里,线性模型的特征选择优势反而更占主导。

Optuna 调参前后对比

模型 调参前(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,验证非线性架构在小样本结构化数据上的真实价值
分位数回归 / 两阶段建模 针对误差分析中暴露的极端价格段偏差

📌 License

  • 代码:MIT
  • 数据与赛题:版权归 Kaggle / Dean De Cock

About

Ames房价预测 · Kaggle竞赛

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages