尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Kaggle房价预测实战:代码运行、特征工程与提交避坑

Kaggle房价预测实战:代码运行、特征工程与提交避坑 简介Kaggle房价预测比赛代码.zip是一份面向数据科学入门与进阶学习者的完整参赛源码包聚焦房价预测这一经典回归任务涵盖从数据清洗、特征构建到模型训练与评估的全流程。压缩包共13个文件包括7个CSV数据文件、5个Python脚本和1个Markdown说明文档CSV存放训练集、测试集与提交样例Py脚本对应随机森林、集成提升、堆叠、神经网络等不同建模方案MD文档提供项目说明与用法指引整体仅274KB轻量易上手。已有250人学习下载。通过学习这份代码可直观理解Kaggle竞赛的标准工作流如何处理缺失值与异常值、构造面积比例等有效特征、比较线性回归/XGBoost/LightGBM等模型效果并利用交叉验证与超参数调优提升精度同时掌握MSE、RMSE、R^2等评估指标的实际运用。代码结构清晰模块化划分明确适合希望将理论落地为实战项目、快速积累竞赛经验的学习者反复研读。1. kaggle房价预测比赛代码.zip 到底装了什么解压前先搞清三件事kaggle房价预测比赛代码.zip 是很多初学者接触 Kaggle 竞赛时最先下载的代码包。它通常围绕 Kaggle 官网的 House Prices: Advanced Regression Techniques 展开目标是拿 79 个特征预测房屋成交价。你把这个 zip 解压后会看到 train.csv、test.csv 以及若干个 Python 脚本或 Notebook。这篇文章不讲空概念直接按“打开 zip → 跑通 → 调参 → 避坑 → 验证”的顺序带你把这份代码变成能提交的 submission.csv。适合第一次跑 Kaggle 竞赛、手头有现成代码但跑不起来的人。2. 环境与文件结构让这份代码在你机器上跑起来的第一步很多下载下来跑不起来的代码问题不在模型而在环境和路径。你拿到 zip 后不要急着双击运行先花十分钟把它拆开看清楚。2.1 先别急着运行zip 里的文件都对应什么常见的 kaggle房价预测比赛代码.zip 里至少有下面几类文件你可以建一个清单逐个核对。文件典型内容作用train.csv1460 行含 Id 和 SalePrice训练样本最后一行是目标值test.csv1459 行没有 SalePrice待预测样本行数一般比 train 少 1sample_submission.csv两列 Id、SalePrice官方提交模板列名不能改动data_description.txt每个字段的含义特征工程必须对照的手册train.py / main.py / model.ipynb训练与预测逻辑主代码可能只有一个 Notebookrequirements.txt依赖包列表帮助复现环境不是必须的先用一条命令看目录结构find . -maxdepth 2 -type f | sortWindows 上可以执行dir /s /b。如果你发现代码在根目录、数据在data/子目录就要么把脚本挪出来要么改代码里的读取路径。不要对着一个相对路径硬跑这是最基础的一个坑。拿到文件后我建议先预览一下数据表的形状import pandas as pd train pd.read_csv(train.csv) print(train.shape) print(train.columns.tolist()[:10])输出大概会是(1460, 81)意思是 1460 个样本、81 列其中一列是 Id一列是 SalePrice剩下 79 个是特征。注意这里第一列是 Id不是行索引。读取时不要设index_col0否则后面提交时 Id 顺序容易搞丢。2.2 用虚拟环境隔离依赖Python 版本与 pip 安装我一般会给每个竞赛项目单独建一个虚拟环境避免不同项目之间的依赖打架。房价预测这类代码用到的主要是 pandas、numpy、scikit-learn、xgboost 和 lightgbmPython 3.8 到 3.11 都能跑。如果你看到代码里用了sklearn.compose或DictVectorizer3.9 以上的版本更省心。python -m venv kaggle_house source kaggle_house/bin/activate # Windows 下执行 kaggle_house\Scripts\activate pip install --upgrade pip pip install pandas numpy scikit-learn xgboost lightgbm jupyter如果你的机器比较老xgboost 或 lightgbm 装不上可以先只装 scikit-learn用RandomForestRegressor也能跑出一个不算差的 baseline。代码包如果带了 requirements.txt直接一行安装pip install -r requirements.txt这里有个非常常见的报错ModuleNotFoundError: No module named sklearn.cross_validation。这是老代码在追旧版本 scikit-learn 导致的。新版里cross_validation已经改名为model_selection把导入语句改成from sklearn.model_selection import train_test_split就能继续跑。类似这种“示例代码讲解”里不会明说的兼容问题遇到一个改一个不要反复降版本折腾环境。2.3 路径是新手的第一道坎用相对路径还是绝对路径很多下载来的代码写的是pd.read_csv(../input/train.csv)这是 Kaggle Notebook 里的写法放到本地立刻报 FileNotFoundError。你可以把数据文件复制到脚本所在目录或者用下面这个相对稳的方式# 统一从脚本所在目录找数据 from pathlib import Path BASE_DIR Path(__file__).resolve().parent train pd.read_csv(BASE_DIR / train.csv) test pd.read_csv(BASE_DIR / test.csv) sub pd.read_csv(BASE_DIR / sample_submission.csv)逻辑说明Path(__file__).resolve().parent取的是当前脚本的绝对路径无论你从哪个目录执行命令数据路径都被锚定在脚本目录下不会再出现“命令行在 A 目录、脚本在 B 目录”导致的找不到文件。之后所有输出文件也建议写到BASE_DIR / output下避免和原始数据混在一起。路径稳定之后还要注意数据文件本身的编码。train.csv 一般是 UTF-8如果代码里没有指定encoding中文字符串可能报解码错误。读取时可以显式加encodingutf-8。数据列名和 Id 保持原样不要手动重命名否则后面坑更多。3. 跑通基线从默认参数到第一份 submission 文件环境通了之后目标是尽快拿到一份能提交的 CSV。这个阶段不需要追求高分先让整条链路走通你才知道后面每一步调整影响的是哪里。3.1 最小可行的基线模型读取数据、填补缺失、训练这里给一个完整的最小脚本它可以跑通 80% 的房价预测代码包。复制到项目根目录命名为 baseline.py 运行即可。# baseline.py import numpy as np import pandas as pd from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_log_error train pd.read_csv(train.csv) test pd.read_csv(test.csv) # 目标取对数让右偏的 SalePrice 更接近正态分布 y np.log1p(train[SalePrice]) X train.drop(columns[Id, SalePrice]) X_test test.drop(columns[Id]) # 缺失值填充数值列用中位数类别列用 None for col in X.columns: if X[col].dtype object: X[col] X[col].fillna(None) X_test[col] X_test[col].fillna(None) else: X[col] X[col].fillna(X[col].median()) X_test[col] X_test[col].fillna(X_test[col].median()) # One-Hot 编码测试集可能少列必须对齐训练集 X pd.get_dummies(X) X_test pd.get_dummies(X_test) X_test X_test.reindex(columnsX.columns, fill_value0) X_train, X_val, y_train, y_val train_test_split( X, y, test_size0.2, random_state42 ) model RandomForestRegressor(n_estimators200, max_depth12, random_state42) model.fit(X_train, y_train) pred model.predict(X_val) score np.sqrt(mean_squared_log_error(y_val, pred)) print(RMSLE:, score) # 生成提交文件注意用 expm1 还原预测值 test_pred model.predict(X_test) sub pd.DataFrame({Id: test[Id], SalePrice: np.expm1(test_pred)}) sub.to_csv(submission.csv, indexFalse)逻辑说明训练前对 SalePrice 做np.log1p是房价预测的关键一步因为官方指标是 RMSLE它本身就在 log 空间计算。预测完成后必须用np.expm1还原成原始房价再写进提交文件。参数说明n_estimators200是随机森林的树数量越大越稳但越慢max_depth12限制每棵树的深度防止过拟合test_size0.2表示拿 20% 的样本做本地验证random_state42固定随机种子保证别人复现你的分数和提交结果。新手想快速验证流程可以把n_estimators降到 50跑通后再加回去。如果你拿到的代码是.ipynb文件就打开 Jupyter Notebook 按 cell 从上往下执行。不要在没导入 pandas 的情况下跳着运行中间某个 cell示例代码讲解里经常有人跳过数据预览直接跑训练最后报NameError。3.2 必须遵守的提交格式sample_submission.csv 长什么样先看官方模板的样子head -5 sample_submission.csv输出大概是Id,SalePrice 1,121403 2,150475 3,132172这看起来很简单但提交格式错误是新手最常见的失败原因之一。Id 的顺序必须和 test.csv 一致列名必须严格是Id,SalePrice不能有多余空格也不能改成小写。很多代码在清洗数据时对 test 做了排序结果 Id 被重排线上直接判格式错误。生成提交文件后用一个自查脚本拦截低级问题sub pd.read_csv(submission.csv) sample pd.read_csv(sample_submission.csv) assert list(sub.columns) list(sample.columns), 列名不一致 assert len(sub) len(sample), 行数不一致 assert (sub[Id].values sample[Id].values).all(), Id顺序不一致 print(格式检查通过)这段代码值得一直保留。因为你改完特征或者调完参之后未必还会每一轮都检查列数和顺序加一个 assert 能在几秒内发现问题省下一次无效提交的机会。3.3 让预测结果还原RMSLE 的 log 陷阱如果你像 3.1 那样对 y 做了np.log1p那么模型预测出来的是 log 尺度的数值直接提交会得到一个偏离实际的 SalePrice。必须用np.expm1还原也就是exp(x) - 1。下面这个函数把训练、预测、提交三条逻辑固定在一起减少遗忘def save_submission(model, X_test, test_ids, pathsubmission.csv): raw_pred model.predict(X_test) pred np.expm1(raw_pred) # 如果训练时取过 log1p sub pd.DataFrame({Id: test_ids, SalePrice: pred}) sub.to_csv(path, indexFalse) return sub参数说明raw_pred是 log 空间的预测值np.expm1(raw_pred)是np.log1p的逆操作。如果训练时没取过对数千万不要加这一步否则预测值会全部变成巨大的数。判断依据很简单看训练代码里y np.log1p(...)有没有出现有就加没有就不加。4. 提升分数特征工程与模型参数的调整路线baseline 跑通之后本地 RMSLE 可能停在 0.16 到 0.20。想继续往下压要同时动特征和模型。这部分不是玄学每一步都有可验证的分数变化。4.1 先看数据分布SalePrice 为什么要取对数先用一行代码看 SalePrice 的分布import matplotlib.pyplot as plt import seaborn as sns sns.histplot(train[SalePrice], bins50) plt.show() train[LogSalePrice] np.log1p(train[SalePrice]) sns.histplot(train[LogSalePrice], bins50) plt.show()你会看到原始 SalePrice 明显右偏少数豪宅把尾巴拖得很长。取对数之后分布接近钟形树模型和线性模型都更容易拟合。这也解释了为什么官方评估指标选择 RMSLE它惩罚相对误差而不是绝对误差。一栋 5 万的房子预测偏差 1 万比一栋 500 万的房子偏差 1 万严重得多。特征工程的第一步就是确保所有特征在逻辑上都对得上这个目标。比如 OverallQual 的取值是 1 到 10它是综合质量评分对房价影响很大不要把它当成普通数值做缩放。有些代码会对它做 one-hot也可以但树模型下保留原始整数更高效。注意这个比赛数据集不是 sklearn 波士顿房价那个老数据集两者字段完全不同别拿波士顿的 13 个特征往这里套。4.2 组合特征与缺失值策略不要拿到手就 One-Hot房价预测里有很多字段含义重叠比如 TotalBsmtSF、1stFlrSF、2ndFlrSF 都是面积单独给模型看不如先合成一个总面积。常见的组合特征有def build_features(df): df df.copy() df[TotalSF] df[TotalBsmtSF] df[1stFlrSF] df[2ndFlrSF] df[OverallGrade] df[OverallQual] * df[OverallCond] df[HasPool] (df[PoolArea] 0).astype(int) df[HasGarage] (df[GarageArea] 0).astype(int) df[HasBasement] (df[TotalBsmtSF] 0).astype(int) for col in df.select_dtypes(includeobject).columns: df[col] df[col].fillna(None) return df逻辑说明HasPool、HasGarage把连续面积变成二值标记让树模型直接根据“是否有”做切分。OverallGrade是质量和条件的交互项能抓到“质量高但条件差”这类特殊房屋。类别列的缺失值统一填None而不是填众数因为缺失本身可能就代表“没有车库”“没有地下室”。这里要提醒一个常见的错误认知不是所有缺失值都要填充。像 Alley、PoolQC、MiscFeature 这些字段缺失往往表示“没有这个设施”填None是对的信息而 GarageArea 缺失可能真的是数据遗漏用中位数补才有意义。所以特征处理要按字段语义分组不能一把梭。4.3 模型选型与关键参数LightGBM、XGBoost 该调谁房价预测这类表格型数据梯度提升树几乎总是比随机森林表现好。你拿到的代码包如果只用了随机森林可以从 LightGBM 开始替换训练速度快而且参数好调。常用参数如下。参数建议范围作用调参注意learning_rate0.01 到 0.05每棵树贡献的收缩步长越小越稳但要加大 n_estimatorsn_estimators500 到 3000树的数量配合 early_stopping不用手工死磕num_leaves31 到 127每棵树的叶子数过大容易过拟合小数据别超过 64max_depth3 到 7树的最大深度LightGBM 里一般不用XGBoost 里常用subsample0.7 到 0.9每棵树随机采样行比例小于 1 能防过拟合colsample_bytree0.7 到 0.9每棵树随机采样列比例特征多时建议开小一个稳定的训练流程是先用默认参数跑通再逐步下调 learning_rate同时增大 n_estimators配合早停。下面这段代码是常见做法import lightgbm as lgb from sklearn.model_selection import KFold params { objective: regression, metric: rmse, learning_rate: 0.01, num_leaves: 31, max_depth: 5, subsample: 0.8, colsample_bytree: 0.8, verbosity: -1, seed: 42, } kf KFold(n_splits5, shuffleTrue, random_state42) scores [] for train_idx, val_idx in kf.split(X): X_tr, X_va X.iloc[train_idx], X.iloc[val_idx] y_tr, y_va y.iloc[train_idx], y.iloc[val_idx] model lgb.LGBMRegressor(**params, n_estimators2000) model.fit( X_tr, y_tr, eval_set[(X_va, y_va)], callbacks[lgb.early_stopping(100), lgb.log_evaluation(200)] ) pred model.predict(X_va) scores.append(np.sqrt(mean_squared_log_error(y_va, pred))) print(CV RMSLE:, np.mean(scores))逻辑说明KFold会把数据切成 5 份轮流用 4 份训练、1 份验证最终得到 5 个分数再平均这个均值比单次留出法更可信。early_stopping(100)表示验证集分数连续 100 轮不提升就停止训练能省下一大半时间。log_evaluation(200)是每 200 轮打印一次分数避免刷屏。参数说明如果你发现训练集分数和验证集分数差距很大先把num_leaves调小、subsample调低。如果两个分数都很低再考虑加大n_estimators或新增特征。不要一上来就搜索一大堆参数先把 learning_rate 和 early_stopping 这套组合用熟。模型层面还有一个简单有效的动作用同一套特征分别训练 LightGBM 和 XGBoost再把两个模型的预测取平均通常比其中任何一个低 0.005 到 0.01。5. 避坑手册zip 解压到提交常见的 5 个问题这部分每条都是真实出现过的问题按“现象 → 原因 → 解决”来整理。5.1 解压后文件名乱码代码找不到 train.csv现象zip 在 Windows 下解压后出现train​.csv这类乱码文件名Python 读文件报 FileNotFoundError。原因zip 内部记录文件名的编码不统一很多 Windows 压缩工具用的是 GBK而 Python 的 zipfile 默认按 UTF-8 解码解出来的名字就会变成乱码。解决不要手动改名直接用 Python 按正确编码重新解压import zipfile with zipfile.ZipFile(kaggle房价预测比赛代码.zip) as zf: for info in zf.infolist(): name info.filename.encode(cp437).decode(gbk, errorsignore) print(name) with zf.open(info) as src, open(name, wb) as dst: dst.write(src.read())这个脚本先把文件名按 cp437 编码还原成字节再用 gbk 解码成正常中文或英文。如果你在 macOS 或 Linux 上解压遇到类似问题把gbk换成utf-8再试一次。如果解压时提示要密码先别急着找“zip 密码移除”工具很多包只是伪加密文件头标记了加密位但内容没加密网上找一段改 flag 的脚本就能解开。正常竞赛代码不会加密遇到加密包大概率是来路不明的谨慎使用。5.2 运行报 ModuleNotFoundError代码对不上环境现象执行python train.py后报No module named xgboost。原因当前 Python 环境里没有安装 xgboost或者你建了虚拟环境但没有激活系统解释器还是原来的。解决先确认当前解释器再安装缺的包which python pip list | grep xgboost source kaggle_house/bin/activate pip install xgboost如果 pip 安装时一直在编译报错常见于老版本的 Python 缺少与新版 xgboost 对应的预编译 wheel可以先升级 pip再强制用预编译版本pip install --upgrade pip pip install xgboost --only-binary :all:不要因为某个包装不上就把 Python 版本从头换一遍。先查报错末尾的提示是ModuleNotFoundError还是ImportError后者往往是包内部依赖冲突比如 numpy 版本太低升级 numpy 就行。5.3 测试集拼接后少列预测直接报错现象训练完成后对测试集执行model.predict(X_test)报错Number of features of the model must match the input。原因pd.get_dummies在训练集和测试集上分别生成列如果测试集里某个类别没有出现就会少一列导致测试集特征数比训练集少。解决在编码完成后用训练集的列去对齐测试集X_test pd.get_dummies(X_test) X_test X_test.reindex(columnsX_train.columns, fill_value0)reindex会保留X_train.columns指定的列顺序测试集缺少的列自动补 0。注意这句话必须在get_dummies之后、模型训练之前执行。如果你用的是 sklearn 的ColumnTransformer它内部会自动处理但纯 pandas 写法的代码包很容易踩这个坑。5.4 本地交叉验证很高提交排名却掉一大截现象本地五折 RMSLE 是 0.120提交线上变成 0.145排名比预期低很多。原因最常见的是数据泄漏。比如代码先pd.concat([train, test])合并后再统一做缺失值填充或标准化这会让训练集提前看到测试集的信息本地验证自然虚高。另一个原因是 KFold 的随机种子太固定某一次的切分碰巧容易拟合。解决把所有预处理步骤写成“先 fit 训练集再 transform 测试集”。缺失值填充时用train.median()填充测试集不要在测试集上重新计算中位数。类别编码同理先用训练集定义类别列表测试集只映射这些类别。另外把随机种子从 42 换成 2024 再训一次看分数波动是否在 0.005 以内超过这个范围说明模型不稳定优先处理特征而不是急着调参。5.5 提交提示格式错误原来是 Id 顺序问题现象Kaggle 页面显示提交成功但分数为 0或者提示Your submission scored incorrectly。原因生成的 submission.csv 中 Id 的顺序和 test.csv 不一致。有些代码在特征处理时调用了sort_values对测试集排序但提交时又直接取排序后的 Id就错位了。解决提交前必须运行 3.2 小节的自查脚本逐项检查列名、行数、Id 顺序。如果你确实需要对测试集排序先把原始 Id 单独保存一份最后再合并test_ids test[Id].copy() # 后续对 test 随便排序只要最终提交用 test_ids 就行 sub pd.DataFrame({Id: test_ids, SalePrice: pred})注意sub[Id]的长度必须和pred一致否则 pandas 会按位置对齐而不是按 Id 对齐这是一个安静的坑报错时很难发现。6. 提交前的最后验证让本地 CV 和线上分数对得上最后一关不是模型是验证你的评估标准是不是可信。这里有一个很实用的习惯在本地用和官网相同的 RMSLE 指标对预测结果做一次完整回评。from sklearn.metrics import mean_squared_log_error # 如果你在验证集上预测的是还原后的真实值先取 log 再算 true_val np.expm1(y_val) # 如果 y_val 是 log1p 后的值 pred_real np.expm1(pred) score np.sqrt(mean_squared_log_error(true_val, pred_real)) print(最终 RMSLE:, score)逻辑说明mean_squared_log_error要求输入是原始尺度所以必须先还原再计算。这一步能在提交前发现 log 还原遗漏、量纲错误等问题。我每次提交前都会跑一遍这个回评并且和训练时打印的 RMSLE 做对比如果差超过 0.01说明训练代码和评测代码之间有不一致的地方。另一个进阶技巧是“多折多次取平均”。单纯五折的 RMSLE 波动较大建议做 5 折重复 3 次每次换不同的随机种子取 15 个分数的均值作为本地 CV。这个均值如果和线上分数差距在 0.01 以内说明你的评估管道没有问题。如果差距始终在 0.03 以上优先回去查数据泄漏而不是继续调参。最后提交前固定一个检查清单列名是否一致、行数是否一致、Id 顺序是否一致、是否用了 expm1 还原、本地 RMSLE 是否在合理范围。我第一次提交时忘了还原 log线上分直接 1.2后来把提交代码封装成save_submission函数每次都强制经过自查脚本再没在这个问题上翻过车。希望这些经验能帮你少走一段弯路祝顺利提交出自己满意的分数。本文还有配套的精品资源点击获取
返回列表