决策树回归实战:波士顿房价预测与模型调优

决策树回归实战:波士顿房价预测与模型调优
1. 决策树回归实战从波士顿房价预测到模型调优全解析在机器学习领域决策树因其直观易懂的特性广受欢迎。大多数人接触决策树都是从分类问题开始但决策树同样擅长解决回归问题——预测连续数值。今天我们就来深入探讨决策树回归的完整实现流程以经典的波士顿房价预测为例带你从零开始构建模型并通过学习曲线分析和网格搜索调参来优化模型性能。2. 决策树回归基础概念2.1 决策树回归与分类的核心区别决策树回归和分类在核心划分逻辑上是一致的都采用贪心算法进行特征选择和节点划分。但它们在几个关键方面存在显著差异对比维度决策树分类决策树回归任务目标预测离散类别标签预测连续数值划分准则基尼系数/信息熵均方误差(MSE)/平均绝对误差(MAE)叶节点输出节点中占比最多的类别节点中所有样本标签的均值模型评估指标准确率、精确率、召回率等R²分数、MSE、MAE、RMSESklearn实现类DecisionTreeClassifierDecisionTreeRegressor在实际应用中回归树的每个叶节点不再输出类别而是输出该节点所有训练样本标签的平均值。这种设计使得决策树能够很好地捕捉数据中的非线性关系。2.2 回归模型评估指标详解在回归任务中我们主要使用以下几个评估指标均方误差(MSE)公式MSE 1/n Σ(y_true - y_pred)²特点对较大误差惩罚更重因为误差被平方了平均绝对误差(MAE)公式MAE 1/n Σ|y_true - y_pred|特点对异常值不如MSE敏感R²分数(决定系数)公式R² 1 - Σ(y_true-y_pred)²/Σ(y_true-ȳ)²特点衡量模型解释标签变化的能力最佳值为1可能为负其中R²分数是最常用的回归评估指标它表示模型能够解释的目标变量方差的比例。R²1表示完美预测R²0表示模型仅相当于预测均值R²0则表示模型表现比简单预测均值还要差。3. 波士顿房价预测实战3.1 数据准备与环境设置首先我们需要设置Python环境并加载数据import matplotlib.pyplot as plt import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import r2_score import warnings # 环境配置 plt.rcParams[font.sans-serif] [SimHei] # 解决中文显示问题 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题 warnings.filterwarnings(ignore) # 过滤警告信息 # 加载波士顿房价数据集 boston datasets.load_boston() X boston.data # 特征数据 (506, 13) y boston.target # 目标值 (506,) # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split(X, y, random_state233)注意较新版本的scikit-learn中load_boston已被移除可以使用fetch_california_housing()替代或者手动下载波士顿房价数据集。3.2 基础模型训练与评估让我们先训练一个没有任何剪枝参数的决策树回归模型# 初始化决策树回归器 reg DecisionTreeRegressor() # 训练模型 reg.fit(X_train, y_train) # 评估模型 train_score reg.score(X_train, y_train) test_score reg.score(X_test, y_test) print(f训练集R²分数: {train_score:.4f}) print(f测试集R²分数: {test_score:.4f})运行结果通常会显示训练集R²为1.0而测试集R²明显较低约0.7-0.8这是典型的过拟合现象——模型完美记住了训练数据但对新数据的泛化能力不足。4. 模型诊断与调优4.1 学习曲线分析学习曲线是诊断模型问题的有力工具。它展示了随着训练样本数量的增加模型在训练集和测试集上性能的变化情况。plt.figure(figsize(12, 8)) max_depths [2, 5, 10, 20] for i, depth in enumerate(max_depths): reg DecisionTreeRegressor(max_depthdepth) train_scores, test_scores [], [] # 逐步增加训练样本 for k in range(1, len(X_train)1): reg.fit(X_train[:k], y_train[:k]) train_scores.append(r2_score(y_train[:k], reg.predict(X_train[:k]))) test_scores.append(r2_score(y_test, reg.predict(X_test))) # 绘制子图 plt.subplot(2, 2, i1) plt.plot(range(1, len(X_train)1), train_scores, r-, label训练集) plt.plot(range(1, len(X_train)1), test_scores, b-, label测试集) plt.title(f最大深度{depth}) plt.xlabel(训练样本数量) plt.ylabel(R²分数) plt.legend() plt.grid(True) plt.tight_layout() plt.show()通过分析不同深度下的学习曲线我们可以得出以下结论max_depth2训练和测试分数都较低模型欠拟合max_depth5训练和测试分数达到较好平衡max_depth10训练分数接近1测试分数开始下降出现过拟合max_depth20严重过拟合测试分数明显低于训练分数4.2 网格搜索调参手动尝试各种参数组合效率低下我们可以使用网格搜索自动寻找最优参数from sklearn.model_selection import GridSearchCV # 定义参数网格 param_grid { max_depth: range(2, 15), min_samples_leaf: range(3, 20) } # 初始化网格搜索 grid_search GridSearchCV( estimatorDecisionTreeRegressor(), param_gridparam_grid, cv5, # 5折交叉验证 n_jobs-1 # 使用所有CPU核心 ) # 执行搜索 grid_search.fit(X_train, y_train) # 输出最优结果 print(f最优参数: {grid_search.best_params_}) print(f最优交叉验证R²: {grid_search.best_score_:.4f}) print(f测试集R²: {grid_search.best_estimator_.score(X_test, y_test):.4f})典型的输出结果可能是最优参数: {max_depth: 5, min_samples_leaf: 3} 最优交叉验证R²: 0.7352 测试集R²: 0.7824可以看到经过调参后模型在测试集上的表现从约0.74提升到了0.78左右泛化能力得到了明显改善。5. 决策树回归的过拟合与解决方案5.1 决策树过拟合的特征决策树特别容易过拟合主要表现在训练集R²分数接近或等于1测试集R²显著低于训练集树结构非常深有很多节点学习曲线中训练和测试分数差距大5.2 常用剪枝参数为了防止过拟合我们可以使用以下预剪枝参数max_depth树的最大深度min_samples_split节点分裂所需的最小样本数min_samples_leaf叶节点所需的最小样本数max_leaf_nodes最大叶节点数量min_impurity_decrease分裂需要的最小不纯度减少量在实际应用中通常从max_depth和min_samples_leaf开始调优这两个参数对模型性能影响最大。6. 完整代码实现以下是整合了所有功能的完整代码可以直接在PyCharm等IDE中运行# 决策树回归完整实现波士顿房价预测 import matplotlib.pyplot as plt import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import r2_score import warnings # 1. 环境配置 warnings.filterwarnings(ignore) plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 2. 数据准备 boston datasets.load_boston() X, y boston.data, boston.target X_train, X_test, y_train, y_test train_test_split(X, y, random_state233) # 3. 基础模型 base_model DecisionTreeRegressor() base_model.fit(X_train, y_train) print(f基础模型 - 训练R²: {base_model.score(X_train, y_train):.4f}) print(f基础模型 - 测试R²: {base_model.score(X_test, y_test):.4f}) # 4. 学习曲线分析 plt.figure(figsize(12, 8)) for i, depth in enumerate([2, 5, 10, 20]): model DecisionTreeRegressor(max_depthdepth) train_scores, test_scores [], [] for k in range(1, len(X_train)1): model.fit(X_train[:k], y_train[:k]) train_scores.append(r2_score(y_train[:k], model.predict(X_train[:k]))) test_scores.append(r2_score(y_test, model.predict(X_test))) plt.subplot(2, 2, i1) plt.plot(range(1, len(X_train)1), train_scores, r-, label训练集) plt.plot(range(1, len(X_train)1), test_scores, b-, label测试集) plt.title(fmax_depth{depth}) plt.legend() plt.tight_layout() plt.show() # 5. 网格搜索调参 param_grid { max_depth: range(2, 15), min_samples_leaf: range(3, 20) } grid GridSearchCV(DecisionTreeRegressor(), param_grid, cv5, n_jobs-1) grid.fit(X_train, y_train) best_model grid.best_estimator_ print(f最优参数: {grid.best_params_}) print(f最优模型测试R²: {best_model.score(X_test, y_test):.4f})7. 常见问题与解决方案在实际应用中可能会遇到以下典型问题问题训练分数很高但测试分数很低原因模型过拟合解决增加min_samples_leaf或减小max_depth问题训练和测试分数都很低原因模型欠拟合解决增大max_depth或减小min_samples_leaf问题网格搜索运行时间过长原因参数空间太大解决先粗调后精调或使用RandomizedSearchCV问题R²分数为负原因模型表现比简单预测均值还差解决检查数据预处理或模型选择是否有问题决策树回归是一个强大而直观的工具特别适合作为入门机器学习的第一个回归算法。通过本教程的实践你应该已经掌握了从基础实现到高级调优的完整流程。记住模型调优的关键在于平衡偏差和方差找到那个既不过于简单又不过于复杂的甜蜜点。