决策树回归超详细讲解(附完整实战代码)
决策树回归(Decision Tree Regression)是机器学习中经典的数值预测算法,核心思路是通过"提问-划分数据-输出预测值"的树形决策过程,完成房价、销量、温度这类连续值的预测,理解门槛低、实战性强,是本科和研究生机器学习入门的重点算法。
本文会从通俗原理 、核心流程 、数学推导 、完整实战 、优缺点与算法对比五个维度讲解,内容通俗易懂,附带可直接运行的Python代码,适配本科课程学习和研究生入门实践。
一、什么是决策树回归?(通俗理解)
可以把决策树回归想象成玩"20个问题猜答案 "的游戏,核心是通过一系列针对性问题,把数据分成相似的小组,用小组的平均值作为预测结果。
举个房价预测的例子,决策树会这样一步步提问划分:
- 房子面积大于100㎡吗?→ 是(左分支)/ 否(右分支)
- 房子在市中心吗?→ 是(左分支)/ 否(右分支)
- 房子是豪华装修吗?→ 是(左分支)/ 否(右分支)
经过多轮提问,所有房子会被分到不同的小分组中,每个分组的房价平均值,就是这个分组内新房的预测价格 。
这个**"问问题→划分子集→计算均值预测"**的过程,就是决策树回归的核心逻辑。
二、决策树回归的工作流程
决策树回归的训练过程分为3个核心步骤,简单来说就是先分大组,再拆小组,最后定预测值:
- 初次分组 :从所有特征中找一个最优分割点(比如面积100㎡、收入8000元),把整体数据切成两部分,让每部分内的数据尽可能相似(比如同面积的房子房价更接近);
- 递归细分 :对切分后的每个子组,继续找最优分割点再拆分,直到满足停止条件(比如子组数据量太少、数据已经足够相似);
- 生成预测值 :当数据不能再拆分时,取每个子组的所有数据的平均值,作为这个子组的最终预测值。
三、决策树回归核心原理与数学推导
决策树回归的核心是通过二元划分(每次切分成2组)最小化数据的均方误差(MSE),让每个子组的"纯度"最高(数据最相似),以下是关键原理和数学公式,公式均做简化解释,适配入门学习。
3.1 核心评价指标:均方误差(MSE)
回归任务中,用均方误差 衡量模型的预测误差,误差越小,模型预测越准确,也是决策树划分节点的核心依据。
对于一组数据(x1,y1),(x2,y2),...,(xn,yn){(x_{1}, y_{1}),(x_{2}, y_{2}), ...,(x_{n}, y_{n})}(x1,y1),(x2,y2),...,(xn,yn),均方误差的定义为:
MSE=1n∑i=1n(yi−y^i)2MSE=\frac{1}{n} \sum_{i=1}^{n}\left(y_{i}-\hat{y}_{i}\right)^{2}MSE=n1i=1∑n(yi−y^i)2
- yiy_iyi:数据的真实值(比如房子的实际价格);
- y^i\hat{y}_iy^i:数据的预测值(比如模型算出的房价);
- nnn:数据的样本数量。
决策树回归的目标:找到最优的特征和分割点,让划分后的整体均方误差最小。
3.2 节点划分的误差计算
决策树每次划分都会将一个父节点TTT分成左子节点 (满足条件,如面积≤100㎡)和右子节点 (不满足条件,如面积>100㎡),划分后的整体误差为两个子节点的加权均方误差 (按样本数加权):
MSET=nleftnT⋅MSEleft+nrightnT⋅MSErightMSE_{T}=\frac{n_{left }}{n_{T}} \cdot MSE_{left }+\frac{n_{right }}{n_{T}} \cdot MSE_{right }MSET=nTnleft⋅MSEleft+nTnright⋅MSEright
- nTn_TnT:父节点TTT的总样本数;
- nleftn_{left}nleft/nrightn_{right}nright:左/右子节点的样本数;
- MSEleftMSE_{left}MSEleft/MSErightMSE_{right}MSEright:左/右子节点的均方误差。
其中,子节点的均方误差计算和整体一致,只是数据范围限定在子节点内,且子节点的预测值y^left\hat{y}{left}y^left/y^right\hat{y}{right}y^right直接取子节点内所有真实值的平均值 :
MSEleft=1nleft∑i∈Tleft(yi−y^left)2MSE_{left }=\frac{1}{n_{left }} \sum_{i \in T_{left }}\left(y_{i}-\hat{y}{left }\right)^{2}MSEleft=nleft1i∈Tleft∑(yi−y^left)2
MSEright=1nright∑i∈Tright(yi−y^right)2MSE{right }=\frac{1}{n_{right }} \sum_{i\in T_{right }}\left(y_{i}-\hat{y}_{right }\right)^{2}MSEright=nright1i∈Tright∑(yi−y^right)2
3.3 如何找最优分割点?
决策树会通过遍历所有可能 ,找到让划分后MSETMSE_TMSET最小的特征和分割点,步骤如下:
- 遍历数据集中的每一个特征(如面积、地段、装修);
- 对每个特征,遍历其所有可能的数值作为分割点(阈值);
- 对每个分割点,计算划分后的整体加权均方误差MSETMSE_TMSET;
- 选择MSETMSE_TMSET最小的那个「特征+分割点」组合,作为本次划分的依据。
3.4 决策树的停止条件
如果让决策树无限划分,会出现过拟合 (把训练数据的噪声也学习了,测试集预测效果差),因此训练时必须设置停止条件,满足任一条件即停止划分:
- 树的最大深度:限制树的层数(比如最多分5层),避免树长得过大;
- 叶子节点最小样本数:每个最终子组的样本数不能少于某个值(比如最少5个样本);
- 最小误差增益:如果本次划分后,整体均方误差的减少量小于某个阈值,说明划分无意义,直接停止;
- 数据无法再划分:特征已遍历完毕,或所有样本的特征值完全相同。
3.5 叶子节点的最终预测
决策树的叶子节点 (最终无法再划分的子组)的预测值,是该节点内所有样本真实值的平均值 ,公式为:
y^=1m∑i=1myi\hat{y}=\frac{1}{m} \sum_{i=1}^{m} y_{i}y^=m1i=1∑myi
- mmm:叶子节点的样本数;
- yiy_iyi:叶子节点内每个样本的真实值。
四、决策树回归完整实战(Python+加州房价数据集)
本次实战使用加州房价数据集 (sklearn内置公开数据集),完成从数据加载→可视化→模型训练→评估→优化的全流程,代码可直接复制运行,注释详细,适配Python3.7+、sklearn1.0+。
4.1 实战目标
通过房屋的平均房间数、家庭收入、房屋年龄、经纬度等特征,预测房屋的价格,掌握决策树回归的实际应用和调参方法。
4.2 完整代码与步骤解释
步骤1:导入所需库
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 加载数据集
from sklearn.datasets import fetch_california_housing
# 数据划分、模型训练、评估
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.metrics import mean_squared_error, r2_score
# 数据标准化、网格搜索调参
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
步骤2:加载并查看数据集
python
# 加载加州房价数据集
data = fetch_california_housing()
# 特征数据转DataFrame,方便查看
X = pd.DataFrame(data.data, columns=data.feature_names)
# 目标值(房价)转Series
y = pd.Series(data.target)
# 查看前5行特征和目标值
print("特征数据前5行:")
print(X.head())
print("\n房价目标值前5行(单位:10万美元):")
print(y.head())
# 查看数据集基本信息(无缺失值,无需补全)
print("\n数据集基本信息:")
print(X.info())
步骤3:数据可视化(查看特征与房价的关系)
通过散点图查看每个特征和房价的相关性,直观理解数据分布:
python
# 绘制特征与房价的散点图,2行4列布局
plt.figure(figsize=(10, 8))
for i, column in enumerate(X.columns):
plt.subplot(2, 4, i+1)
# 散点图,alpha=0.5解决点重叠问题
plt.scatter(X[column], y, alpha=0.5)
plt.title(f'{column} 与房价的关系')
plt.xlabel(column)
plt.ylabel('房价(10万美元)')
# 调整子图间距,避免重叠
plt.tight_layout()
plt.show()
可视化结果解读:能直观看到如「家庭收入(MedInc)」和房价呈正相关,经纬度和房价有明显的区域特征。
步骤4:数据预处理与划分
决策树回归无需特征标准化 (后续会讲原因),这里做标准化是为了演示,实际可省略;同时将数据划分为训练集(80%)和测试集(20%):
python
# 数据标准化(决策树可省略,此处仅作演示)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分训练集和测试集,random_state=42保证结果可复现
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42
)
print(f"训练集样本数:{X_train.shape[0]},测试集样本数:{X_test.shape[0]}")
步骤5:训练基础决策树回归模型并评估
先训练未调参的基础模型,观察模型表现,重点看过拟合现象:
python
# 初始化决策树回归模型,random_state=42保证结果可复现
model = DecisionTreeRegressor(random_state=42)
# 用训练集训练模型
model.fit(X_train, y_train)
# 对训练集和测试集做预测
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
# 计算模型评估指标:MSE(均方误差)、R²(决定系数,越接近1越好)
train_mse = mean_squared_error(y_train, y_train_pred)
test_mse = mean_squared_error(y_test, y_test_pred)
train_r2 = r2_score(y_train, y_train_pred)
test_r2 = r2_score(y_test, y_test_pred)
# 打印评估结果
print("基础模型评估结果:")
print(f"训练集MSE:{train_mse:.2f}")
print(f"测试集MSE:{test_mse:.2f}")
print(f"训练集R²:{train_r2:.2f}")
print(f"测试集R²:{test_r2:.2f}")
结果解读 :基础模型会出现训练集R²≈1,测试集R²较低 ,这是典型的过拟合,因为决策树无限制划分,把训练集的噪声都学习了。
步骤6:可视化决策树(理解模型决策过程)
通过可视化树形结构,直观看到模型的划分特征、分割点,理解决策树的工作原理:
python
# 绘制决策树,figsize设置图大小,filled=True填充颜色
plt.figure(figsize=(20, 10))
plot_tree(
model,
filled=True, # 节点填充颜色
feature_names=X.columns, # 显示特征名
fontsize=10 # 字体大小
)
plt.title("加州房价预测-决策树回归模型", fontsize=16)
plt.show()
可视化解读:每个节点会显示「划分特征+分割点」「样本数」「MSE」,叶子节点会显示最终的预测均值,能清晰看到模型是如何一步步划分数据的。
步骤7:模型优化(网格搜索GridSearchCV调参)
决策树的性能受树的深度、叶子节点最小样本数 等参数影响极大,通过网格搜索遍历最优参数组合,解决过拟合问题,提升模型泛化能力:
python
# 定义待搜索的参数范围,核心调参参数
param_grid = {
'max_depth': [5, 10, 15, None], # 树的最大深度
'min_samples_split': [2, 5, 10], # 节点划分所需的最小样本数
'min_samples_leaf': [1, 2, 4], # 叶子节点的最小样本数
'max_features': ['sqrt', 'log2'] # 划分时使用的最大特征数
}
# 初始化网格搜索,cv=5表示5折交叉验证,评分标准为负MSE(sklearn默认越大越好)
grid_search = GridSearchCV(
estimator=DecisionTreeRegressor(random_state=42),
param_grid=param_grid,
cv=5,
scoring='neg_mean_squared_error'
)
# 用训练集训练网格搜索模型,找到最优参数
grid_search.fit(X_train, y_train)
# 打印最优参数和最优交叉验证MSE
print("网格搜索最优参数:")
print(grid_search.best_params_)
print(f"\n最优交叉验证MSE:{-grid_search.best_score_:.2f}")
# 使用最优参数训练最终模型
best_model = grid_search.best_estimator_
# 用最优模型对测试集预测
y_test_pred_optimized = best_model.predict(X_test)
# 评估优化后的模型
test_mse_optimized = mean_squared_error(y_test, y_test_pred_optimized)
test_r2_optimized = r2_score(y_test, y_test_pred_optimized)
print(f"\n优化后模型-测试集MSE:{test_mse_optimized:.2f}")
print(f"优化后模型-测试集R²:{test_r2_optimized:.2f}")
调参结果解读 :优化后模型的测试集R²会明显提升,MSE会降低,过拟合问题得到有效解决。
步骤8:对比优化前后模型表现
python
# 打印优化前后的测试集指标对比
print("模型优化前后对比(测试集):")
print(f"优化前 - MSE:{test_mse:.2f},R²:{test_r2:.2f}")
print(f"优化后 - MSE:{test_mse_optimized:.2f},R²:{test_r2_optimized:.2f}")
# 绘制预测值与真实值的对比图
plt.figure(figsize=(10, 6))
# 散点图:真实值vs预测值
plt.scatter(y_test, y_test_pred_optimized, color='blue', alpha=0.5, label='预测值vs真实值')
# 红线:理想预测(预测值=真实值)
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='red', linewidth=2, label='理想预测线')
plt.xlabel('真实房价(10万美元)')
plt.ylabel('预测房价(10万美元)')
plt.title('决策树回归模型-真实值vs预测值', fontsize=16)
plt.legend()
plt.show()
对比解读 :优化后的模型散点会更贴近红色理想线,说明预测值和真实值的偏差更小,模型性能显著提升。
五、决策树回归的优缺点
5.1 优点(入门首选的核心原因)
- 易于理解和解释:树形结构直观展示决策过程,能清晰看到哪个特征对预测结果影响最大,适合向非技术人员解释模型,也是本科/研究生课程中易上手的原因;
- 无需特征缩放/归一化:不受特征量纲影响(比如面积用㎡还是㎡²,收入用元还是万元),无需做标准化、归一化,简化数据预处理步骤;
- 能处理非线性关系:完美适配特征和目标值之间的复杂非线性关系(比如房价和经纬度的区域非线性关系),弥补线性回归的不足;
- 直接处理类别特征:无需将类别特征(如地段:市中心/郊区、装修:豪华/普通)转成数值型,模型可直接根据类别划分数据,适配混合类型数据(数值+类别)。
5.2 缺点(核心问题需注意)
- 极易过拟合 :未调参的决策树会无限划分数据,学习到训练集的噪声,导致测试集预测效果差,必须通过调参/剪枝解决;
- 模型不稳定:对训练数据的微小变化极其敏感(比如删除几个样本、修改一个特征值),会导致树形结构发生巨大变化,泛化能力弱;
- 对噪声/异常值敏感:异常值会误导决策树的分割点选择,导致模型划分不合理,预测结果偏差大,训练前建议做异常值处理;
- 计算复杂度随深度提升:单节点计算简单,但树的深度越大、数据量/特征数越多,训练时间越长,处理超大规模数据时效率较低。
六、决策树回归与相似算法的对比
为了让大家在实战中选对算法 ,以下对比决策树回归与线性回归、支持向量回归(SVR)、随机森林回归、梯度提升回归(GBR)的优缺点+适用场景,表格简洁明了,适配本科课程考核和研究生实战选型:
| 算法 | 核心优点 | 核心缺点 | 适用场景 |
|---|---|---|---|
| 决策树回归 | 直观易懂、无需特征缩放、处理非线性/类别特征 | 易过拟合、模型不稳定、对噪声敏感 | 特征关系复杂、需要模型解释性、数据预处理不足的场景(如房价预测、销量预测) |
| 线性回归 | 简单高效、计算开销小、易理解 | 仅适用于线性关系、对异常值敏感 | 特征与目标值呈线性关系的简单预测(如身高预测体重、销量预测广告费用) |
| 支持向量回归(SVR) | 适配高维数据、核函数处理复杂非线性 | 参数调优要求高、计算开销大、不适用于大数据集 | 高维数据(如文本特征)、需要高精度的非线性预测 |
| 随机森林回归 | 抗过拟合、自动特征选择、适配高维数据 | 训练时间长、模型难以解释、对噪声敏感 | 数据集大、特征关系复杂、需要高精度且可接受黑箱模型的场景(如金融预测) |
| 梯度提升回归(GBR) | 预测精度极高、适配高维/大数据集 | 训练时间长、参数敏感、易过拟合 | 对预测精度要求极高、不计较训练时间的复杂场景(如竞赛、工业级预测) |
关键选型结论
- 优先选决策树回归:需要模型解释性、特征关系非线性、数据预处理不充分时;
- 选线性回归:特征与目标值呈明显线性关系,追求简单高效时;
- 选随机森林/梯度提升 :需要高精度预测、可接受黑箱模型、数据集较大时(解决决策树过拟合的最优方案);
- 选SVR:高维数据预测、数据集规模较小时。
七、总结
- 决策树回归是数值预测 的入门算法,核心是通过二元划分最小化MSE,用叶子节点的均值作为预测值,理解和实现门槛低;
- 决策树的最大问题是过拟合,必须通过调参(max_depth、min_samples_leaf等)或集成学习(随机森林)解决;
- 决策树的核心优势是可解释性和免预处理,适合特征复杂、需要向非技术人员解释的场景,是本科和研究生机器学习的重点掌握内容;
- 实战中如果追求高精度,不建议单独使用决策树,优先选择其集成版本(随机森林、梯度提升),既保留了决策树处理非线性的优势,又解决了过拟合和不稳定性问题。
拓展学习 :掌握决策树回归后,可继续学习随机森林回归 (决策树的集成,Bagging思想)、梯度提升回归(XGBoost/LightGBM)(Boosting思想),这两类是工业界和竞赛中的主流算法,也是研究生阶段的重点学习内容。