XGBoost回归预测实战:Python代码实现与散点图折线图可视化
简介这份资源面向具备一定机器学习基础的Python开发者与数据科学学习者提供一套基于XGBoost的回归预测完整实现方案用于解决房价类连续值预测的建模与结果展示问题。压缩包共5个文件约191KB包含2个xlsx格式的训练与测试数据集、1个py主程序脚本、1个png结果示意图以及1个md说明文档覆盖数据加载、模型训练、评估与可视化全流程。运行脚本后可分别得到训练集与测试集真实值对预测值的散点图以及测试集逐样本真实值与预测值的折线图并输出均方根误差RMSE作为量化评估指标。目前已有4295人学习下载适合希望快速掌握XGBoost回归建模、结果可视化与误差分析的中级学习者参考也可作为课程实验或项目原型的起点。1. 从一份能直接跑通的 XGBoost 回归代码说起很多做数据回归预测的朋友都有过这种经历算法原理看了一堆公式推导也能说上几句真到要交一份能跑、能出图、能解释结果的代码时却卡在数据加载、参数设置和可视化上。这份基于 XGBoost 的数据回归预测 Python 代码就是冲着这个痛点来的。它用波士顿房价数据集做演示从 Excel 文件读取训练和测试数据训练 XGBoost 回归模型在测试集上评估并生成散点图和折线图来对比真实值与预测值。整个包里有xgboost_regression.py主脚本、训练和测试两个 Excel 数据文件、一份 README 说明以及一张示例输出图。适合刚接触 XGBoost 回归、需要快速搭出可复现流程的从业者也适合想拿一份干净模板改造成自己业务数据回归任务的人。下面我按实际拆包和跑通的顺序把这份资源讲透。2. 拆开压缩包文件构成与运行环境准备2.1 包内文件清单与各自作用拿到基于XGBoost的数据回归预测Python代码 包含散点图和折线图可视化.zip之后先别急着解压运行。我一般会先看一眼目录结构确认数据文件和脚本的对应关系。这个包的结构很扁平没有多余的层级文件/目录类型作用xgboost_regression.pyPython 脚本主程序负责数据加载、模型训练、预测、评估和绘图boston_housing_train_data.xlsxExcel 数据训练集包含特征列和目标房价列boston_housing_test_data.xlsxExcel 数据测试集用于评估模型泛化能力README.md文档运行说明和依赖提示Figure_1.png图片示例输出方便对照自己跑出来的图这种扁平结构的好处是路径简单脚本里读写 Excel 基本就是同目录相对路径不容易出现“文件找不到”的低级错误。但也要注意如果你把脚本单独拷到别的目录跑Excel 文件没跟着走就会直接报FileNotFoundError。常见做法是把整个文件夹一起移动或者改脚本里的路径变量。2.2 Python 环境与依赖库安装这份代码依赖的库不算多但版本上有点讲究。核心是xgboost、pandas、scikit-learn、matplotlib和openpyxl。其中openpyxl是 pandas 读写.xlsx文件的引擎很多人装完 pandas 以为就能读 Excel结果一跑就报Missing optional dependency openpyxl这就是典型的漏装。我一般会先建一个干净的虚拟环境避免和系统里已有的包版本打架# 创建虚拟环境Python 3.8 及以上都行 python -m venv xgb_env # 激活环境Windows 用下面这行 xgb_env\Scripts\activate # macOS/Linux 用这行 source xgb_env/bin/activate # 一次性安装依赖openpyxl 别漏 pip install xgboost pandas scikit-learn matplotlib openpyxl这里有几个参数和选择理由值得说清楚。xgboost从 1.6 版本之后 API 相对稳定XGBRegressor的用法变化不大所以不用刻意锁死某个小版本。scikit-learn主要用来算 RMSE 和做数据划分的辅助虽然这份代码可能已经提前分好了训练测试集但评估指标还是靠它。matplotlib负责画散点图和折线图默认后端在无图形界面的服务器上可能报错如果你是在 Linux 服务器上跑可以加一句matplotlib.use(Agg)再导入pyplot这样只存图不弹窗。提示如果你用的是 Anaconda可以用conda install xgboost pandas scikit-learn matplotlib openpyxl但 conda 源里 xgboost 的版本有时偏旧遇到 API 不兼容时优先用 pip 装。装完之后建议做个最小验证确认 xgboost 能正常导入import xgboost as xgb import pandas as pd import sklearn import matplotlib print(xgb.__version__) print(pd.__version__)如果这一步就报错后面不用看了先把环境问题解决。版本号不用和示例完全一致但 xgboost 建议不低于 1.5pandas 不低于 1.3否则某些参数名会有差异。3. 跑通主脚本数据加载、模型训练与预测全流程3.1 数据加载与训练测试集划分逻辑这份代码的数据是从 Excel 直接读的训练集和测试集已经分成两个文件。这种做法的好处是数据划分固定每次跑结果可复现不会因为随机种子不同导致评估指标跳动。但也要注意如果这两个文件本身是从同一批数据里随机切出来的那没问题如果是按时间或其他规则切的就要留意分布是否一致。脚本里加载数据的部分通常长这样import pandas as pd # 读取训练集和测试集注意文件路径要和脚本同目录 train_data pd.read_excel(boston_housing_train_data.xlsx) test_data pd.read_excel(boston_housing_test_data.xlsx) # 假设目标列名是 MEDV特征列是其余所有列 target_col MEDV X_train train_data.drop(columns[target_col]) y_train train_data[target_col] X_test test_data.drop(columns[target_col]) y_test test_data[target_col] print(训练集形状:, X_train.shape) print(测试集形状:, X_test.shape)这里的关键参数是target_col也就是目标列的名字。波士顿房价数据集里目标列通常叫MEDV但如果你换成自己的数据这一列的名字必须改对否则drop会报KeyError。另外read_excel默认读第一个 sheet如果你的 Excel 有多个 sheet要加sheet_name参数指定。我见过有人把数据放在第二个 sheet结果读出来是空的排查半天才发现是 sheet 的问题。还有一个容易忽略的点Excel 里的列名如果有空格或特殊字符pandas 读进来会原样保留后面按列名索引时就会对不上。建议读完先print(train_data.columns.tolist())看一眼实际列名确认和目标列名一致。3.2 XGBoost 回归模型训练与关键参数设置数据准备好之后就是核心的模型训练。这份代码用的是XGBRegressor属于 xgboost 的 sklearn 风格接口对熟悉 scikit-learn 的人来说上手很快。基础训练代码大概是这样from xgboost import XGBRegressor # 初始化回归器这里给一组常用参数 model XGBRegressor( n_estimators100, # 树的数量太少欠拟合太多容易过拟合 learning_rate0.1, # 学习率控制每棵树对最终结果的贡献 max_depth6, # 树的最大深度越大模型越复杂 subsample0.8, # 每棵树随机采样的样本比例防过拟合 colsample_bytree0.8, # 每棵树随机采样的特征比例 random_state42 # 固定随机种子保证结果可复现 ) # 在训练集上拟合模型 model.fit(X_train, y_train) # 在测试集上预测 y_pred model.predict(X_test)这几个参数是 XGBoost 回归里最常调的。n_estimators和learning_rate是一对学习率低的时候树要多一些学习率高的时候树可以少一些但太高容易跳过最优解。max_depth控制单棵树的复杂度波士顿房价这种特征量不大的数据集深度 4 到 8 之间比较常见。subsample和colsample_bytree是防过拟合的随机采样比例一般设在 0.6 到 0.9 之间。random_state固定之后每次跑出来的 RMSE 基本一致方便对比不同参数的效果。如果你想让模型自己找参数可以用RandomizedSearchCV或GridSearchCV包一层但这份代码没带自动调参属于手动设置。对于刚跑通流程来说手动参数足够看到效果真要上生产还是得做一轮超参数搜索。3.3 预测结果评估RMSE 计算与输出解读模型跑完预测之后脚本会算一个 RMSE均方根误差。这是回归任务里最常用的指标之一单位跟目标变量一致解释起来直观。计算代码通常是这样from sklearn.metrics import mean_squared_error import numpy as np # 计算均方根误差 rmse np.sqrt(mean_squared_error(y_test, y_pred)) print(f测试集 RMSE: {rmse:.4f})RMSE 的数值本身没有绝对的好坏标准要看目标变量的量级。波士顿房价的目标值大概在 5 到 50 之间RMSE 如果在 3 到 5 左右说明模型大致抓住了主要趋势如果 RMSE 接近甚至超过目标值的标准差那模型基本没学到东西。我一般会顺手算一下目标变量的标准差做对比print(目标变量标准差:, y_test.std())如果 RMSE 明显小于标准差说明模型有预测能力如果两者差不多就要回头检查特征是否有效、数据是否有泄漏、参数是否合理。这一步很多人会跳过只看一个 RMSE 数字就下结论其实对照标准差才能判断模型到底有没有用。4. 可视化两张图散点图与折线图的实现细节4.1 训练集与测试集散点图真实值 vs 预测值散点图是回归任务里最直观的评估方式。横轴放真实值纵轴放预测值理想情况下所有点应该落在对角线附近。这份代码会分别画训练集和测试集的散点图方便对比模型在两部分数据上的表现。实现代码大概是这样import matplotlib.pyplot as plt # 设置中文字体避免中文乱码 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 训练集散点图 plt.figure(figsize(8, 6)) plt.scatter(y_train, model.predict(X_train), alpha0.6, edgecolorsk) plt.plot([y_train.min(), y_train.max()], [y_train.min(), y_train.max()], r--, lw2) plt.xlabel(真实值) plt.ylabel(预测值) plt.title(训练集真实值 vs 预测值) plt.tight_layout() plt.savefig(train_scatter.png, dpi150) plt.show()这里有几个细节值得注意。alpha0.6是透明度点重叠的时候能看出密度不然一片黑糊糊的。edgecolorsk给点加黑色边框图更清晰。红色虚线是对角参考线用来判断点偏离程度。dpi150控制保存图片的分辨率默认 100 在报告里可能偏糊。测试集散点图同理把y_train和X_train换成测试集变量即可。如果点大量偏离对角线尤其是测试集上偏离明显说明模型泛化能力不足可能是过拟合了。这时候可以回头看训练集和测试集的 RMSE 差距差距大就是过拟合的典型信号。4.2 测试集折线图逐样本对比与横坐标密集问题折线图展示的是测试集里每个样本的真实值和预测值随样本序号的变化。这种图适合看模型有没有系统性偏高或偏低也能看出在某些样本上预测偏差特别大。代码大概是这样# 测试集折线图按样本序号排列 plt.figure(figsize(12, 5)) plt.plot(range(len(y_test)), y_test.values, label真实值, markero, markersize3) plt.plot(range(len(y_test)), y_pred, label预测值, markerx, markersize3) plt.xlabel(样本序号) plt.ylabel(房价) plt.title(测试集真实值与预测值对比) plt.legend() plt.tight_layout() plt.savefig(test_line.png, dpi150) plt.show()这里最容易翻车的地方是横坐标太密集。如果测试集样本有几百个range(len(y_test))会把每个序号都标出来横轴挤成一团。常见做法是隔几个样本标一个刻度import matplotlib.ticker as ticker ax plt.gca() ax.xaxis.set_major_locator(ticker.MultipleLocator(20))MultipleLocator(20)表示每隔 20 个样本显示一个刻度具体间隔按样本总数调整。另外marker参数在样本多的时候会让图很乱可以去掉 marker 只保留线或者把 markersize 调小。注意y_test.values这里用.values是为了避免 pandas Series 的索引干扰折线图的横坐标对齐。如果直接用y_testmatplotlib 可能会按索引画而索引不一定是 0 到 n-1图就会错位。4.3 图表保存与中文显示避坑中文显示是 matplotlib 的老问题。默认字体不支持中文标题和轴标签会变成方框。上面代码里设置了SimHei这是 Windows 上常见的中文字体。如果你在 macOS 或 Linux 上跑SimHei可能不存在需要换成系统里有的字体比如Arial Unicode MS或WenQuanYi Micro Hei。更稳妥的做法是先查一下系统可用字体import matplotlib.font_manager as fm fonts [f.name for f in fm.fontManager.ttflist] print([f for f in fonts if Hei in f or Song in f or Arial in f])找到可用字体后替换plt.rcParams[font.sans-serif]里的值。另外axes.unicode_minus False是为了让负号正常显示不然负号也会变方框。这两个设置建议放在所有绘图代码之前避免中途改配置导致部分图生效部分不生效。保存图片时plt.savefig要放在plt.show()之前。因为show()之后画布可能被清空再保存就是空白图。这个顺序问题我见过不少人踩坑图能弹出来但保存的是空的排查半天才发现是顺序反了。5. 避坑与常见问题排查5.1 报错 FileNotFoundErrorExcel 文件路径不对现象是运行脚本直接抛FileNotFoundError: [Errno 2] No such file or directory: boston_housing_train_data.xlsx。原因通常是脚本的工作目录和 Excel 文件不在同一层比如你在上一级目录用python xgboost_regression/xgboost_regression.py运行工作目录是上一级相对路径就找不到了。解决办法有两个一是cd到脚本所在目录再运行二是把脚本里的路径改成绝对路径或基于__file__的动态路径import os base_dir os.path.dirname(os.path.abspath(__file__)) train_path os.path.join(base_dir, boston_housing_train_data.xlsx)这样不管从哪个目录运行都能定位到 Excel 文件。5.2 报错 KeyError目标列名对不上现象是KeyError: MEDV或类似列名找不到。原因是 Excel 里的实际列名和脚本里写的target_col不一致可能是大小写差异、多了空格或者你换了自己的数据但没改列名。解决办法是先打印列名确认print(train_data.columns.tolist())然后按实际列名修改target_col。如果列名里有空格可以用train_data.columns train_data.columns.str.strip()统一去掉首尾空格。5.3 RMSE 异常大或预测值全是一个数现象是 RMSE 大得离谱或者预测值几乎都相同。原因可能是目标列选错了把某个特征列当成了目标也可能是数据里混入了非数值列XGBoost 无法处理。解决办法是检查X_train.dtypes确保所有特征都是数值类型。如果有object类型的列要么做编码转换要么直接剔除。另外确认y_train的数值范围是否合理如果全是 0 或异常值模型学不到东西。5.4 中文乱码或负号显示为方框现象是图上的中文标题和轴标签变成方框负号也显示异常。原因是 matplotlib 默认字体不支持中文。解决办法是设置plt.rcParams[font.sans-serif]为系统里存在的中文字体并设置plt.rcParams[axes.unicode_minus] False。如果换了字体还是乱码可能是字体缓存问题删掉~/.matplotlib缓存目录再重跑。5.5 折线图横坐标挤成一团现象是测试集折线图的横轴刻度密密麻麻完全看不清。原因是样本数多默认每个样本都标刻度。解决办法是用ticker.MultipleLocator设置刻度间隔或者用plt.xticks(rotation45)旋转标签。如果样本特别多还可以考虑只画前 N 个样本或者改用散点图代替折线图。6. 进阶用法把这份代码改成你自己的回归任务跑通示例只是第一步真正有价值的是把它迁移到自己的数据上。我一般会按下面这个顺序改基本不会翻车。第一步替换数据文件。把你的训练和测试数据存成 Excel列名改成脚本里对应的名字或者改脚本里的target_col。如果你的数据只有一个文件可以用train_test_split切分from sklearn.model_selection import train_test_split data pd.read_excel(your_data.xlsx) X data.drop(columns[target]) y data[target] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 )test_size0.2表示测试集占 20%random_state固定后每次切分一致。第二步做一轮超参数搜索。手动调参靠经验自动搜索更省事。用RandomizedSearchCV可以在指定范围内随机采样比网格搜索快from sklearn.model_selection import RandomizedSearchCV from scipy.stats import randint, uniform param_dist { n_estimators: randint(50, 300), learning_rate: uniform(0.01, 0.3), max_depth: randint(3, 10), subsample: uniform(0.6, 0.4), colsample_bytree: uniform(0.6, 0.4) } search RandomizedSearchCV( XGBRegressor(random_state42), param_dist, n_iter30, cv3, scoringneg_root_mean_squared_error, random_state42, n_jobs-1 ) search.fit(X_train, y_train) print(最佳参数:, search.best_params_)n_iter30表示随机尝试 30 组参数cv3是三折交叉验证scoring用负 RMSE 是因为 sklearn 的评分函数默认越大越好所以取负。n_jobs-1用满所有 CPU 核心加速。第三步验证模型稳定性。别只看一次切分的结果可以用交叉验证看 RMSE 的波动from sklearn.model_selection import cross_val_score scores cross_val_score( search.best_estimator_, X_train, y_train, cv5, scoringneg_root_mean_squared_error ) rmse_scores np.sqrt(-scores) print(交叉验证 RMSE:, rmse_scores) print(均值:, rmse_scores.mean(), 标准差:, rmse_scores.std())标准差小说明模型稳定标准差大说明对数据划分敏感可能需要更多数据或更简单的模型。第四步把可视化改成适合自己数据的样式。如果目标变量范围很大散点图可以用对数坐标如果样本特别多折线图可以改成按月或按周聚合后再画。图表不是越花哨越好能说明问题就行。从那以后我每次拿到一份新的回归代码都会先跑通示例数据确认环境和流程没问题再换自己的数据。换数据的时候先只改数据加载部分模型和绘图先不动跑通之后再逐步调参和改图。这样出问题的时候能快速定位是数据的问题还是代码的问题。希望这份拆解能帮你少走点弯路顺利把 XGBoost 回归用到自己的任务里。本文还有配套的精品资源点击获取