【机器学习】案例1.1——决策树进行非线性回归任务(正弦曲线拟合)

一、项目背景与解决方案

1. 项目背景

决策树是机器学习中经典的非参数模型,可同时支持分类和回归任务(决策树回归)。在回归场景中,决策树通过递归划分特征空间,将每个划分后的子区域映射为该区域内样本的均值(以MSE为划分准则),从而实现对连续值的预测。

本项目聚焦非线性回归任务(正弦曲线拟合),核心目标包括:

  • 验证决策树回归器对带噪声非线性数据的拟合能力;
  • 探究决策树核心超参数max_depth(树深度)对拟合效果的影响(深度过小易欠拟合,深度过大易过拟合);
  • 通过可视化对比真实值与不同深度模型的预测值,直观展示超参数选择的重要性。
2. 解决方案

整体流程分为三步:

  1. 数据构建:生成[-3, 3]范围内的随机自变量,基于正弦函数生成因变量并添加轻微噪声,模拟真实场景的非线性带噪声数据;
  2. 基础拟合验证:使用固定深度(3)的决策树回归器拟合数据,可视化预测曲线与真实值的对比;
  3. 超参数对比分析:构建深度为2/4/6/8/10的决策树回归器,分别拟合数据并可视化预测曲线,分析不同深度的拟合效果(欠拟合/过拟合)。

二、带详细注释的代码

# 导入必要的库
import numpy as np  # 数值计算库,用于生成数据、数组处理
from sklearn.tree import DecisionTreeRegressor  # 导入决策树回归器
import matplotlib.pyplot as plt  # 可视化库,用于绘制拟合结果

# ===================== 第一步:构建带噪声的正弦函数数据集 =====================
# 设置样本数量为100
N = 100
# 生成[-3, 3]范围内的随机自变量x:np.random.rand(N)生成[0,1)的随机数,*6后范围是[0,6),-3后范围是[-3,3)
x = np.random.rand(N) * 6 - 3
# 对x进行排序,方便后续可视化(排序后曲线更易观察)
x.sort()

# 生成因变量y:基于正弦函数np.sin(x),添加均值为0、方差0.05的随机噪声(模拟真实数据的噪声)
y = np.sin(x) + np.random.rand(N) * 0.05
# 打印y值(可选,用于调试查看数据)
print(y)

# 重塑x的形状:sklearn模型要求输入特征为二维数组(样本数×特征数),reshape(-1,1)表示将一维数组转为N行1列的二维数组
x = x.reshape(-1, 1)
# 打印重塑后的x(可选,用于调试查看数据维度)
print(x)

# ===================== 第二步:使用固定深度的决策树回归拟合数据 =====================
# 初始化决策树回归器
# criterion='mse':划分准则为均方误差(回归任务默认准则,最小化每个节点的均方误差)
# max_depth=3:设置决策树最大深度为3,限制树的复杂度,避免过拟合
dt_reg = DecisionTreeRegressor(criterion='mse', max_depth=3)
# 用训练数据(x,y)拟合决策树模型
dt_reg.fit(x, y)

# 生成测试集:在[-3,3]范围内生成50个均匀分布的点,用于绘制平滑的预测曲线
x_test = np.linspace(-3, 3, 50).reshape(-1, 1)
# 使用训练好的模型预测测试集的y值
y_hat = dt_reg.predict(x_test)

# 可视化真实值与预测值
plt.plot(x, y, "y*", label="actual")  # 绘制真实值,黄色星号标记
plt.plot(x_test, y_hat, "b-", linewidth=2, label="predict")  # 绘制预测值,蓝色实线,线宽2
plt.legend(loc="upper left")  # 显示图例,位置在左上角
plt.grid()  # 显示网格线,方便观察
plt.show()  # 展示图像
# plt.savefig("./temp_decision_tree_regressor")  # 可选:保存图像到指定路径

# ===================== 第三步:对比不同深度的决策树拟合效果 =====================
# 定义要测试的决策树深度列表
depth = [2, 4, 6, 8, 10]
# 定义对应深度曲线的颜色(r=红,g=绿,b=蓝,m=品红,y=黄)
color = 'rgbmy'
# 初始化决策树回归器(暂不指定深度,后续通过set_params动态修改)
dt_reg = DecisionTreeRegressor()
# 绘制真实值,黑色圆点标记
plt.plot(x, y, "ko", label="actual")
# 生成测试集(与第二步一致,用于绘制平滑预测曲线)
x_test = np.linspace(-3, 3, 50).reshape(-1, 1)

# 遍历不同深度和对应颜色,逐一训练并可视化
for d, c in zip(depth, color):
    # 动态设置决策树的最大深度
    dt_reg.set_params(max_depth=d)
    # 用训练数据拟合当前深度的决策树
    dt_reg.fit(x, y)
    # 预测测试集的y值
    y_hat = dt_reg.predict(x_test)
    # 绘制当前深度的预测曲线,指定颜色和线宽,添加图例标签
    plt.plot(x_test, y_hat, '-', color=c, linewidth=2, label="depth=%d" % d)

# 显示图例,位置在左上角
plt.legend(loc="upper left")
# 显示网格线(b=True为显式开启,默认开启)
plt.grid(b=True)
# 展示图像
plt.show()
# plt.savefig("./temp_compare_decision_tree_depth")  # 可选:保存对比图像到指定路径

简洁版

import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt

# 生成带噪声的正弦数据集
N = 100
x = np.random.rand(N) * 6 - 3
x.sort()
y = np.sin(x) + np.random.rand(N) * 0.05
x = x.reshape(-1, 1)

# 固定深度决策树回归拟合与可视化
dt_reg = DecisionTreeRegressor(criterion='mse', max_depth=3)
dt_reg.fit(x, y)
x_test = np.linspace(-3, 3, 50).reshape(-1, 1)
y_hat = dt_reg.predict(x_test)

plt.plot(x, y, "y*", label="actual")
plt.plot(x_test, y_hat, "b-", linewidth=2, label="predict")
plt.legend(loc="upper left")
plt.grid()
plt.show()

# 对比不同深度决策树拟合效果
depth = [2, 4, 6, 8, 10]
color = 'rgbmy'
dt_reg = DecisionTreeRegressor()
plt.plot(x, y, "ko", label="actual")
x_test = np.linspace(-3, 3, 50).reshape(-1, 1)

for d, c in zip(depth, color):
    dt_reg.set_params(max_depth=d)
    dt_reg.fit(x, y)
    y_hat = dt_reg.predict(x_test)
    plt.plot(x_test, y_hat, '-', color=c, linewidth=2, label=f"depth={d}")

plt.legend(loc="upper left")
plt.grid(b=True)
plt.show()

三、代码运行结果分析

  1. 固定深度(3)的拟合结果:预测曲线能大致贴合正弦曲线的趋势,但因深度限制,曲线是分段常数(决策树回归的特性),不会过度拟合噪声;
  2. 不同深度的对比结果
    • 深度=2:曲线过于简单,无法捕捉正弦曲线的波动,呈现欠拟合
    • 深度=4/6:曲线能较好贴合正弦曲线趋势,拟合效果最优;
    • 深度=8/10:曲线过度贴合噪声点,呈现过拟合(曲线出现不必要的锯齿状波动)。

该结果验证了决策树深度对拟合效果的核心影响:深度需根据数据复杂度合理选择,过浅欠拟合、过深过拟合。

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值