ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

波士顿房价预测实战:线性回归完整源码与避坑指南

波士顿房价预测实战:线性回归完整源码与避坑指南 简介基于线性回归实现波士顿房价预测的Python源码大作业是一份适合机器学习初学者与相关课程学生的完整课程设计/期末项目。压缩包内共5个文件包含2个Python脚本、1张可视化结果图、1个说明文档及gitignore配置整体仅122KB轻量且结构清晰便于快速部署学习。目前已有1454人学习下载。项目采用批量梯度下降BGD与小批量梯度下降MBGD两种方式优化线性回归模型围绕波士顿房价数据展开完整实现从数据导入、训练集与测试集划分、数据归一化到模型参数初始化与迭代更新、损失函数变化曲线绘制、测试集预测评估及拟合效果可视化等环节。代码获得导师指导并评定为97分高分下载即可运行、无需修改附带的说明文档和结果图片可辅助核对关键步骤适合作为课程设计参考或毕业设计基础帮助读者深入理解线性回归原理、梯度下降策略及机器学习项目的基础流程。1. 波士顿房价预测大作业为什么第一个回归模型都选它现在打开搜索引擎搜“线性回归 python 源码”十有八九会撞上波士顿房价预测这个经典项目。作为机器学习课程里最常被布置的大作业之一它几乎成了每个初学者接触回归任务的第一道坎。但有意思的是这个题目背后的数据集已经在较新版本的 scikit-learn 中被移除了——很多照着老教程敲代码的同学卡在第一步导入数据就翻车。这不是你的问题是版本迭代的坑。这个项目的本质是用 13 个与房产相关的特征如犯罪率、房间数、城镇师生比去拟合一个连续值——房价中位数。线性回归之所以被选作教学案例是因为它足够简单假设特征与目标之间存在线性关系然后用最小二乘法找到一组权重让预测误差的平方和最小。整套逻辑透明、可解释性强而且代码量少到能在一页纸里写完。这篇文章会从环境准备讲到完整源码再到评估、调参和踩坑记录。无论你是正在赶大作业的学生还是想用这个项目入门机器学习照着做就能跑通跑通了就能讲明白。2. 动手前把环境与原理备齐sklearn 版本、数据集形状与线性回归的边界2.1 线性回归的核心逻辑最小二乘法在做什么线性回归的数学形式很简单y w1*x1 w2*x2 ... w13*x13 b。目标是找一组权重w和偏置b让预测值y_hat和真实值y之间的均方误差MSE最小。这里有个关键点均方误差对权重求导后会得到一个闭式解也就是正规方程Normal Equation。这意味着线性回归不需要像神经网络那样反复迭代一步就能算出最优权重。代码里sklearn.linear_model.LinearRegression底层默认用的是最小二乘法基于 SVD 分解训练过程快得几乎没有体感。但线性回归的边界也在这里它只能捕捉特征与目标之间的线性关系。如果真实世界里的房价不是线性的——比如面积翻倍但价格涨了三倍——线性回归就会欠拟合。大作业阶段你不太需要担心这一点但要能说出这个局限报告里写一句“未来可尝试多项式特征或树模型”就是得分点。2.2 环境准备Python 版本与关键库的安装顺序这个项目依赖四个库numpy、pandas、matplotlib、scikit-learn。建议使用 Python 3.8 到 3.12 之间的版本官方维护的新版本大概率兼容。# 建议先升级 pip再逐个安装避免依赖冲突 python -m pip install --upgrade pip pip install numpy pandas matplotlib scikit-learn逻辑说明numpy提供数组运算支持pandas用来加载和查看数据matplotlib负责画预测值与真实值的对比图scikit-learn提供线性回归模型和数据划分工具。安装顺序上没有严格依赖但先装numpy和pandas可以避免后续某些包在安装时检查依赖失败。参数说明如果你的机器上同时存在 Python 2 和 Python 3请用python3 -m pip install确保装进正确的环境。Windows 用户如果遇到pip 不是内部或外部命令多半是没把 Python 的 Scripts 目录加进 PATH重装 Python 时勾选“Add Python to PATH”就能解决。2.3 波士顿房价数据集从内置到外迁版本差异怎么处理波士顿房价数据集是 1978 年统计的 506 条样本每条样本包含 13 个特征和 1 个目标值房价中位数单位千美元。在 scikit-learn 1.0 之前的版本里可以直接用load_boston()加载。但在 1.2 版本之后这个数据集被移除了。原因是它包含一些有争议的变量比如与种族相关的指标且不适合作为现代机器学习教学的默认案例。官方建议改用fetch_california_housing或自己加载 CSV 文件。不过对于大作业来说你完全可以从网上下载boston.csv到本地用pandas.read_csv读取。另外也可以用数据集内置的方案from sklearn.datasets import fetch_openml # 从 OpenML 加载波士顿房价数据集 data fetch_openml(nameboston, version1, as_frameTrue) print(data.data.shape) # 查看特征矩阵形状506 行13 列 print(data.target[:5]) # 查看前 5 个目标值逻辑说明fetch_openml需要联网但它比找乱七八糟的第三方 CSV 靠谱得多。返回值是 Bunch 对象data.data是特征矩阵data.target是目标向量。as_frameTrue会返回 pandas DataFrame方便直接操作。参数说明nameboston指定数据集名称version1指定版本。如果网络环境不稳定会抛出urllib.error.URLError这时候要么换网络要么退回到手动下载 CSV 的方式。3. 基于线性回归实现波士顿房价预测完整可运行的 python 源码3.1 从读取数据到训练模型核心代码全流程下面这段代码是完整可运行的保存为boston_linear_regression.py直接执行即可。它包含了数据加载、训练测试集划分、模型训练和评估四个环节是我自己反复精简后给学生作为模板的版本。import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import fetch_openml from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score # 1. 加载数据 data fetch_openml(nameboston, version1, as_frameTrue) X data.data y data.target # 2. 拆分训练集和测试集8:2 比例固定随机种子保证可复现 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) # 3. 创建并训练线性回归模型 model LinearRegression() model.fit(X_train, y_train) # 4. 预测并评估 y_pred model.predict(X_test) mse mean_squared_error(y_test, y_pred) mae mean_absolute_error(y_test, y_pred) r2 r2_score(y_test, y_pred) print(fMSE: {mse:.4f}) print(fMAE: {mae:.4f}) print(fR2: {r2:.4f}) # 5. 画图真实值 vs 预测值 plt.figure(figsize(8, 6)) plt.scatter(y_test, y_pred, alpha0.6) plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--) plt.xlabel(True Price) plt.ylabel(Predicted Price) plt.title(Boston Housing: Linear Regression) plt.show()逻辑说明第 2 步拆分数据集是整个流程里最需要理解的一步train_test_split会随机打乱数据后按比例切分random_state42保证每次运行切分结果一致——这一点在交作业时很重要老师复现你的代码能得到相同结果不会因为随机性对不上。第 3 步的fit就是模型在“学习”线性回归在这里完成 SVD 分解并求出权重。第 4 步的三个指标分别衡量误差的平方平均、误差的绝对平均和模型对方差解释的比例。参数说明test_size0.2是常见做法意味着 506 条样本中约 101 条留给测试集。如果你数据量小、想要训练得更充分可以调到0.15但测试集太小会导致评估结果不稳。random_state可以换成任何整数只要固定即可它的值不影响模型质量只影响数据切分方式。3.2 输出模型系数让作业有“解释性”的加分项线性回归和黑匣子模型最大的区别在于它的每一个特征都有一个明确的权重系数正负号直接告诉你这个特征和房价是正相关还是负相关。这一小节的内容在大作业报告里非常加分因为多数同学只贴了分数的截图很少有人展示系数含义。# 继续使用上一小节的 model 和 X feature_names X.columns coef_dict dict(zip(feature_names, model.coef_)) # 按绝对值从大到小排序 sorted_coef sorted(coef_dict.items(), keylambda item: abs(item[1]), reverseTrue) for name, coef in sorted_coef: print(f{name}: {coef:.4f})逻辑说明model.coef_是训练完成后模型学到的权重向量长度等于特征数量。zip把特征名和权重配对再按绝对值排序。绝对值越大说明该特征对房价的影响越强。这一步能让你在报告里直接写出“LSTAT低收入人口比例与房价负相关系数为 -0.95是所有特征中影响最大的因素”比单纯贴个 R² 分数有说服力得多。参数说明这里没有需要调的超参数但要注意model.coef_是 numpy 数组直接和列表zip没问题但打印时最好用:.4f格式化不然会出现一长串小数影响报告整洁度。3.3 交叉验证用 robust 的方式评估模型稳定性单次划分训练集和测试集存在运气成分——如果测试集恰好都是些好预测的样本分数会虚高。交叉验证是解决这个问题的标准方案把数据切成 K 份轮流拿一份做验证其余 K-1 份做训练最终取平均分。from sklearn.model_selection import cross_val_score # 5 折交叉验证评估 R² 分数 cv_scores cross_val_score(model, X, y, cv5, scoringr2) print(f5-fold R2 scores: {cv_scores}) print(fAverage R2: {cv_scores.mean():.4f} (/- {cv_scores.std():.4f}))逻辑说明cross_val_score是 sklearn 提供的一行式交叉验证工具它会自动帮你完成切分、训练、评估的循环。cv5表示 5 折输出结果会是 5 个 R² 分数。这里用的model是之前已经fit过的实例但cross_val_score内部会在每一折重新复制并训练模型不会污染你已有的模型状态这是很多初学者容易误解的地方。参数说明cv的取值常见为 5 或 10。数据量只有 506 条时cv10会让每一折训练集过小方差变大cv5是稳妥选择。scoringr2指定评估指标如果你想看 MSE改为scoringneg_mean_squared_error即可——注意 sklearn 里的负号约定误差类指标都是“负的越小越好”用来统一“分数越高越好”的接口。4. 评估模型与写报告决定作业分数的关键数值4.1 三个指标怎么读MSE、MAE、R² 各自的侧重点模型训练完不是终点能解释清楚评估指标才是老师判断你是否真懂的依据。这三个指标在大作业里基本是必写项但很多同学的报告只写了公式没写解读。平均绝对误差MAE的单位和房价一致就是“平均每个预测偏离真实值多少千美元”。如果 MAE 是 3.2说明平均预测偏差 3200 美元。均方误差MSE把误差平方了所以大误差会被放大它对离群点更敏感。R² 是拟合优度取值最大为 10.7 以上通常认为模型可接受0.8 以上算良好。一个具体的解读样例如果 R² 0.71可以写“模型解释了房价变动中 71% 的方差剩余的 29% 可能来自非线性关系或未纳入的特征如地理位置、房龄”。这种表达比单纯报数字成熟很多。4.2 残差图一眼看出模型哪里不行残差是“真实值减预测值”。如果模型假设成立残差应该随机分布在 0 附近没有明显模式。如果残差呈现喇叭形随预测值增大而增大说明存在异方差性如果残差和某个特征仍有关联说明该特征没有被线性地充分利用。residuals y_test - y_pred plt.figure(figsize(8, 5)) plt.scatter(y_pred, residuals, alpha0.6) plt.axhline(y0, colorr, linestyle--) plt.xlabel(Predicted Price) plt.ylabel(Residuals) plt.title(Residual Plot) plt.show()逻辑说明这段代码画的是“预测值为横轴、残差为纵轴”的散点图。对比上一节的真实值-预测值图残差图能更细致地暴露模型系统性问题。如果散点大致均匀地分布在 y0 上下两侧且无明显形状说明模型没有遗漏线性模式。这里给一个排查思路波士顿房价数据中房价被截断在 50千美元附近因为数据收集时对超过 50 的房价统一记为 50。这会在残差图右上角形成一条水平线属于数据集本身的特性不是模型漏洞但这种观察写进报告是加分项。4.3 报告结构老师最想看到的五个部分大作业最终交付物通常是一个 zip 包里面是 .py 代码和一份实验报告。报告结构不求花哨但逻辑链要完整。我一般建议按下面五段组织第一段写实验目的和数据集描述包括样本量 506、特征数 13、目标含义。第二段写模型原理最小二乘法一句话加一个公式即可不用铺开推导。第三段写实验过程包括数据划分比例 8:2、模型参数无超参数如有则说明取值理由、运行环境Python 版本、库版本。第四段写实验结果贴出 MSE、MAE、R²、交叉验证均值加一段文字解读。第五段写结论与不足结论 1-2 句不足方向写特征工程不足或线性假设限制。这套结构我让几十个学生用过反馈是“照着填就能把报告写到 B 以上”。关键是每一部分都要有数字支撑不要只写定性描述。5. 避坑线性回归大作业里的五个经典翻车现场5.1 翻车一新版本 sklearn 直接跑load_boston()报错现象运行from sklearn.datasets import load_boston时抛出ImportError报错信息类似“Cannot import name load_boston”。原因scikit-learn 1.2 版本移除了这个数据集。网上大量教程还在用老式写法照着敲必定翻车。解决换成fetch_openml(nameboston, version1, as_frameTrue)或者从本地 CSV 读入。如果你正在用的版本是 1.1 及以下load_boston()仍然可用但你会收到弃用警告建议直接改新写法免得换环境后还要改代码。5.2 翻车二fit的时候报 ValueError输入包含 NaN现象训练时报错提示输入数据包含 NaN缺失值或者直接是无穷大。原因波士顿数据集本身没有缺失值但如果你是从某些第三方网站下载的 CSV里面可能存在空单元格读入后被 pandas 转换成 NaN。解决在训练之前加一行清理代码。X X.dropna()会删掉包含缺失值的行但要注意这也会把对应的 y 删掉所以做得严谨一点应该先用布尔索引把有效行的索引筛出来再同时过滤 X 和 y。更稳妥的做法是valid_idx X.dropna().index然后X X.loc[valid_idx]y y.loc[valid_idx]保证 X 和 y 对齐。5.3 翻车三特征量纲差异导致某些系数大到离谱现象训练完成后打印出model.coef_发现 ZN占地面积比例的系数是 0.004CRIM犯罪率的系数是 -0.05看起来都很小而 RM房间数的系数却是 4.5。报告里写“CRIM 不重要”就是从这里来的误判。原因不同特征的数值范围差别很大。CRIM 取值范围 0.006 到 88RM 取值范围 3.5 到 8.8。系数是用来乘特征的所以量纲大的特征天然会得到数值小的系数不能直接比较大小。解决如果你要比较特征重要性先做标准化再训练。from sklearn.preprocessing import StandardScalerscaler StandardScaler()X_scaled scaler.fit_transform(X)然后用标准化后的数据重新训练。标准化之后的系数就可以按绝对值大小排序来解读了。注意标准化不影响模型预测质量对线性回归来说只影响系数可解释性。5.4 翻车四训练集分数远超测试集开始怀疑人生现象用model.score(X_train, y_train)得到 0.75用model.score(X_test, y_test)只有 0.59。原因这是过拟合的典型表现。波士顿数据集只有 506 条样本如果模型在训练集上拟合得过于精细把噪声当成规律学进去了测试集上就会表现差。解决对线性回归来说过拟合并不常见所以先检查是不是数据划分出了问题——比如测试集太小、随机性太大。把test_size改为0.3再试一次交叉验证的结果比单次划分更可靠。如果交叉验证平均分接近单次测试分数那单次低分可能只是运气问题不是模型问题。如果持续存在较大差距考虑正则化比如改用Ridge回归from sklearn.linear_model import Ridge ridge Ridge(alpha1.0) ridge.fit(X_train, y_train)参数说明alpha是正则化强度越大惩罚越重系数越趋向于 0。常见取值范围 0.1 到 10可以先从 1.0 开始试看验证集分数变化。这个改动在代码里只有一行但在报告里可以写成“为缓解过拟合对比了普通最小二乘与 L2 正则化的效果最终选择 alpha1.0 作为折中方案”。5.5 翻车五matplotlib中文显示成方块现象图表的标题和坐标轴标签里如果包含中文显示出来是一排小方块。原因matplotlib 默认字体不支持中文字符。解决在画图代码前加两行plt.rcParams[font.sans-serif] [SimHei] # 或用 Microsoft YaHei plt.rcParams[axes.unicode_minus] False # 解决负号显示问题逻辑说明第一行指定 sans-serif 字体族优先使用黑体第二行关闭 Unicode 负号否则坐标轴上的负号会变成方块。这个坑在交作业时特别致命——老师看图如果看到满屏方块第一印象就差了。如果你用的是 macOS把SimHei换成Arial Unicode MS即可。6. 进阶用回归系数反推业务逻辑让大作业从“跑通”变“能讲”线性回归在这个项目里最大的卖点不是性能而是可解释性。如果你想让大作业从“我跑通了”提升到“我能讲清楚”做一件事就够了构建一张特征影响表。拿标准化前的模型举例标准化后系数代表“特征变动一个标准差对房价的影响”更适合口头解读把 13 个特征的系数按绝对值排序然后找到正负相关最强的各 3 个特征分别解释它们的业务方向。以波士顿数据为例RM平均房间数正系数最大符合直觉——房间越多房价越高。LSTAT低收入人口比例负系数最强低收入人口聚集区域房价偏低。CRIM犯罪率负相关治安越差房价越低。这些结论不需要额外查资料从你的模型系数里就能读出来。表格可以这样做第一列特征名第二列系数第三列业务含义一句话第四列方向正/负。整个表放在报告的“结果分析”部分老师在翻报告时通常会在那里停留最久。如果你还有余力再做一个实验对比手动添加一个特征比如“房间数的平方”重新训练模型观察 R² 是否提升。这个实验目的是验证波士顿房价是否和面积存在非线性关系——提升说明有没提升说明线性假设在这个数据集上已经够用。代码上就是在 X 里加一列平方值三行就能跑完X[RM_sq] X[RM] ** 2 model_2 LinearRegression() model_2.fit(X_train, y_train) print(fR2 with squared RM: {model_2.score(X_test, y_test):.4f})逻辑说明RM_sq是手动构造的多项式特征把原有特征的平方加进去模拟非线性关系。代价是特征多了一列但线性回归框架不变。如果 R² 没有明显提升说明房价和房间数的关系接近线性也证明了原模型没有严重欠拟合。我自己的习惯是每次跑完线性回归都会顺手画一张系数柱状图横轴是特征名纵轴是系数值颜色按正负区分。一来报告里能用二来自己回头调试时扫一眼就能发现量纲异常。说实话这个习惯比很多花哨的调参技巧更值钱。项目做完去面试实习讲到这个图时面试官明显更愿意接着聊。记住一件事大作业本身不值钱值钱的是你能不能用这个简单模型讲出一个完整的故事——从数据到模型到结论到反思。波士顿房价项目练的就是这套链路。把这套链路走熟后面换任何数据集、换成逻辑回归或决策树你会发现框架完全不需要变。希望帮到你。本文还有配套的精品资源点击获取
返回列表