ML-For-Beginners 回归作业实战:用 Scikit-learn 构建并评估线性回归与多项式回归模型
【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners
本篇技术指南围绕 ML-For-Beginners 第 2 章「回归」第 3 课作业(translations/es/2-Regression/3-Linear/assignment.md,英文原文见 2-Regression/3-Linear/assignment.md)展开:作业要求基于课程学到的线性回归(Linear Regression)与多项式回归(Polynomial Regression),自行寻找数据集(或使用 Scikit-learn 内置数据集)构建一个新模型,并在 notebook 中解释技术选型理由、演示模型精度。读完本文,你将掌握完整的作业完成路径:从数据清理、相关性分析,到用 Scikit-learn 训练模型、用 RMSE 与决定系数评估精度,直至对照评分标准自查提交。
作业要求解读
课程作业(Assignment "Create a Regression Model")的核心指令如下:
本课向你展示了如何使用线性回归和多项式回归构建模型。运用所学知识,找一个数据集,或使用 Scikit-learn 内置数据集,构建一个新模型。在你的 notebook 中解释你为什么选择该技术,并演示你模型的精度。如果模型不够精确,请解释原因。
英文原文(2-Regression/3-Linear/assignment.md):
In this lesson you were shown how to build a model using both Linear and Polynomial Regression. Using this knowledge, find a dataset or use one of Scikit-learn's built-in sets to build a fresh model. Explain in your notebook why you chose the technique you did, and demonstrate your model's accuracy. If it is not accurate, explain why.
拆解成可执行的任务清单:
- 数据来源二选一:自选公开数据集,或直接使用
sklearn.datasets内置数据集(如diabetes等经典回归集)。 - 模型构建:运用线性回归与(可选)多项式回归至少一种技术完成训练。
- 技术选型论证:在 notebook 中用文字解释「为什么选线性/多项式」,这是作业的评分重点之一。
- 精度演示:用测试集评估并展示量化指标。
- 失败归因:若精度不理想,必须分析原因(例如数据本身非线性、缺失值、特征不足、相关性过低等)。
评分标准与达标路径
作业自带 Rubric 评分表:
| 标准 | 优秀(Exemplary) | 合格(Adequate) | 需改进(Needs Improvement) |
|---|---|---|---|
| 总体要求 | 提交一个完整、文档记录良好的解决方案 notebook | 解决方案不完整 | 解决方案存在错误或缺陷 |
| Criteria | Exemplary | Adequate | Needs Improvement |
|---|---|---|---|
| presents a complete notebook with a well-documented solution | the solution is incomplete | the solution is flawed or buggy |
要拿到「优秀」档,notebook 必须同时具备:完整性(含数据探索、训练、评估全流程)与文档化(每个步骤有文字说明,尤其是技术选型理由)。建议在 notebook 中至少包含四个明确小节:数据准备 → 相关性分析 → 模型训练 → 精度评估与结论。
技术背景:为什么先看相关性
课程 2-Regression/3-Linear/README.md 强调,线性回归的目标是拟合一条直线,达到两个目的:展示变量关系与对新数据点做预测。其数学基础是最小二乘法(Least-Squares Regression)——对每个数据点测量实际值与回归线之间的垂直距离(残差),将其平方后求和,再寻找使该总和最小的那条"最佳拟合线":
- 量级优先于方向:平方使 -5 与 +5 的误差同权处理,全部转正;
- 惩罚离群点:平方赋予大误差更大权重,迫使直线更贴近远离主体的点。
拟合直线可表示为Y = a + bX,其中X是解释变量,Y是因变量,b是斜率,a是截距(即X = 0时Y的值)。对应本课南瓜数据问题「按月预测每蒲式耳南瓜价格」,X为价格、Y为销售月份。
相关系数(Correlation Coefficient)是判断线性回归是否可行的第一道关口:散点呈整齐直线排布则相关性高,杂乱分布则相关性低。好的线性回归模型应当具有接近 1(而非 0)的相关系数。作业中选择数据集时,建议先对目标特征做corr()检查——若相关系数接近 0,直接解释"数据缺乏线性关系,因此线性回归不适用",这本身就是合格的失败归因。
数据准备:以南瓜数据集为例
课程使用美国南瓜批发数据集 2-Regression/data/US-pumpkins.csv。完整的数据清洗代码在课程 notebook 2-Regression/3-Linear/notebook.ipynb 中,参考答案见 solution/notebook.ipynb。核心步骤:
- 只保留以蒲式耳计价的记录(
Package列包含bushel); - 保留关键列(Package、Variety、City Name、Month、Low Price、High Price、Date);
- 价格取高低价均值:
price = (Low Price + High Price) / 2; - 按包装规格折算为每蒲式耳价格:
1 1/9蒲式耳纸箱除以 1.1,1/2蒲式耳乘以 2; - 计算
DayOfYear(自年初的天数):
day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)清洗后得到类似new_pumpkins的结构(字段:Month、DayOfYear、Variety、City、Package、Low Price、High Price、Price)。作业中若使用 Scikit-learn 内置数据集(如load_diabetes()),则可跳过这步,但仍建议在 notebook 中先describe()、检查缺失值。
相关性分析:作业的第一步论证
课程在 README.md 中演示了相关性检查(结果与 solution notebook 实测一致):
print(new_pumpkins['Month'].corr(new_pumpkins['Price'])) # ≈ -0.15 print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price'])) # ≈ -0.17相关性很小,但按品种着色绘制散点后可以发现价格存在多个簇——品种对价格的影响比日期更大。只关注PIE TYPE品种时,DayOfYear与Price的相关系数为-0.27(见 solution/notebook.ipynb),此时训练预测模型才有意义。
对作业的启示:如果自选数据集的相关系数同样很低,就可以在 notebook 中记录这一发现,并据此论证为什么可能需要多项式回归或更多特征,这正是「解释技术选型」的素材。
另外,线性回归对缺失值敏感,训练前必须清理空值:
pie_pumpkins.dropna(inplace=True)另一种做法是用列均值填充空值。
实现一:简单线性回归
训练模型使用Scikit-learn,核心代码(与课程和 solution notebook 一致):
from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1, 1) y = pie_pumpkins['Price'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) lin_reg = LinearRegression() lin_reg.fit(X_train, y_train)要点说明:
reshape(-1, 1):LinearRegression 要求二维输入,每一行对应一个特征向量;单特征场景需要 N×1 形状的数组。train_test_split(..., test_size=0.2, random_state=0):20% 数据留作测试集,random_state=0保证可复现(作业建议固定随机种子,这也是"文档化"的一部分)。- 拟合后通过
.coef_读取系数(本案例约-0.017,即价格每天约降 2 美分),通过.intercept_读取截距(约21,即年初价格)。 - 用测试集预测并计算RMSE(均方根误差):
import numpy as np pred = lin_reg.predict(X_test) rmse = np.sqrt(mean_squared_error(y_test, pred)) print(f'RMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%)')- 决定系数(coefficient of determination,即 R²)用
score获取:
score = lin_reg.score(X_train, y_train) print('Model determination: ', score)R² 为 0 表示模型退化为"最差线性预测器"(直接输出均值);为 1 表示完美预测。本案例 R² ≈ 0.06~0.07,非常低——这就是作业要求的"如果不精确,请解释原因"的典型场景:仅凭日期一个特征无法解释价格波动。
实现二:多项式回归
当变量间关系并非直线(例如价格在一年内呈抛物线波动、存在最低点)时,可引入多项式回归。Scikit-learn 提供了Pipeline API(sklearn.pipeline.make_pipeline)把数据处理步骤串联成 estimator 链:
from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import make_pipeline pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression()) pipeline.fit(X_train, y_train)PolynomialFeatures(2)表示加入输入数据的全部二次多项式项:单特征时是DayOfYear²;若有两个输入变量 X、Y,则会生成 X²、XY、Y²。如需更高阶曲线可增大阶数(如 3),但需注意过拟合风险。Pipeline 的用法与LinearRegression完全一致,可fit、predict、score:
pred = pipeline.predict(X_test) rmse = np.sqrt(mean_squared_error(y_test, pred)) print(f'RMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%)') score = pipeline.score(X_train, y_train) print('Model determination: ', score)绘制平滑拟合曲线时,应使用np.linspace生成均匀的输入值序列(直接在乱序测试集上连线会得到锯齿线):
X_range = np.linspace(X_test.min(), X_test.max(), 100).reshape(-1, 1) y_range = pipeline.predict(X_range) plt.scatter(X_test, y_test) plt.plot(X_range, y_range)课程实测:单特征多项式回归的 RMSE 与 R² 相比线性回归仅有微弱提升(RMSE 2.73 vs 2.77,R² 0.08 vs 0.07),说明仅靠日期特征不够,必须引入更多特征。这个"试了多项式但提升有限"的结论本身就是作业里极佳的论证材料。
实现三:引入分类特征(One-Hot 编码)
Variety等列是非数值的分类特征(categorical)。线性回归无法直接使用文本值,需要编码,有两种思路:
- 简单数值编码:给品种编号后用编号作为数值输入。这对线性回归并不合适——回归会按编号的实际数值乘以系数加进结果,而编号与价格的映射通常非线性。
- One-Hot 编码:把
Variety拆成多个 0/1 列,每列对应一个品种。这样线性回归会为每个品种学习一个独立的"附加价格"系数。
使用 Pandas 的get_dummies即可:
pd.get_dummies(new_pumpkins['Variety'])X = pd.get_dummies(new_pumpkins['Variety']) y = new_pumpkins['Price']课程进一步演示了把分类特征与数值特征拼接成完整特征矩阵:
X = pd.get_dummies(new_pumpkins['Variety']) \ .join(new_pumpkins['Month']) \ .join(pd.get_dummies(new_pumpkins['City'])) \ .join(pd.get_dummies(new_pumpkins['Package'])) y = new_pumpkins['Price']加入City与Package后,RMSE 降至 2.84(10.5%),R² 提升到 0.94。这是作业中"提升模型精度"的最有效手段,也是应当写进 notebook 的关键步骤。
综合对照:五类模型的结果对比
课程在 README.md 汇总了本课构建的所有模型(数值与 solution notebook 实测一致):
| 模型 | RMSE | 决定系数(R²) |
|---|---|---|
DayOfYear线性 | 2.77(17.2%) | 0.07 |
DayOfYear多项式 | 2.73(17.0%) | 0.08 |
Variety线性 | 5.24(19.7%) | 0.77 |
| 全部特征线性 | 2.84(10.5%) | 0.94 |
| 全部特征多项式 | 2.23(8.25%) | 0.97 |
完整版"全部特征 + 多项式"代码(可直接复用于作业):
# 准备训练数据 X = pd.get_dummies(new_pumpkins['Variety']) \ .join(new_pumpkins['Month']) \ .join(pd.get_dummies(new_pumpkins['City'])) \ .join(pd.get_dummies(new_pumpkins['Package'])) y = new_pumpkins['Price'] # 划分训练/测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) # 构建并训练 Pipeline pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression()) pipeline.fit(X_train, y_train) # 预测 pred = pipeline.predict(X_test) # 评估 rmse = mean_squared_error(y_test, pred, squared=False) print(f'RMSE: {rmse:3.3} ({rmse/pred.mean()*100:3.3}%)') score = pipeline.score(X_train, y_train) print('Model determination: ', score)最终模型的 R² 接近 0.97、RMSE ≈ 2.23(约 8% 预测误差),是本课能达到的最佳结果。作业中建议至少完成一个「简单线性回归 → 多项式/更多特征 → 评估对比」的完整闭环,并记录每一步的 RMSE 与 R²,与上面的基准值形成对照。
作业自查清单
对照 Rubric「优秀」档逐项自查:
- notebook 完整:包含数据加载(自选数据或
sklearn.datasets内置集)、数据探索、训练、评估全过程;每个代码单元有 Markdown 文字说明。 - 技术选型有理由:明确写出"为什么用线性/多项式回归"——例如"相关性分析显示
corr ≈ -0.27,存在一定线性关系,故先尝试简单线性回归";若 R² 低,说明"单特征线性关系弱,改用多项式/引入更多特征"。 - 精度演示:输出 RMSE(含百分比)与 R² 两个指标,并附测试集散点与回归线的可视化图(线性结果可参考 2-Regression/3-Linear/images/linear-results.png,多项式结果可参考 2-Regression/3-Linear/images/poly-results.png)。
- 失败归因:若模型不精确,分析原因(相关性过低、特征不足、数据缺失、非线性关系、过拟合等)并写在 notebook 结论区。
延伸学习:课程 README.md 还建议在学完本课后进一步了解 Stepwise、Ridge、Lasso 与 Elasticnet 等回归技术;本课的 R 语言版本见 solution/R/lesson_3-R.ipynb,可作对比参考。完成本作业后,你将在回归章节的最后一部分接触逻辑回归(Logistic Regression),用于类别预测。
【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考