机器学习房价预测实战:从数据集到模型调参全指南 简介这套项目聚焦北京新房与二手房房价预测以机器学习完整流程为主线适用于毕业设计、期末大作业和课程设计也适合希望快速上手房价预测实战的初学者。资源覆盖数据采集、预处理、特征工程、模型训练与结果可视化代码注释细致依赖安装完成后简单部署即可运行作者自述为个人手打98分项目导师认可度高整体参考价值较强。压缩包共26个文件以 Python 脚本和 Jupyter Notebook 为主要分析载体包含链家、安居客爬虫脚本和 CSV 数据集另有可视化图表、HTML 分析报告、README 及配套文档压缩后仅1.29MB便于本地快速搭建环境。目前已有161人学习下载。下载后可以系统获得从数据爬取、清洗到房价建模评估的一站式方案既能用来观察北京二手房特征与成交价之间的关系也能直接作为项目答辩、课程展示或毕业设计演示的完整素材。1. 机器学习房价预测大作业到底在做什么期末周最让人头疼的不是算法推导而是“AI大作业”这四个字背后那个既要求有数据集、又要求有可运行源码、还要有文档的完整闭环。房价预测恰好是最适合当课程设计题目的方向数据好找、特征含义直观、模型效果能可视化而且从线性回归到随机森林、XGBoost都能往上套工作量弹性极大。这篇博文顺着“基于机器学习的房价和二手房房价预测”这个标题把数据集怎么选、源码怎么组织、文档资料怎么写清楚让大作业既过得了查重也经得起答辩追问。做这类项目的核心不是把模型精度刷到小数点后三位而是让老师看到你理解“数据 - 特征 - 模型 - 评估”这条完整链路。很多人喜欢一上来就调参结果问一句“缺失值怎么处理的”就答不上来印象分直接掉一半。下文按实际项目交付的顺序展开从数据集踩坑、特征工程、模型选型与调参到源码和文档的最终形态每一节都有可以直接抄进自己工程的代码和参数表。最后一章会给出三个验收前的自检技巧这些细节往往是区分“能跑”和“做好了”的关键。2. 房价预测数据集选择与预处理从波士顿到二手房源2.1 常用数据集对比与选型大作业选数据集的第一个原则是“别用已经被写烂的波士顿房价”。虽然sklearn.datasets.load_boston是经典教材案例但该数据集在 2019 年之后已从新版 scikit-learn 中移除而且它的字段只有 13 个做完特征工程后很难展示“你处理过数据”。更关键的是波士顿房价数据存在伦理争议不少课程老师已经明确不推荐。实用替代方案有三类各有适用场景数据集规模特征数适合场景获取方式加州房价California Housing20640 条8 个数值特征回归入门、特征分布分析sklearn.datasets.fetch_california_housing台北二手房Taipei Real Estate414 条6 个特征小样本演示、快速迭代UCI 机器学习库自爬链家/贝壳二手房数千到数万条10 含文本展示完整爬虫与清洗能力自行采集注意反爬与合规我的建议是如果只想安稳交付首选加州房价理由是数据加载不需要额外下载、字段说明文档齐全、样本量足够做 train/test 拆分和交叉验证。如果你想让大作业看起来“更有工作量”就选链家二手房数据但要处理好地址解析、单价单位换算、朝向和装修状态的文本转数值。注意自采数据时不要绕过登录验证破坏网站服务也不要在论文里公开具体爬取脚本的请求频率做几个页面样本即可。无论选哪个数据集拿到原始数据后的第一件事不是建模而是写一个describe()info()的探针脚本。这一步能直接暴露出缺失值、量纲差异和异常值比如房屋面积出现 0 平方米、房价单价为个位数等脏数据。把这些内容截图放进文档的“数据探索”章节比写三段空话更有说服力。2.2 数据清洗与特征工程的可复现步骤以一个标准二手房数据集为例包含总面积,厅室数,朝向,楼层,建筑年份,单价以及需要预测的总价预处理通常分四步走去重、缺失值处理、异常值截断、特征衍生。下面给出可直接运行的 Python 代码import pandas as pd import numpy as np df pd.read_csv(house_data.csv) print(df.shape, df.isnull().sum()) # 1. 去除完全重复记录 df df.drop_duplicates() # 2. 缺失值数值列用中位数填充类别列用众数填充 num_cols df.select_dtypes(include[np.number]).columns for col in num_cols: df[col] df[col].fillna(df[col].median()) cat_cols df.select_dtypes(include[object]).columns for col in cat_cols: df[col] df[col].fillna(df[col].mode()[0]) # 3. 异常值以总价为例超过99分位数或低于1分位数的置为边界值 lo, hi df[总价].quantile(0.01), df[总价].quantile(0.99) df[总价] df[总价].clip(lo, hi) print(df.describe())这段代码的逻辑说明drop_duplicates()去除因为爬虫重试导致的重复房源数值特征用中位数而不是均值填充是为了避免被偏态分布拉高clip()把极端房价截断而不是直接删除保留样本数量的同时限制异常值对模型的干扰。参数0.01和0.99是经验值如果你发现数据中单价百万和千万的房子混在一起可以调整分位数区间但不要低于0.005否则样本损失太多。特征工程环节老手和新手的分水岭在于是否做“领域特征”。只给模型总面积和厅室数太单薄我一般会再加三列房龄 当前年份 - 建筑年份、平均每厅室面积 总面积 / (厅数 室数)、是否满五唯一用于反映二手房税费成本。如果楼层是数值可以构造高层标识如果朝向是文本按[东,南,西,北]做 one-hot 时把“南北通透”这种组合朝向单独拆出is_south_north布尔列。特征不是越多越好但每一列都要能讲出“为什么对房价有影响”的理由答辩时这就是你的加分项。3. 基于机器学习的房价预测模型搭建线性回归到集成学习3.1 模型选型与评估指标房价预测是一个典型的有监督回归问题评估指标不是准确率而是误差。大作业最常用的是均方根误差RMSE和平均绝对误差MAERMSE 对大误差敏感能放大离群点的影响MAE 更稳健适合解释“平均差多少钱”。如果答辩老师问你为什么不用 R² 作为唯一指标你可以回答R² 表示模型解释的方差比例但它无法直接告诉我们预测值和真实值差多少万元对于房价业务来说误差的绝对金额更有意义。模型选型建议按“基线 - 线性 - 集成 - 调参”的顺序走不要一上来就上 XGBoost。先跑一个线性回归作为 baseline再对比岭回归和 Lasso然后用随机森林和梯度提升树看看能否明显下降误差。这样做的理由很实际线性模型揭示特征权重方向树模型自动处理非线性和交互项两者的对比能在文档“实验结果”章节写出 3 段有营养的分析。如果数据集只有几千条不需要上深度学习容易过拟合且训练时间更长答辩时还会被追问“为什么不选更简单的模型”。3.2 用 scikit-learn 跑通最小训练流程在完成特征工程后一个干净的最小训练脚本如下使用加州房价数据演示from sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, mean_absolute_error data fetch_california_housing() X, y data.data, data.target X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) scaler StandardScaler() X_train scaler.fit_transform(X_train) X_test scaler.transform(X_test) lr LinearRegression() lr.fit(X_train, y_train) y_pred lr.predict(X_test) print(LR RMSE:, mean_squared_error(y_test, y_pred, squaredFalse)) rf RandomForestRegressor(n_estimators100, max_depth10, random_state42) rf.fit(X_train, y_train) y_pred_rf rf.predict(X_test) print(RF RMSE:, mean_squared_error(y_test, y_pred_rf, squaredFalse)) print(RF MAE:, mean_absolute_error(y_test, y_pred_rf))逻辑说明train_test_split中的random_state42固定随机种子保证每次运行划分一致这是大作业必须养成的习惯。StandardScaler在训练集上fit_transform在测试集上只transform目的是防止测试集信息泄漏到训练过程。squaredFalse让mean_squared_error直接返回 RMSE数值单位与房价一致。随机森林的参数里n_estimators100是性能与时间的折中max_depth10限制单棵树深度以缓解过拟合。如果你自己采集的二手房数据特征量纲差异大面积几百、总价几百万线性模型必须做标准化树模型不依赖标准化但标准化不会带来负面影响统一处理可以让后续调参逻辑更简单。代码跑完后把 RMSE 和 MAE 记录在表格里这组数字就是文档的“实验结果”部分。3.3 关键参数调整与调参方向大作业不需要做超参搜索到极致但至少要调整随机森林和梯度提升的 3 个核心参数并在文档里给出调参前后对比。以RandomForestRegressor为例必调参数如下参数默认值调整方向作用n_estimators100200500树的数量越多方差越小但训练时间线性增加max_depthNone1030限制深度防止单棵树记忆噪声min_samples_leaf1510叶子节点最小样本数值越大越平滑max_features1.00.60.9每次分裂考虑的特征比例引入随机性减少过拟合可以用GridSearchCV做一个小范围搜索但要注意网格过大会导致时间爆炸。我通常的做法是先固定n_estimators300用RandomizedSearchCV对另外三个参数跑 20 组然后查看最佳参数from sklearn.model_selection import RandomizedSearchCV from scipy.stats import randint param_grid { max_depth: randint(5, 30), min_samples_leaf: randint(1, 10), max_features: [0.6, 0.8, 1.0] } search RandomizedSearchCV( RandomForestRegressor(n_estimators300, random_state42), param_distributionsparam_grid, n_iter20, cv5, scoringneg_root_mean_squared_error, random_state42 ) search.fit(X_train, y_train) print(search.best_params_)这段代码的逻辑cv5表示五折交叉验证评估指标用负 RMSEscikit-learn 的优化方向是越大越好n_iter20控制在 20 组随机组合内搜索比网格搜索快得多。调参后的模型别忘了重新在完整训练集上训练一次然后再评估测试集顺序不要乱。如果调参后测试集误差比训练集误差大很多说明过拟合优先增大min_samples_leaf或减少max_depth。4. 项目源码组织与文档资料配套大作业提交的完整形态4.1 源码目录结构与模块划分很多人大作业只交一个 Jupyter Notebook能跑但结构混乱答辩时演示到一半找不到下一个 cell。规范的做法是把代码拆成模块化目录让老师一眼看出你有工程意识。推荐结构如下house_price_project/ ├── data/ │ ├── raw/ # 原始数据集CSV/Excel │ └── processed/ # 清洗后的数据 ├── src/ │ ├── data_preprocess.py # 数据清洗与特征工程 │ ├── train_model.py # 模型训练与评估 │ ├── predict.py # 加载模型并预测新样本 │ └── visualize.py # 绘制真实值与预测值对比图 ├── models/ # 保存训练好的模型文件 (.pkl/.joblib) ├── docs/ │ ├── 实验报告.md │ └── 项目说明.pptx ├── requirements.txt └── README.md每个 Python 文件只干一件事data_preprocess.py负责读入data/raw输出清洗后的data/processedtrain_model.py负责从 processed 数据中读取、训练、评估并把模型保存到models/predict.py提供命令行接口接受一个特征输入并返回预测房价。这样拆分之后如果答辩老师要求“换一个数据集再跑一次”你只需要修改data_preprocess.py里的读取路径其他模块不用动。requirements.txt必须写清楚依赖版本例如pandas2.0.3、scikit-learn1.3.0不要只写“pandas”不带版本否则不同环境可能因为版本差距导致 API 不兼容。4.2 文档资料包含哪些内容文档资料是很多人的短板总觉得“代码能跑就行”。实际上大作业的评分标准通常包含文档占比 30% 以上。一份合格的文档至少要有这六块问题定义、数据说明、特征工程方法、模型选择理由、实验对比、结论与不足。这里给出可直接套用的内容清单问题定义一句话说清楚是回归问题预测目标是房屋总价单位万元输入特征有哪些。数据说明表格列出每个字段的类型、缺失率、均值、标准差来源写清楚是公开数据集还是自采。特征工程至少写三点比如缺失值填充策略、异常值截断分位数、新增了哪些衍生特征并附上关键代码。模型选择线性回归作为 baseline随机森林和梯度提升作为集成模型各给一段原理简述和选型理由。实验对比表格展示 RMSE、MAE、训练时间最好有三组模型。结论与不足模型适合哪些类型的房屋哪些因素未被纳入如学区、地铁距离改进方向是什么。这里要特别注意不要直接复制数据集官方描述当文档老师一眼能看出来。用自己的话描述字段含义和分布哪怕只有三句也比你抄一段英文文档要强。4.3 从数据集到预测结果的全流程复现为了让老师能按 README 一步步复现我通常是写一个run_all.sh或者一条 Makefile 命令按顺序执行三行命令python src/data_preprocess.py python src/train_model.py python src/predict.py --input 100,3,1,2020,南逐行说明第一行生成data/processed/cleaned.csv第二行读取清洗结果训练模型并保存到models/rf_model.joblib同时输出测试集 RMSE第三行接受一个--input字符串格式与特征顺序对应内部调用predict.py中加载模型的函数返回预测总价。这样做的好处是评审老师不需要打开 Jupyter 一个个 cell 顺序执行直接跑一行命令即可验证项目可用性。在文档的“运行环境”部分写清 Python 版本3.9 或 3.10 均可和操作系统Windows/macOS/Linux 并注明如果遇到ModuleNotFoundError执行pip install -r requirements.txt。如果你使用 Anaconda建议导出环境文件conda env export environment.yml一并放在docs/下面。有了这套全流程即使老师不在你的电脑上也能自己跑通这是“工程完成度”的最直接体现。5. 结课验收前必做的 3 个验证技巧5.1 用交叉验证判断模型稳定性单次 train/test 划分的 RMSE 有运气成分换一个random_state数字结果可能波动 5%10%。大作业里正确做法是报告五折交叉验证的均值和标准差。用cross_val_score一行就能得到结果但我更习惯手写循环来保留每个折的预测值便于绘制误差分布from sklearn.model_selection import KFold from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error import numpy as np kf KFold(n_splits5, shuffleTrue, random_state42) rmses [] for train_idx, val_idx in kf.split(X_train): model RandomForestRegressor(n_estimators300, random_state42) model.fit(X_train[train_idx], y_train[train_idx]) pred model.predict(X_train[val_idx]) rmses.append(mean_squared_error(y_train[val_idx], pred, squaredFalse)) print(fCV RMSE: {np.mean(rmses):.3f} /- {np.std(rmses):.3f})这段代码里shuffleTrue让每个折的样本分布更接近整体避免按原始顺序折分导致的时间或地域偏差。如果标准差超过均值的 20%说明模型不稳定需要检查特征是否有异常样本或减少max_depth。把交叉验证结果写进文档比只放一个测试集 RMSE 更有说服力。5.2 预测结果可视化与误差分布检查模型好坏不能只靠数字还要看图。我通常画两张图第一张是真实值 vs 预测值的散点图对角线yx位置点越密集说明预测越准第二张是残差分布直方图如果残差近似正态分布在 0 附近说明模型没有系统性偏差。如果残差图呈现漏斗形误差随真实值增大而增大说明模型对高房价样本拟合不足可以考虑对目标变量做对数变换即预测np.log1p(y)评估时再np.expm1还原。可视化脚本的代码逻辑很简单但注意在文档中要给出图的解读。例如散点图在低价区间贴近对角线而高价区间偏离说明模型对低价房更准确。这句话比任何调参都更能体现你的数据分析能力。5.3 模型文件与依赖环境的可移植性验收时老师可能在你自己电脑看不到模型文件或者模型文件损坏。保证可移植性的两个关键操作第一训练完成后立即用joblib.dump保存模型而不是只保存在内存里第二保存特征列的顺序列表feature_names.json因为predict.py里构造新样本时特征的顺序必须与训练时完全一致。如果不幸丢失模型文件可以重新运行train_model.py但随机种子无法完全复现同一个模型因此模型版本管理和特征顺序备忘变得非常重要。最后一个技巧在答辩演示前运行一次python src/predict.py --input 100,3,1,2020,南确认输出不是报错而是具体数字如果输入格式里包含中文朝向文本检查data_preprocess.py里是否已经将该列转换为 one-hot。这个简单的冒烟测试能避免 80% 的演示翻车。把这三点都做进你的项目大作业即便拿不到最高分也绝对处于“能打”的那一档。本文还有配套的精品资源点击获取