ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ML-For-Beginners 实战:用 Scikit-learn 构建南瓜价格回归模型——线性回归、多项式回归与类别特征编码

ML-For-Beginners 实战:用 Scikit-learn 构建南瓜价格回归模型——线性回归、多项式回归与类别特征编码 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 课程第 3 课translations/el/2-Regression/3-Linear/README.md 的英文母本为 2-Regression/3-Linear/README.md展开以美国南瓜批发价数据集为主线系统讲解最小二乘线性回归、多项式回归、类别特征 One-Hot 编码三大核心知识点并最终用同一套特征组合出四种回归模型横向对比。读完本文你将掌握从数据清洗、相关性探查到 Scikit-learn 建模评估的完整链路能够独立复现用DayOfYear、Variety、City、Package预测每蒲式耳南瓜价格的实战项目。线性拟合是一条直线多项式拟合是一条曲线两者都能逼近数据但适用关系不同。背景南瓜价格数据集与课程上下文本课使用的数据来自 2-Regression/data/US-pumpkins.csv记录了美国多个城市的南瓜批发价格、品种Variety、城市City、包装规格Package、日期Date等 26 列原始字段。上一课2-Regression/2-Data/README.md已经完成了初步清洗只保留按蒲式耳bushel计价的记录、以最高价与最低价的均值作为价格、并把价格统一换算到每蒲式耳。在 2-Regression/3-Linear/notebook.ipynb 中可以看到完整的清洗实现import pandas as pd import matplotlib.pyplot as plt import numpy as np from datetime import datetime pumpkins pd.read_csv(../data/US-pumpkins.csv) # 只保留按蒲式耳计价的记录 pumpkins pumpkins[pumpkins[Package].str.contains(bushel, caseTrue, regexTrue)] columns_to_select [Package, Variety, City Name, Low Price, High Price, Date] pumpkins pumpkins.loc[:, columns_to_select] # 以最高价与最低价的均值作为价格 price (pumpkins[Low Price] pumpkins[High Price]) / 2 month pd.DatetimeIndex(pumpkins[Date]).month # 计算一年中的第几天 day_of_year pd.to_datetime(pumpkins[Date]).apply(lambda dt: (dt-datetime(dt.year,1,1)).days) new_pumpkins pd.DataFrame( {Month: month, DayOfYear : day_of_year, Variety: pumpkins[Variety], City: pumpkins[City Name], Package: pumpkins[Package], Low Price: pumpkins[Low Price], High Price: pumpkins[High Price], Price: price}) # 包装规格换算1 1/9 蒲式耳箱 → 除以 1.11/2 蒲式耳篮 → 乘以 2 new_pumpkins.loc[new_pumpkins[Package].str.contains(1 1/9), Price] price/1.1 new_pumpkins.loc[new_pumpkins[Package].str.contains(1/2), Price] price*2 new_pumpkins.head()清洗后得到的数据帧new_pumpkins形如下表完整运行结果可参考 2-Regression/3-Linear/solution/notebook.ipynbIDMonthDayOfYearVarietyCityPackageLow PriceHigh PricePrice709267PIE TYPEBALTIMORE1 1/9 bushel cartons15.015.013.636364719267PIE TYPEBALTIMORE1 1/9 bushel cartons18.018.016.3636367210274PIE TYPEBALTIMORE1 1/9 bushel cartons18.018.016.3636367310274PIE TYPEBALTIMORE1 1/9 bushel cartons17.017.015.4545457410281PIE TYPEBALTIMORE1 1/9 bushel cartons15.015.013.636364注意由于原始数据只覆盖 8 月到 12 月这个数据帧只有约 415 条记录见 solution notebook 中 One-Hot 编码表格输出显示的415 rows且全部来自秋季月份。课程希望借此提出三个真实商业问题什么时候买南瓜最划算一箱迷你南瓜大概什么价买半蒲式耳篮还是 1 1/9 蒲式耳箱最小二乘线性回归拟合一条最佳直线线性回归用于预测数值型目标房价、温度、销量等。它的目标是在散点图中画一条直线使其同时做到两点展示变量关系直观呈现输入特征与输出之间的关联方向与强度做出预测对落在直线附近的新数据点给出尽可能准确的估计。残差与平方的动机最小二乘Least-Squares这个名字源自它的拟合过程对每个数据点测量该点与回归线的垂直距离称为残差 residual然后把所有残差平方后求和找到使该总和最小的那条线。为什么要平方残差课程给出了两个关键原因重大小、轻方向我们希望误差 -5 与误差 5 被同等对待平方后所有值都变为正数惩罚离群点平方会给较大的误差更大权重迫使直线更贴近偏离较远的点。直线方程Y a bX这条最佳拟合线用一元线性方程表达Y a bX其中X是解释变量输入特征Y是因变量输出目标b是斜率slopea是 y 轴截距intercept即X 0时的Y值。对应到南瓜数据集的原问题——按月预测每蒲式耳南瓜价格——X是月份或一年中的第几天Y是价格。若把特征换成DayOfYear那么斜率b表示每过一天价格变化多少截距a表示年初第 0 天的价格起点。从 2-Regression/3-Linear/solution/notebook.ipynb 的实际训练结果看DayOfYear线性模型的系数为array([-0.01751876])、截距约为21.13说明价格随时间缓慢下降约每天降 2 美分年初理论价格约 21 美元。这正是斜率 截距两个参数对业务的可解释表达。相关性分析先看再练建模之前先用**相关系数Correlation Coefficient**评估特征与目标的关系强度。散点图是快速目测相关性的工具数据点沿一条整齐的线分布表示高相关在 X、Y 之间均匀散开表示低相关。好的线性回归模型通常对应接近 1而非接近 0的相关系数。运行本课配套 notebook2-Regression/3-Linear/notebook.ipynb中的散点图观察Month与Price、DayOfYear与Price的关系然后量化计算print(new_pumpkins[Month].corr(new_pumpkins[Price])) print(new_pumpkins[DayOfYear].corr(new_pumpkins[Price]))输出见 solution notebook约为-0.14878293554077535 -0.16673322492745407即Month约 -0.15、DayOfYear约 -0.17相关性很弱。但散点图中可以看到价格存在多个明显的价格簇——这提示真正起作用的可能是品种等其他因素。为了验证把不同品种用不同颜色画在同一张图上借助scatter的ax参数叠加所有品种axNone colors [red,blue,green,yellow] for i,var in enumerate(new_pumpkins[Variety].unique()): df new_pumpkins[new_pumpkins[Variety]var] ax df.plot.scatter(DayOfYear,Price,axax,ccolors[i],labelvar)不同品种用不同颜色标出后价格簇与品种一一对应的规律立刻显现。再用分组柱状图观察各品种的平均价格new_pumpkins.groupby(Variety)[Price].mean().plot(kindbar)结论很明确品种Variety对价格的影响远大于销售日期。接下来把注意力收窄到 PIE TYPE馅饼南瓜这一个品种单独看日期对价格的影响pie_pumpkins new_pumpkins[new_pumpkins[Variety]PIE TYPE] pie_pumpkins.plot.scatter(DayOfYear,Price)此时计算Price与DayOfYear的相关系数约为-0.27solution notebook 中实际输出-0.2669192282197318相关性虽仍不高但已经足以让训练预测模型变得有意义。建模前的数据卫生线性回归对缺失值敏感因此在训练前应清除空单元格pie_pumpkins.dropna(inplaceTrue) pie_pumpkins.info()另一种替代策略是用对应列的均值填充缺失值两种做法都可接受。简单线性回归用 Scikit-learn 训练第一个模型本课训练模型统一使用Scikit-learn。先导入所需组件from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split准备输入reshape 成二维数组把特征与标签拆成独立的 numpy 数组。这里有个容易踩的坑LinearRegression要求输入是二维数组每行对应一个特征向量当前只有一个特征因此需要把一维数组 reshape 成 N×1 形状X pie_pumpkins[DayOfYear].to_numpy().reshape(-1,1) y pie_pumpkins[Price]划分训练集与测试集为了在训练后验证模型用 20% 的数据做测试X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state0)训练与参数解读训练本体只有两行代码定义LinearRegression对象再用fit拟合lin_reg LinearRegression() lin_reg.fit(X_train,y_train)fit之后回归系数保存在.coef_属性中。本案例只有一个系数约为-0.017含义是价格随时间略有下降但幅度不大每天约 2 美分。y 轴截距通过.intercept_获取约为21表示年初的价格起点。评估RMSE 与决定系数用测试集预测并计算均方根误差RMSE——期望值与预测值之差的平方均值的开方pred lin_reg.predict(X_test) rmse np.sqrt(mean_squared_error(y_test,pred)) print(fRMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%))误差约为 2 个单位即 ~17%并不理想。另一个质量指标是决定系数coefficient of determination即score方法返回的 R²score lin_reg.score(X_train,y_train) print(Model determination: , score)R² 的语义等于 0 表示模型没有利用输入数据、退化为最差的线性预测器即直接输出均值等于 1 表示完美预测。本案例 R² 约为 0.06非常低说明单靠DayOfYear无法解释价格波动。把测试数据与回归直线画在一起可以直观看到拟合效果plt.scatter(X_test,y_test) plt.plot(X_test,pred)图中散点是真实测试样本直线是学到的Price ≈ 21 - 0.0175 × DayOfYear。斜率平缓、离散度大正对应低 R²。训练好的模型可以直接用于业务预测例如估算程序员日一年中第 256 天的南瓜价格lin_reg.predict([[256]])solution notebook 中该调用的输出约为array([16.64893156])即约 16.65 美元/蒲式耳。多项式回归用 Pipeline 拟合曲线并非所有变量关系都是线性的——南瓜越大、价格越高这类关系还可以是曲面或曲线而日期与价格的关系也可能先降后升例如冬季价高、夏季价低、秋季再涨。此时可以尝试多项式回归给输入特征添加平方项、交叉项等多项式特征让模型用曲线去贴合非线性数据。在本案例中若在输入中加入DayOfYear²就能用一条抛物线拟合数据其最低点对应一年中价格最低的时点。Pipeline把特征工程 回归串成链Scikit-learn 提供 Pipeline APImake_pipeline可以把多个**估计器estimator**按顺序组合成一个整体。下面的 pipeline 先通过PolynomialFeatures(2)生成二阶多项式特征再送入LinearRegression训练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时等价于添加DayOfYear²若有 X、Y 两个输入变量则会生成 X²、XY、Y²。需要时也可以指定更高阶数。Pipeline 的用法与原始LinearRegression完全一致——先fit再predictpred pipeline.predict(X_test) rmse np.sqrt(mean_squared_error(y_test,pred)) print(fRMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%)) score pipeline.score(X_train,y_train) print(Model determination: , score)solution notebook 中该段输出为Mean error: 2.73 (17.0%)、Model determination: 0.0764相比线性模型只有轻微改善。绘制平滑曲线如果直接对未排序的测试数据连线会得到锯齿状折线。要画光滑的近似曲线用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)抛物线的最低点大致落在万圣节Halloween前后与秋季南瓜供应充足、价格走低的市场现象吻合可以作为数据洞察的延伸讨论点。总体而言仅用日期做多项式回归RMSE 与 R² 提升有限——必须纳入其他特征。类别特征从 Variety 到 One-Hot 编码理想情况下我们希望用同一个模型预测所有品种的价格。但Variety列存放的是非数值的品种名如PIE TYPE、MINIATURE这类列称为类别特征categorical features。线性回归只能吃数值因此必须先编码encode。两种常见编码方式对比数值编码numeric encoding为每个品种分配一个索引号0、1、2、3…。对线性回归而言这不是好主意——模型会把索引当作真实数值乘上系数加到结果里而索引与价格之间显然不是线性关系One-Hot 编码把Variety一列拆成 4 个 0/1 列每列对应一个品种行属于该品种时为 1、否则为 0。这样线性回归会得到 4 个系数分别代表每种南瓜的起始价附加价。Pandas 一行即可完成 One-Hot 编码pd.get_dummies(new_pumpkins[Variety])得到如下结构的矩阵IDFAIRYTALEMINIATUREMIXED HEIRLOOM VARIETIESPIE TYPE700001710001...............1738010017390100174001001741010017420100把 One-Hot 后的品种矩阵作为特征输入X pd.get_dummies(new_pumpkins[Variety]) y new_pumpkins[Price]训练代码与前面完全相同。solution notebook 把拆分-训练-评估封装成了可复用函数run_linear_regression(X, y)def run_linear_regression(X,y): X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state0) lin_reg LinearRegression() lin_reg.fit(X_train,y_train) pred lin_reg.predict(X_test) mse np.sqrt(mean_squared_error(y_test,pred)) print(fMean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)) score lin_reg.score(X_train,y_train) print(Model determination: , score)运行结果Mean error: 5.24 (19.7%)、Model determination: 0.7741——RMSE 与线性模型相当但R² 从 0.06 跃升到约 77%印证了品种主导价格的判断。要进一步提升精度可以把更多类别特征City、Package与数值特征Month通过join拼成一张大特征表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]此时线性模型达到Mean error: 2.84 (10.5%)、Model determination: 0.9401——R² 提升到 94%。集成全部特征 多项式回归既然类别特征 数值特征已经拿到 94% 的 R²再用多项式回归处理特征间的非线性交互理论上可以更上一层楼。完整代码如下# 设置训练数据 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_size0.2, random_state0) # 搭建并训练 pipeline pipeline make_pipeline(PolynomialFeatures(2), LinearRegression()) pipeline.fit(X_train,y_train) # 在测试集上预测 pred pipeline.predict(X_test) # 计算 RMSE 与决定系数 rmse mean_squared_error(y_test, pred, squaredFalse) print(fRMSE: {rmse:3.3} ({rmse/pred.mean()*100:3.3}%)) score pipeline.score(X_train,y_train) print(Model determination: , score)运行结果solution notebookMean error: 2.23 (8.25%)、Model determination: 0.9653即R² 接近 97%、RMSE 2.23约 8% 的预测误差——这就是本课回归的四种方式能达到的最佳成绩。四种模型横向对比模型RMSE决定系数R²DayOfYear线性2.77 (17.2%)0.07DayOfYear多项式2.73 (17.0%)0.08Variety线性One-Hot5.24 (19.7%)0.77全部特征 线性2.84 (10.5%)0.94全部特征 多项式2.23 (8.25%)0.97对比表给出了非常清晰的建模直觉单一数值特征日期无论线性还是多项式解释力都很弱R² 0.1仅用品种 One-Hot 编码R² 即跃升至 77%说明品种是价格的最主要驱动因子叠加城市、包装、月份后线性模型达到 94%最后用二阶多项式处理特征交互把 R² 推到 97% 附近RMSE 降至 2.23约 8%。延伸练习与挑战本课配套的练习 2-Regression/3-Linear/assignment.md 建议基于本课学到的线性/多项式回归知识自行找一份数据集或使用 Scikit-learn 内置数据集构建全新模型在 notebook 中说明技术选型理由、展示模型精度若精度不佳则分析原因。值得继续深挖的方向挑战任务在本课 notebook2-Regression/3-Linear/notebook.ipynb中尝试更换不同特征观察相关系数与模型精度的联动关系也可以参考完整带输出的 2-Regression/3-Linear/solution/notebook.ipynb 核对每一步结果R 语言版本同一课程提供了 R 实现2-Regression/3-Linear/solution/R/lesson_3.html适合习惯 R 生态tidyverse/recipes/parsnip的读者对照学习更广的回归谱系本课聚焦线性与多项式回归课程还提示可进一步研读 Stepwise、Ridge、Lasso、Elasticnet 等正则化与变量选择技术它们解决高维特征下的过拟合与共线性问题是全部特征 多项式方案在生产环境中的自然演进。至此你已经在一课之内用同一份南瓜数据构建了四种回归模型并把决定系数从 0.06 提升到 97%。下一课将进入回归家族的最后一块拼图——用于分类判定的逻辑回归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),仅供参考
返回列表