哈喽,大家好~
今天和大家聊聊线性回归和决策树的对比,在回归建模中线性与非线性模型的适配选择~
在线性回归和决策树用于回归建模的问题中,我们面对的是一个关键的选择:线性模型 vs 非线性模型。
这关系到模型的预测能力、可解释性、训练效率等多方面。
下面,咱们先从基础概念讲起,
线性回归
假设输入特征为 ,输出为 。线性回归模型假设输出与输入呈线性关系:
其中:
-
:待估参数 -
:噪声项
最小化目标函数(均方误差):
解析解:
决策树回归
回归树的基本思想是将特征空间分割成若干个子区域,对每个区域内的样本用一个常数值(通常是该区域内样本的均值)来预测输出。
基本形式:
其中:
-
:划分出的区域 -
:区域内样本均值 -
:指示函数
目标是最小化平方损失:
线性模型与非线性模型适配性比较
|
|
|
|
|---|---|---|
| 模型形式 |
|
|
| 对特征的要求 |
|
|
| 可解释性 |
|
|
| 鲁棒性 |
|
|
| 过拟合倾向 |
|
|
| 拟合能力 |
|
|
| 特征扩展支持 |
|
|
适配推理过程
线性回归推理过程
目标函数:
取导求极值:
这说明当数据确实满足线性关系时,线性回归能够以最小方差无偏性估计出最优解。
适配条件:
-
与 的关系近似线性; -
噪声为高斯分布; -
特征间没有多重共线性。
决策树回归推理过程
每次划分过程:
-
对每个特征 ,对其所有可能的切分点 :
-
将样本划分为两部分 , -
对每个区域拟合一个常数 -
计算总平方误差:
-
选取最小化误差的 划分。
适配条件:
-
目标函数非线性; -
特征间存在交互作用; -
数据分布非均匀、噪声分布未知或非高斯; -
存在离群值。
总的来说,选择关键在于数据理解。如果你知道变量之间是线性的,选择线性回归;如果你不了解变量关系或预期高度非线性,先尝试决策树;
使用交叉验证或 AIC/BIC 等模型选择准则来比较模型优劣;
在实际应用中,以解释为主选择线性回归,以性能为主选择树模型或集成方法。
完整案例
在现实中的回归问题中,模型选择是建模成功的核心之一。我们常常会面临如下问题:
给定一组数据,我们应选择线性模型(如线性回归)还是非线性模型(如决策树回归)?
它们在预测效果、鲁棒性和解释性上有哪些差异?
如何利用图形和指标做出理性选择?
为了说明这些问题,我们将构造一个 含有线性与非线性成分的合成数据集,分别使用线性回归和决策树进行建模,并通过图像与误差指标进行全面分析。
我们设计一个数据集,包含两种变量:
-
:与目标变量 具有明显线性关系 -
:与目标变量具有非线性关系(例如正弦) -
添加噪声项
目标变量定义为:
这个设定兼顾线性和非线性结构,非常适合比较模型性能。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
np.random.seed(42)
# 1. 构造数据
n_samples = 3000
x1 = np.random.rand(n_samples) # 线性特征
x2 = np.random.rand(n_samples) # 非线性特征
epsilon = np.random.normal(0, 0.1, size=n_samples)
y = 3 * x1 + 2 * np.sin(1.5 * np.pi * x2) + epsilon
X = np.vstack([x1, x2]).T
y = y.reshape(-1, 1)
# 拆分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 2. 建模
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_test)
tree = DecisionTreeRegressor(max_depth=5)
tree.fit(X_train, y_train)
y_pred_tree = tree.predict(X_test)
# 3. 指标评估
mse_lr = mean_squared_error(y_test, y_pred_lr)
mse_tree = mean_squared_error(y_test, y_pred_tree)
r2_lr = r2_score(y_test, y_pred_lr)
r2_tree = r2_score(y_test, y_pred_tree)
print(f"Linear Regression: MSE = {mse_lr:.4f}, R^2 = {r2_lr:.4f}")
print(f"Decision Tree: MSE = {mse_tree:.4f}, R^2 = {r2_tree:.4f}")
# 4. 图像绘制
fig, axs = plt.subplots(2, 2, figsize=(16, 12))
# 图1:真实目标值与预测值散点图(线性回归)
axs[0, 0].scatter(y_test, y_pred_lr, color="dodgerblue", alpha=0.6, label="预测值")
axs[0, 0].plot(y_test, y_test, color="black", linestyle="--", label="理想线")
axs[0, 0].set_title("线性回归预测 vs 实际", fontsize=14)
axs[0, 0].set_xlabel("实际值")
axs[0, 0].set_ylabel("预测值")
axs[0, 0].legend()
# 图2:真实目标值与预测值散点图(决策树)
axs[0, 1].scatter(y_test, y_pred_tree, color="orange", alpha=0.6, label="预测值")
axs[0, 1].plot(y_test, y_test, color="black", linestyle="--", label="理想线")
axs[0, 1].set_title("决策树预测 vs 实际", fontsize=14)
axs[0, 1].set_xlabel("实际值")
axs[0, 1].set_ylabel("预测值")
axs[0, 1].legend()
# 图3:模型残差分布图(线性 vs 树)
residuals_lr = y_test.flatten() - y_pred_lr.flatten()
residuals_tree = y_test.flatten() - y_pred_tree.flatten()
sns.kdeplot(residuals_lr, label="线性回归", ax=axs[1, 0], color="dodgerblue", fill=True)
sns.kdeplot(residuals_tree, label="决策树", ax=axs[1, 0], color="orange", fill=True)
axs[1, 0].axvline(0, linestyle="--", color="gray")
axs[1, 0].set_title("残差分布比较", fontsize=14)
axs[1, 0].set_xlabel("残差")
axs[1, 0].legend()
# 图4:x2 对 y 的关系(非线性特征)
axs[1, 1].scatter(x2, y, color="purple", alpha=0.6)
axs[1, 1].set_title("x2 与 y 的非线性关系", fontsize=14)
axs[1, 1].set_xlabel("x2")
axs[1, 1].set_ylabel("y")
plt.tight_layout()
plt.show()
图1:线性回归预测 vs 实际值
评估线性回归对测试集的预测效果。点与理想线(对角线)偏离明显,尤其在高值区域说明预测存在系统误差。
图2:决策树预测 vs 实际值
查看非线性模型的预测准确性。预测点更靠近理想线,说明模型捕捉到了非线性特征。
图3:残差分布比较
比较两个模型的误差分布,线性回归的残差呈现双峰形状(未能拟合非线性成分)。决策树残差更集中于0,拟合效果更佳。
图4:x2 与 y 的非线性关系
展示特征 x2 对目标变量 y 的非线性贡献。明显呈正弦曲线,说明需要非线性模型来捕捉其模式。
通过本实验我们验证了一个核心观点:
在建模中,理解数据结构(线性 vs 非线性)对模型选择至关重要。
线性回归简单高效,适合解释清晰场景;
决策树模型强大灵活,适合数据复杂、非线性显著的场合。
在建模实践中,推荐从简单模型入手,逐步引入更复杂的模型,配合可视化与误差分析作出理性判断。
最后

