超简单白话文机器学习 - 回归树树剪枝(含算法介绍,公式,源代码实现以及调包实现)

1. 回归树

1.1 算法介绍

大家看到这篇文章时想必已经对树这个概念已经有基础了,如果不是很了解的朋友可以看看笔者的这篇文章:

超简单白话文机器学习-决策树算法全解(含算法介绍,公式,源代码实现以及调包实现)_白话决策树-CSDN博客

对于回归树的建立,我们一般使用CART回归树,CART(Classification and Regression Trees)回归树是一种用于连续值预测的树模型。它通过递归地分裂数据集,以最小化预测误差为目标,最终生成一棵树结构的模型。

CART回归树的构建核心是选择最佳分裂点通过计算MSE进行衡量。

1. 选择最佳分裂点,对每个特征尝试所有的分裂点,计算分裂后各个数据集的均方误差。

2. 计算分裂前后的总MSE:

其中,n为总样本数,各分子分别是左子节点和右子节点的样本数。

3. 递归分裂,对每个子节点重复上述步骤直到满足停止条件(例如达到最大深度或叶节点中的样本数少于阈值)

获得最佳划分特征之后,需要确定分裂节点的阈值,需要最小化目标函数

1. 首先对于最佳划分特征中的数值进行迭代。

2. 对于该特征特定数值进行分裂的样本进行错误率的计算。

3. 汇总后选择错误率最小的数值作为阈值选择。

2. 树剪枝概述

2.1 预剪枝

2.1.1 算法

预剪枝的核心是在生成决策树的过程中提前停止树的增长。计算当前的划分是否能带来模型泛化能力的提升,如果不能,则不再继续生长子树。

有如下几种方法:

( 1 )当树到达一定深度的时候,停止树的生长。
( 2 )当到达当前结点的样本数量小于某个阈值的时候,停止树的生长。
( 3 )计算每次分裂对测试集的准确度提升,当小于某个阈值的时候 ,不再继续扩展。

2.2 后剪枝

2.2.1 算法

首先我们先讲后剪枝的伪代码用口水话进行呈现:

基于已有的树切分测试数据:

1. 如果存在任一子集是一棵树,则在该子集递归剪枝过程

2. 计算将当前两个叶节点合并后的误差

3. 计算不合并的误差

4. 如果合并可以降低误差,就合并

剪枝策略:

如果剪枝后的叶节点误差小于或等于未剪枝子树的误差,则进行剪枝,即将该内部节点变为叶节点。继续评估和剪枝树中的其他节点,直到不再有可以进一步剪枝的节点。

误差的衡量方式有多种,回归树的误差衡量我们一般选择MSE。

2.2.2 代价复杂度剪枝

前文我们已经讲了,防止过拟合的方法之一时,对决策树进行剪枝,即减少树的分支。 剪枝防止过拟合使得在测试集上的表现更好。

将公式呈现在这里:

让我们用白话文转化一下这个公式:

评价一棵树的得分由两部分组成,第一部分为SSR,一种预测错误率的衡量方式。第二部分代表决策树T的叶子结点个数,阿尔法是自定义指数,需要通过交叉验证的方式得到最佳参数,不同的参数影响最终所生成的树。

举个例子:

对于这四个树我们取得了他们总体的SSR值,假设我们的参数值为1000,计算树的得分。

选取得分最小的树作为我们的预测模型,即第一棵树拥有四个叶子节点。改变参数值会选择不同的预测模型,让我们计算在什么参数值下会分别指向哪一棵树。

在不同参数值的条件下,我们使用测试集迭代进行交叉验证,根据测试集最后的得分我们选择最佳参数作为判断标准,最终构造我们的预测树模型。

3. 手写代码实现

3.1 回归树

def regLeaf(dataset):
    return np.mean(dataset[:,-1]) #得到叶结点,目标变量的均值
    
def regErr(dataset):
    return np.var(dataset[:,-1]) * np.shape(dataset)[0] #返回的是总方差

def chooseBestSplit(dataset,leafType=regLeaf,errType=regErr,ops=(1,4)):
    tols = ops[0];tolN = ops[1] #tols是容许的误差下降值, yolN是切分的最少样本数
    if len(set(dataset[:,-1].T.tolist()[0])) == 1: #如果剩余特征为1
        return None,leafType(dataset) #直接返回叶子结点
    m,n = np.shape(dataset)
    S = errType(dataset) #数据集的总误差
    bestS = 100000; bestIndex=0;bestvalue = 0
    for featIndex in range(n-1):
        for splitVal in set(dataset[:,featIndex]): #对于某特征不同值的集合进行迭代
            mat0,mat1 = binSplitDataset(dataset,feat,splitVal)
            if (np.shape(mat0)[0] < tolN) or (np.shape(mat1)[0] < tolN): continue #如果不满足最少切分样本树
            newS = errType(mat0) + errorType(mat1) #返回数据集的总方差
            if newS < bestS: #选择总方差最少的数据分类方式
                bestIndex = feat
                bestvalue = splitVal
                bestS = newS
    if (S - bestS) < tols: #如果小于要求的误差下降值,则直接返回叶子结点
        return None,leafType(dataset)
    mat0,mat1 = binSplitDataset(dataset,bestIndex,bestvalue)
    if (np.shape(mat0)[0] < tolN) or (np.shape(mat1)[0] < tolN):
        return None, leafType(dataset)
    return bestIndex,bestValue

4. 调包实现

4.1 预剪枝

import numpy as np
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加载数据集
data = load_iris()
X = data.data
y = data.target

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 设置预剪枝条件
max_depth = 3  # 限制树的最大深度
min_samples_split = 4  # 分裂一个内部节点所需的最小样本数
min_samples_leaf = 2  # 叶节点所需的最小样本数

# 初始化并训练决策树分类器
clf = DecisionTreeClassifier(random_state=42, 
                             max_depth=max_depth, 
                             min_samples_split=min_samples_split, 
                             min_samples_leaf=min_samples_leaf)

clf.fit(X_train, y_train)

# 预测并评估模型性能
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)

print(f'预剪枝条件下的决策树分类器准确率: {accuracy:.4f}')

# 可视化决策树(需要graphviz支持)
from sklearn.tree import export_graphviz
import graphviz

dot_data = export_graphviz(clf, out_file=None, 
                           feature_names=data.feature_names,  
                           class_names=data.target_names,  
                           filled=True, rounded=True,  
                           special_characters=True)  
graph = graphviz.Source(dot_data)  
graph.render("iris_prepruned_tree")  # 将树保存为PDF文件
graph  # 在Jupyter Notebook中显示决策树

4.2 后剪枝

import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, cross_val_score
import matplotlib.pyplot as plt

# 示例数据集
X = np.array([[2.7, 2.5], [1.3, 1.5], [3.2, 2.8], [3.8, 2.5], [2.9, 2.4],
              [6.5, 3.1], [7.1, 3.4], [6.0, 2.9], [7.6, 3.2], [6.3, 3.0]])
y = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 生成完整的决策树
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)

# 获取剪枝路径
path = clf.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas, impurities = path.ccp_alphas, path.impurities

# 遍历不同的剪枝参数,选择最佳剪枝
clfs = []
for ccp_alpha in ccp_alphas:
    clf = DecisionTreeClassifier(random_state=42, ccp_alpha=ccp_alpha)
    clf.fit(X_train, y_train)
    clfs.append(clf)

# 交叉验证选择最佳剪枝参数
alpha_scores = [cross_val_score(clf, X_train, y_train, cv=2).mean() for clf in clfs]
best_clf = clfs[np.argmax(alpha_scores)]

# 在测试集上评估最佳模型
test_score = best_clf.score(X_test, y_test)
print(f'Best alpha: {ccp_alphas[np.argmax(alpha_scores)]}')
print(f'Test set score: {test_score}')

# 可视化剪枝路径
plt.figure(figsize=(10, 6))
plt.plot(ccp_alphas, alpha_scores, marker='o', drawstyle='steps-post')
plt.xlabel('Alpha')
plt.ylabel('Cross-validated accuracy')
plt.title('Alpha vs Cross-validated accuracy')
plt.show()

5. 剪枝的优点与局限性

5.1 预剪枝

5.1.1 优点

提高可解释性:便于理解。

减少计算复杂度:在构建树的过程中提前停止分裂,减少模型训练时间和计算资源的消耗。

防止过拟合:限制树的复杂度,提高模型的泛化能力。

5.1.2 局限性

次优决策:在树构建过程中基于局部信息作出决策,可能忽略了更深层次的潜在有用分裂。

信息丢失:某些潜在的重要特征和信息可能未能充分利用,导致模型的表达能力有限。

难以处理复杂模式:简单树结构可能无法捕捉复杂的决策边界,从而影响分类或回归的精度。

5.2 后剪枝

5.2.1 优点

后剪枝比预剪枝保留了更多的分支, 欠拟合风险小 , 泛化性能往往优于预剪枝决策树

5.2.2 局限性

训练时间开销大 :后剪枝过程是在生成完全决策树 之后进行的,需要自底向上对所有非叶结点逐一计算

6. 应用前景

1. 医疗保健:

-疾病预测:回归树用于疾病的发生概率,基于病患的历史数据和体检报告进行精准预测

-治疗效果评测:预测不同治疗方案的效果,帮助医生制定个性化的治疗计划

2. 环境科学:

-气象预测:用于预测天气变化趋势,例如温度,降水量等

-环境监测:监测和预测空气质量,水质等环境指标

...

6. 参考资料

https://www.cnblogs.com/wuliytTaotao/p/10724118.html

机器学习-预剪枝和后剪枝-CSDN博客

回归树剪枝:代价复杂度剪枝

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/641572.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件设计师备考笔记(十):网络与信息安全基础知识

文章目录 一、网络概述二、网络互连硬件&#xff08;一&#xff09;网络的设备&#xff08;二&#xff09;网络的传输介质&#xff08;三&#xff09;组建网络 三、网络协议与标准&#xff08;一&#xff09;网络的标准与协议&#xff08;二&#xff09;TCP/IP协议簇 四、Inter…

大模型再进化,实时互动成为未来核心能力

就在上周&#xff0c;OpenAI 又在 AI 湖面抛下一块大石&#xff0c;激起了千层浪&#xff1a;全新一代旗舰生成模型 GPT-4o 登场了。从现场演示来看&#xff0c;它与人类进行了一轮轮无缝衔接的对话&#xff0c;丝滑得就像真人&#xff0c;不仅响应时间极短&#xff0c;还能识别…

SkyWalking 介绍及部署

1、SkyWalking简介2、SkyWalking的搭建 2.1 部署Elasticsearch2.2 部署SkyWalking-Server2.3 部署SkyWalking-UI3、应用接入 3.1 jar包部署方式3.2 dockerfile方式3.3 DockerFile示例4、SkyWalking UI 界面说明 4.1 仪表盘 4.1.1 APM &#xff08;1&#xff09;全局维度&#x…

IDEA中好用的插件

IDEA中好用的插件 CodeGeeXMybatis Smart Code Help ProAlibaba Java Coding Guidelines​(XenoAmess TPM)​通义灵码常用操作 CodeGeeX 官网地址&#xff1a;https://codegeex.cn/ 使用手册&#xff1a;https://zhipu-ai.feishu.cn/wiki/CuvxwUDDqiErQUkFO2Tc4walnZY 安装完…

欣赏倪诗韵青桐断纹古琴很罕见:万中无一。

欣赏倪诗韵青桐断纹古琴很罕见&#xff1a;万中无一。龙池侧签海门倪诗韵制&#xff0c;带收藏证书此琴断纹优美如江面波光粼粼&#xff0c;为流水蛇腹断&#xff0c;是倪老师作品精品中的精品。细心的朋友可以看出倪老师在这张琴上题字非常小心认真。用一个词来形容——万中无…

【Unity2D:Animator】为角色添加动画效果

一、添加Animator组件并创建Animator Controller文件 1. 添加Animator组件&#xff1a; 2. 在Assets-Art文件夹中新建一个名为Animations的文件夹&#xff0c;用来存储所有动画资源 3. 在Animations文件夹中新建一个名为Player的文件夹&#xff0c;再创建一个名为Animators的文…

通过RAG架构LLM应用程序

在之前的博客文章中&#xff0c;我们已经描述了嵌入是如何工作的&#xff0c;以及RAG技术是什么。本节我们我们将使用 LangChain 库以及 RAG 和嵌入技术在 Python 中构建一个简单的 LLM 应用程序。 我们将使用 LangChain 库在 Python 中构建一个简单的 LLM 应用程序。LangChai…

白鹭群优化算法,原理详解,MATLAB代码免费获取

白鹭群优化算法&#xff08;Egret Swarm Optimization Algorithm&#xff0c;ESOA&#xff09;是一种受自然启发的群智能优化算法。该算法从白鹭和白鹭的捕食行为出发&#xff0c;由三个主要部分组成:坐等策略、主动策略和判别条件。将ESOA算法与粒子群算法(PSO)、遗传算法(GA)…

提取COCO 数据集的部分类

1.python提取COCO数据集中特定的类 安装pycocotools github地址&#xff1a;https://github.com/philferriere/cocoapi pip install githttps://github.com/philferriere/cocoapi.git#subdirectoryPythonAPI若报错&#xff0c;pip install githttps://github.com/philferriere…

docker-如何将容器外的脚本放入容器内,将容器内的脚本放入容器外

文章目录 前言docker-如何将容器外的脚本放入容器内&#xff0c;将容器内的脚本放入容器外、1. docker 如何将容器外的脚本放入容器内1.1. 验证 2. 将容器内的脚本放入容器外 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&…

【AI绘画Stable Diffusion】单人LoRA模型训练,打造你的专属模型,新手入门宝典请收藏!

大家好&#xff0c;我是灵魂画师向阳 本期我将教大家如何进行LoRA模型训练&#xff0c;打造你的专属模型&#xff0c;内容比较干&#xff0c;还请耐心看完&#xff01; 随着AIGC的发展&#xff0c;许多传统工作岗位正逐渐被AI取代。同时&#xff0c;AI变革也在创造前所未有的…

机器学习知识与心得

目录 机器学习实践 机器学习基础理论和概念 机器学习基本方法 1.线性回归&#xff08;回归算法&#xff09; 训练集&#xff08;Training Set&#xff09; 测试集&#xff08;Test Set&#xff09; 交叉验证 正则化 特点 2.logistic回归&#xff08;分类算法&#xf…

智慧环保一体化平台哪家好?(已解答)

在环保行业数字化转型的大潮中&#xff0c;朗观视觉智慧环保一体化平台应运而生&#xff0c;成为推动环境治理现代化的重要手段。选择一个合适的智慧环保一体化平台对于提升环境管理效率、实现精细化监管具有重要意义。本文将从多个维度为您提供一份深度分析与选择指南&#xf…

Python使用virtualenv创建虚拟环境

目录 第一步&#xff1a;安装virtualenv 第二步&#xff1a;选择一个文件夹用来放所创建的虚拟环境 第三步&#xff1a;创建虚拟环境 第四步&#xff1a;激活虚拟环境 第五步&#xff1a;退出虚拟环境 第六步&#xff1a;测试安装django 前提&#xff1a;你得有个python环…

学习通高分免费刷课实操教程

文章目录 概要整体架构流程详细步骤云上全平台登录步骤小结 概要 我之前提到过一个通过浏览器的三个脚本就可以免费高分刷课的文章&#xff0c;由于不方便拍视频进行实操演示&#xff0c;然后写下了这个实操教程&#xff0c;之前的三个脚本划到文章末尾 整体架构流程 整体大…

windows安装rocketmq遇到的问题

运行mqnamesrv.cmd闪退问题。 首先检查是否安装java环境 cdm运行java -version 然后确定环境变量是否配置正确 如果这些地方都没问题那就比较麻烦了&#xff0c;可能是jdk版本&#xff08;小版本&#xff09;与rocketmq不匹配。 小编用的版本&#xff1a; jdk是openjdk 1.8…

DOS学习-目录与文件应用操作经典案例-type

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 1. 查看文本文件内容 2. 同时查看多个文本文件内容 3. 合并文…

mysql驱动版本变更导致查询数据结果一直是空

1 引言 最近接手了一个已离职同事的java项目&#xff0c;这个项目中原来使用了自己的mysql驱动版本&#xff0c;并未使用公司公共依赖中的版本号。我想为了统一版本号&#xff0c;就将当前项目中pom文件中mysql的版本号verson给去除了。没怎么自测&#xff0c;就直接发到测试环…

【网络】为什么udp协议报头有长度字段,而tcp没有

引言&#xff1a; 在网络通信中&#xff0c;UDP&#xff08;用户数据报协议&#xff09;和TCP&#xff08;传输控制协议&#xff09;是两种常用的传输层协议。它们在设计和功能上有一些不同之处&#xff0c;其中之一就是报头中的长度字段。本文将深入探讨UDP和TCP协议中长度字…

解释JAVA语言中关于方法的重载

在JAVA语言中&#xff0c;方法的重载指的是在同一个类中可以存在多个同名方法&#xff0c;但它们的参数列表不同。具体来说&#xff0c;重载的方法必须满足以下至少一条条件: 1. 参数个数不同。 2. 参数类型不同。 3. 参数顺序不同。 当调用一个重载方法时&#xff0c;编译器…