
简介面向机器学习课程设计场景的Python大作业基于线性回归实现波士顿房价预测完整覆盖数据导入、训练集与测试集划分、数据归一化、模型训练、损失曲线绘制、测试集预测评估及可视化等环节并额外实现了小批量梯度下降算法适合初学回归任务的学生参考与复用。资源包共5个文件包含两个Python脚本、一张数据拟合效果图、一份说明文档和gitignore配置压缩包仅122KB结构精简清晰。代码采用梯度下降法BGD优化线性回归模型通过np.concatenate合并截距与权重参数经epochs次迭代更新参数并画出损失函数随迭代次数的变化曲线以观察梯度下降执行情况。项目已获导师指导并通过期末大作业评分为97分目前已有1453人学习下载完整确保可运行可作为课程设计和期末大作业直接使用下载即用无需修改。1. 线性回归与波士顿房价为什么这份97分大作业值得拆开看从boston.csv里读506条样本用13个特征去预测房价中位数MEDV是机器学习入门最有名的基准题之一。这份python源码大作业没有调sklearn.linear_model而是用批量梯度下降BGD从零实现线性回归覆盖读数据、切分训练集、归一化、手写梯度更新、画损失曲线、测试集评估和拟合可视化是一个完整的训练闭环。项目拿到了97分能直接作为课程设计和期末大作业提交但比能运行更值钱的是它把梯度下降的每一步都摊开在代码里。适合两类人一是要交作业、需要快速跑通改参数的学生二是想弄懂w w - lr * grad这行代码背后矩阵维度怎么对齐的入门者。2. BGD梯度下降与归一化训练前必须做对的两件事2.1 线性回归的矩阵形式与损失函数线性回归假设目标值y是特征x的线性组合。对波士顿房价这份数据来说特征有13维模型要学的是一组权重加上一个截距。把截距和权重合并用np.concatenate在特征矩阵第一列拼上全1样本矩阵从(m, 13)变成(m, 14)预测公式就统一成f(x) X w也就是一次矩阵乘法完成所有样本的预测。损失函数用均方误差的改良版本J(w) 1 / (2m) * ||Xw - y||²前面多出的1/2不是多余的求导后平方项的指数会乘到系数上正好和1/2约掉梯度表达式写出来干净很多。LinearRegression_1.py的整个训练循环都是围绕这个公式展开的只要在纸上把X的形状画成(506, 14)、w画成(14,)后面所有维度问题都能推出来。2.2 特征归一化代码Min-Max还是Z-Score波士顿数据里TAX特征取值从一百多到七百多RM只有几到十几量纲差距接近两个数量级。如果不做归一化梯度在各特征方向上的步长差别巨大损失曲线会呈锯齿状来回跳动收敛极慢。常见的做法是Min-Max归一化把每列特征缩放到0到1之间def normalize(x): x_min x.min(axis0) x_max x.max(axis0) return (x - x_min) / (x_max - x_min), x_min, x_maxaxis0表示按每一列特征分别计算最小值与最大值而不是在整个矩阵上取一个标量。返回的x_min和x_max必须保留下来因为测试集进入模型前要用同一组参数做变换而不是重新算一遍。这份源码的逻辑是先归一化特征矩阵X目标值MEDV保持原始房价数值这样后续评估R2、RMSE时数字直观。如果目标值也被压缩到0到1计算出的误差就没有物理含义了。Z-Score归一化在类似作业里也很常见每列减去均值除以标准差对存在异常值的列更稳但波士顿数据分布相对规整Min-Max够用。注意归一化参数只能从训练集上计算。如果先对全量数据归一化再切分测试集信息会渗入训练过程这就是所谓的数据泄漏答辩时老师经常在这里追问。2.3 BGD、SGD与MBGD的选型对比项目主推BGD原因是这个数据集只有506行样本全量计算一次梯度的矩阵乘法开销完全可以接受。三种梯度下降策略各自的特点整理如下策略每次更新使用样本收敛稳定性计算开销适用场景BGD全部样本最稳定损失单调下降每轮最高小数据集、课程作业SGD1个样本震荡大但可能跳出局部极小每轮最低在线学习、大数据集MBGDbatch_size个样本折中折中大多数实际训练任务BGD的缺点是每轮遍历全部样本更新方向最准但迭代速度慢SGD用单样本算梯度噪声偏大损失曲线会上下抖动。这份作业末尾补了MBGD实现本质上就是在这张表里取中间档后面第5章会专门讲改造方法。选型没有绝对好坏样本量、算力、收敛要求共同决定选哪一档。3. LinearRegression_1.py从csv读取到BGD训练闭环的完整拆解3.1 boston.csv的特征字段与读取方式数据文件是boston.csv506行、14列。前13列依次是CRIM犯罪率、ZN住宅占地比、INDUS非零售商业用地比、CHAS是否临河、NOX氮氧化物浓度、RM平均房间数、AGE老房占比、DIS到就业中心距离、RAD高速可达指数、TAX房产税率、PTRATIO师生比、B非裔人口比例换算值、LSTAT低收入人群占比最后一列MEDV是房价中位数单位是千美元。sklearn在新版本已经移除了load_boston()接口所以课程大作业普遍改用本地csv文件落地读取逻辑。读入数据后先做一次基础探查用data.describe()看每列的值域分布重点确认CRIM和TAX这类量纲特别大的列它们直接影响归一化方式和训练收敛速度。import pandas as pd data pd.read_csv(boston.csv) X data.iloc[:, :-1].values # 前13列特征 y data.iloc[:, -1].values # 最后一列MEDV房价iloc[:, :-1]选中除最后一列外的所有列组成特征矩阵iloc[:, -1]单独取目标值。这里直接用values转成numpy数组是为了后续矩阵乘法和np.concatenate操作更顺手省去pandas索引的开销。3.2 train_test_split与归一化的执行顺序先切分后归一化是这个项目最容易被抄错的顺序正确代码如下from sklearn.model_selection import train_test_split train_x, test_x, train_y, test_y train_test_split( X, y, test_size0.2, random_state42 ) train_x, x_min, x_max normalize(train_x) test_x (test_x - x_min) / (x_max - x_min)test_size0.2表示留出约20%的样本做最终预测验证random_state42固定随机种子保证作业每次跑出来的划分结果一致。如果去掉这个参数每次运行切分不同模型的评估分数会有几个百分点的随机波动报告中写出的R2就不可复现了。测试集归一化必须复用训练集算出的x_min和x_max这一步就是前面提到的防泄漏关键。有些实现图省事把测试集单独调用一次normalize()模型输入的分布被人为改变了评估结果会失真这是代码评审里能看到的最典型扣分项。3.3 训练函数np.concatenate合并截距与权重BGD_4.py里最核心的是训练函数骨架如下def model(train_x, train_y, lr0.01, epochs1000): m, n train_x.shape ones np.ones((m, 1)) X np.concatenate((ones, train_x), axis1) # 第一列全1对应截距 w np.zeros(n 1) J_history [] for epoch in range(epochs): f_x X w # 前向计算维度(m,) loss 0.5 * np.mean((f_x - train_y) ** 2) grad (1 / m) * X.T (f_x - train_y) # 梯度维度(n1,) w w - lr * grad J_history.append(loss) return w, J_historynp.concatenate((ones, train_x), axis1)在列方向拼接把截距和13个特征的权重合并成14维向量w。循环内每个epoch做四个操作求f_x、求损失J(w)、求梯度、更新参数。X.T (f_x - train_y)是X^T(Xw-y)的矩阵形式得到维度(14,)的梯度向量和w逐元素对齐。关键参数有三个。lr0.01是相对保守的起步学习率epochs1000比实际需求略多用来观察损失曲线走完后是否还有下降趋势。w np.zeros(n1)从全零初始化对线性回归这种凸问题没有局部极小点风险全零起步和随机初始化最终收敛结果基本一致。如果损失出现nan优先检查lr是不是超过0.1或归一化步骤是否被跳过。参数作用推荐值调参方向lr控制每次更新的步长0.01损失震荡时调小epochs训练轮数1000曲线未平缓时调大test_size测试集比例0.2数据量大时可降至0.33.4 预测时别忘了补全1列测试集预测是另一个高频踩坑点。训练时X已经拼接成14列预测时直接拿归一化后的test_x和w相乘会报维度不匹配需要再补一次全1列test_X np.concatenate((np.ones((test_x.shape[0], 1)), test_x), axis1) y_pred test_X w常见错误是调试sklearn模型习惯了忘了手写模型的特征维度和权重维度必须人工对齐。排查这类问题先把w.shape和test_X.shape打出来确认两者第一维一致。y_pred得到的是测试集预测房价单位是千美元画图和计算误差时都直接用它。4. 损失曲线与R2评估测试集预测效果怎么看4.1 损失函数曲线的收敛迹象训练循环里每次迭代都把loss追加进J_history画图只需两行plt.plot(range(len(J_history)), J_history) plt.xlabel(epochs) plt.ylabel(loss)观察点集中在三处曲线是否平滑下降后期是否趋于水平是否出现周期性震荡。lr过大时损失先降后升或来回反弹lr过小时下降像直线一样平缓1000轮结束还没走到谷底。BGD全量更新理论上损失每轮都在下降一旦看到反弹就可以怀疑数值溢出、学习率太大或归一化没有执行。还可以对纵轴做对数坐标把前几轮的下降细节放大更直观地判断是否进入平缓区。4.2 评估指标R2、RMSE、MAE测试集评估集中在代码后半段核心逻辑如下from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error r2 r2_score(test_y, y_pred) rmse np.sqrt(mean_squared_error(test_y, y_pred)) mae mean_absolute_error(test_y, y_pred) print(fR2{r2:.3f}, RMSE{rmse:.3f}, MAE{mae:.3f})R2是最常被单独汇报的数字表示模型解释目标方差的比例。这个数据集上纯手写BGD加Min-Max归一化R2落在0.68到0.80之间都属于正常水平不必迷信网上那些0.85以上的截图很多是特征工程或交叉验证做得更深的成果。RMSE和房价保持相同单位能直观说明平均预测错几千美元MAE则对极端值更不敏感。三个指标一起报更能说明模型状态指标含义建议R2解释方差比例0.7以上即及格RMSE均方根误差与房价单位一致MAE平均绝对误差比RMSE更稳健4.3 拟合效果可视化作业要求里的展示数据拟合效果最常见的是预测值与真实值的散点图加对角线plt.scatter(test_y, y_pred, alpha0.6) plt.plot([test_y.min(), test_y.max()], [test_y.min(), test_y.max()], r--)对角线是理想状态点越贴近红线预测越准。波士顿数据在两端即房价低于10千美元和高于40千美元的区域通常会明显偏离对角线因为线性模型天然会压缩极值。散点图整体偏移时先检查归一化参数是否在测试集上被错误地重新计算出现水平带状分布时检查y_pred是否被意外截断或四舍五入过。用plt.colorbar给点按RAD或LSTAT染色还能看出模型在哪些特征区间预测偏差大这一手在答辩展示里很加分。5. 从BGD到MBGD减少震荡与稳定收敛的进阶实现5.1 小批量梯度下降的代码改造BGD每轮用全部样本算一次梯度稳定但循环次数多。MBGD把整批样本切成小份每份算一次梯度改造后代码如下def mbgd(train_x, train_y, lr0.01, epochs200, batch_size32): m, n train_x.shape X np.concatenate((np.ones((m, 1)), train_x), axis1) w np.zeros(n 1) for epoch in range(epochs): idx np.random.permutation(m) # 每轮打乱样本顺序 for i in range(0, m, batch_size): batch_idx idx[i:i batch_size] X_b, y_b X[batch_idx], train_y[batch_idx] grad (1 / len(batch_idx)) * X_b.T (X_b w - y_b) w w - lr * grad return wnp.random.permutation(m)把样本索引打乱防止样本固定顺序带来的梯度偏差是MBGD和SGD共用的关键操作。内层循环每次取batch_size个样本计算梯度506条样本、batch_size为32时一个epoch内有约16次参数更新。直接用BGD的epochs1000跑MBGD会导致更新总次数显著膨胀所以epochs要同步调小到200附近。5.2 学习率与batch_size的搭配MBGD调参时我一般按下面这组组合起步组合学习率batch_size表现稳妥0.0132收敛稳定震荡小激进0.0516收敛快后期轻微震荡保守0.00564训练慢接近BGD行为batch_size越小梯度噪声越大学习率要相应调小batch_size越大越接近BGD学习率可以适当放大。最快的调参路径是先固定lr0.01依次试16、32、64三档batch_size观察损失曲线选震荡最小的档位再微调lr。绘制损失曲线时MBGD的单轮loss会有波动可以把每50轮的均值额外画一条平滑线看总趋势比盯单次值有效。5.3 答辩和报告中能直接用的两个验证技巧第一个技巧训练时把归一化参数存到npz文件预测还原时直接用。作业环境里模型训练和预测往往在同一个进程但如果要演示加载已有模型归一化参数必须持久化np.savez(norm_params.npz, x_minx_min, x_maxx_max)测试时读取后先还原y_pred再和test_y做差得到的误差单位是千美元比归一化空间里的抽象数字更容易向老师解释。第二个技巧MBGD受随机打乱影响每次跑出的损失曲线不完全重合。报告中说明这一特性并贴出同一组参数跑三次的曲线叠加图证明收敛趋势稳定比只贴一次结果更能体现对梯度下降原理的理解。这两处改动都很小却是评分里工程完整度最常见的加分点来源。本文还有配套的精品资源点击获取