1. 初识mpg数据集汽车油耗预测的经典案例第一次接触mpg数据集是在五年前的一个燃油效率优化项目上。这个包含398辆汽车信息的经典数据集就像一本汽车行业的营养标签记录了每加仑汽油能跑多少英里miles per gallon这个核心指标以及影响油耗的8个关键特征。这个数据集最吸引我的地方在于它的真实性和完整性。数据来自1983年美国统计协会博览会经过卡内基梅隆大学StatLib库的整理包含了从欧洲、日本到美国不同产地的车型。记得当时为了验证数据质量我特意找了辆老款丰田卡罗拉实测油耗结果与数据集中的记录误差不到5%。对于刚入门数据分析的朋友mpg数据集有三大优势特征丰富包含气缸数、排量、马力等工程参数也有出厂年份、产地等背景信息问题典型油耗预测是回归分析的经典场景结果容易验证规模适中398条记录足够训练模型又不会让新手望而生畏提示数据集中的horsepower字段有6个缺失值这是后续特征工程需要处理的第一个坑2. 数据探索用Python打开汽车数据黑箱2.1 数据加载与初窥我习惯用pandas的read_csv直接加载数据这个数据集在seaborn库中有现成的副本import seaborn as sns df sns.load_dataset(mpg) print(df.head(3))输出结果会显示前三条记录包含mpg、cylinders等字段。第一次运行时我犯了个错误——没检查数据类型后来发现horsepower字段里混进了字符串?表示缺失值。正确的做法是df[horsepower] pd.to_numeric(df[horsepower], errorscoerce)2.2 可视化探索的四个必看视角分布直方图用seaborn的displot看mpg分布会发现呈现右偏态这与现实中多数车集中在中等油耗区间吻合散点矩阵pairplot显示weight与mpg的负相关性最明显这也符合车越重越费油的常识箱线图比较不同产地(origin)的mpg差异日本车的中位数明显更高热力图corr()计算相关系数displacement与weight的相关系数高达0.93存在多重共线性问题# 典型可视化代码示例 sns.jointplot(xweight, ympg, datadf, kindreg) plt.show()3. 特征工程从原始数据到模型食材3.1 数据清洗的实战经验处理horsepower缺失值时我对比过三种方案直接删除缺失记录损失6条数据用均值填充会扭曲分布按cylinders分组插值最终选择具体操作是用每组气缸数对应的马力中位数来填充df[horsepower] df.groupby(cylinders)[horsepower].transform( lambda x: x.fillna(x.median()))3.2 特征创造的三个技巧年代分段将model_year转为车龄相对1982年发现车龄与mpg呈正相关功率重量比新增horsepower/weight字段这个衍生特征最终在模型中重要性排名前三产地编码对origin进行one-hot编码时注意要drop_first避免虚拟变量陷阱# 创建新特征示例 df[power_to_weight] df[horsepower] / df[weight] df[vehicle_age] 82 - df[model_year]4. 模型实战从线性回归到随机森林4.1 基础模型对比测试在划分训练集/测试集7:3比例后我通常会跑三个baseline模型线性回归R2约0.82但残差图呈现喇叭形违背同方差假设决策树max_depth5时测试集R2达0.85明显捕捉到非线性关系随机森林n_estimators200时R2冲到0.89但存在轻微过拟合from sklearn.ensemble import RandomForestRegressor rf RandomForestRegressor(n_estimators200, max_depth7) rf.fit(X_train, y_train) print(rf.score(X_test, y_test))4.2 模型解释的实用方法用SHAP值分析随机森林模型时发现三个有趣现象weight特征贡献度最大但与mpg的关系呈非线性下降曲线日本产地的正向影响超过其他所有产地之和当功率重量比超过0.06时对油耗的负面影响开始加剧import shap explainer shap.TreeExplainer(rf) shap_values explainer.shap_values(X_test) shap.summary_plot(shap_values, X_test)5. 项目复盘那些只有实战才知道的坑第一次用这个数据集时我忽略了model_year字段的特殊性——它本质上是分类变量而非连续值。直接当作数值特征输入模型导致1982年的车与1970年的车被认为相差12个单位实际上这两个年份的技术代差远大于数值差。另一个教训是关于特征缩放。起初我没对displacement做标准化处理导致Lasso回归的系数解释完全失真。后来改用RobustScaler处理离群值后模型稳定性显著提升。在部署预测服务时发现用户常输入当前年份计算车龄。这就需要将代码中的基准年从固定的1982改为动态计算# 动态计算车龄 current_year datetime.now().year df[vehicle_age] current_year - df[model_year]这个项目让我深刻体会到即使像mpg这样的玩具数据集要做出工业级应用也需要处理无数细节。最近用同样流程分析新能源车电耗数据时发现很多经验仍然适用但需要增加充电效率、电池衰减等新特征维度。