机器学习之决策树

news/2024/5/3 5:41:12/文章来源:https://blog.csdn.net/m0_46684880/article/details/127314929

一、决策树基本介绍

Decision Tree

  1. 可以解决分类和回归问题
  2. 监督学习算法

二、决策树工作原理

从根开始,按照决策树的分类属性,从上往下,逐层划分。直到叶子节点,便能获得结果。所以决策树算法的核心在于如何构造一颗决策树?

最常见核心的决策树算法有三个——ID3、C4.5、CART

1. ID3

核心思想:以信息增益来度量特征选择,选择信息增益最大的特征进行分裂

ID3算法的具体步骤
条件熵H(D|A):已知A条件下的熵。A是训练集中除标签外的一个属性,即根据A属性的不同取值将原训练集D划分成若干子集(D1,D2,D3…)。条件熵是各子集所占比重×子集的信息熵 的加和得出。

条件给的越好,划分出子集的信息熵就越小(因为每个子集基本都是同一分类),条件熵就越小,信息增益就越大。所以信息增益最大的属性即当前最好的属性。

计算示例

计算信息增益

缺点

  • ID3 没有剪枝策略,容易过拟合
  • 信息增益准则对可取值数目较多的特征有所偏好,类似“编号”的特征其信息增益接近于 1;
  • 只能用于处理离散分布的特征
  • 没有考虑缺失值。

2. C4.5

改进

  • 引入悲观剪枝策略进行后剪枝(用递归的方式从底往上针对每一个非叶子节点,评估用一个最佳叶子节点去代替这课子树是否有益。如果剪枝后与剪枝前相比其错误率是保持或者下降,则这棵子树就可以被替换掉)
  • 引入信息增益率作为划分标准
  • 将连续特征离散化,假设 n 个样本的连续特征 A 有 m 个取值,C4.5 将其排序并取相邻两样本值的平均数共 m-1 个划分点,分别计算以该划分点作为二元分类点时的信息增益,并选择信息增益最大的点作为该连续特征的二元离散分类点
  • 对于缺失值的处理可以分为两个子问题: 1. 在特征值缺失的情况下进行划分特征的选择? (即如何计算特征的信息增益率)2. 选定该划分特征,对于缺失该特征值的样本如何处理? (即到底把这个样本划分到哪个结点里)
    • 针对问题一,C4.5 的做法是: 对于具有缺失值特征,用没有缺失的样本子集所占比重来折算;
    • 针对问题二,C4.5 的做法是: 将样本同时划分到所有子节点,不过要调整样本的权重值,其实也就是以不同概率划分到不同节点中。
      信息增益率

缺点

  • 剪枝策略可以再优化;
  • C4.5 用的是多叉树,用二叉树效率更高;
  • C4.5 只能用于分类;
  • C4.5 使用的熵模型拥有大量耗时的对数运算,连续值还有排序运算;
  • C4.5 在构造树的过程中,对数值属性值需要按照其大小进行排序,从中选择一个分割点,所以只适合于能够驻留于内存的数据集,当训练集大得无法在内存容纳时,程序无法运行。

3. CART

分类标准是基尼系数,其他内容待进一步学习

基尼系数

剪枝

训练集(上)与验证集(下)

ID3算法生成的未剪枝的决策树

1. 预剪枝

预剪枝决策树
预剪枝使得决策树的很多分支都没有“展开”,不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。但可能导致欠拟合

2. 后剪枝

后剪枝决策树
后剪枝通常比预剪枝决策树保留了更多的分支,欠拟合风险很小,泛化性能优于预剪枝。但要自底向上对非叶节点进行逐一考察,因此训练时间开销比未剪枝决策树和预剪枝决策树都要大得多


三、手写决策树算法核心

# 构造决策树
def createTree(dataSet, labels):classList = [example[-1] for example in dataSet]        # 所有分类的数组if classList.count(classList[0]) == len(classList):     # 所有标签都属于一个分类return classList[0]if len(dataSet[0]) == 1:        # 使用完了所有特征,仍不能将数据集划分成仅包含唯一类别的分组return majorityCnt(classList)  # 若所有属性都被考虑,仍无法划分标签,采用多数表决决定该叶子结点的分类bestFeat = chooseBestFeatureToSplit(dataSet)    # 选取信息增益最大的特征作为下一次分类的依据bestFeatLabel = labels[bestFeat]                # 选取特征对应的标签myTree = {bestFeatLabel:{}}     # 创建tree字典,紧跟现阶段最优特征,下一个特征位于第二个大括号内,循环递归del(labels[bestFeat])      # 使用过的特征从中删除featValues = [example[bestFeat] for example in dataSet]uniqueValues = set(featValues)for value in uniqueValues:subLabels = labels[:]   # 复制labels列表,避免每次调用createTree()函数将原始列表改变,因为有的调用在前有的调用在后myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)  # 循环递归生成树return myTree# 使用决策树的分类函数
def classify(inputTree,featLabels,testVec):firstStr = list(inputTree.keys())[0]          # 第一个按照其分类的属性secondDict = inputTree[firstStr]        # 第一个属性下的节点字典,也就是子树featIndex = featLabels.index(firstStr)   # 将标签换为索引key = testVec[featIndex]valueOfFeat = secondDict[key]if isinstance(valueOfFeat, dict):  # 如果还是个字典,说明没到叶子结点,继续递归classLabel = classify(valueOfFeat, featLabels, testVec)else:  # 如果到达叶子结点,直接返回分类标签classLabel = valueOfFeatreturn classLabel

四、sklearn实现决策树算法

1. 分类问题

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifieriris = datasets.load_iris()  # 加载鸢尾花数据集
X = iris.data[:, 2:]         # 只取后两个维度特征
y = iris.targetdt_clf = DecisionTreeClassifier(max_depth=2, criterion="entropy")  # 最大深度2,使用信息熵作为划分标准
dt_clf.fit(X, y)"""sklearn的决策树实现: CART算法DecisionTreeClassifier部分参数(默认值)criterion='gini': 划分标准.默认gini,也可以改成entropy等max_depth=2: 限制整棵树的最大深度.越大越容易过拟合max_leaf_nodes=None: 最多有几个叶子结点.越大越容易归你和min_samples_leaf=1: 对于一个叶子结点,最少应该有几个样本.越小越容易过拟合min_samples_split=2: 对于一个节点,至少有多少个样本数据,才继续拆分.越小越容易过拟合
"""# 绘制决策边界
def plot_decision_boundary(model, axis):x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 100)).reshape(-1, 1),np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 100)).reshape(-1, 1),)X_new = np.c_[x0.ravel(), x1.ravel()]y_predict = model.predict(X_new)zz = y_predict.reshape(x0.shape)from matplotlib.colors import ListedColormapcustom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])plt.contourf(x0, x1, zz, cmap=custom_cmap)plot_decision_boundary(dt_clf, axis=[0.5, 7.5, 0, 3])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.scatter(X[y==2,0], X[y==2,1])
plt.show()

DecisionTreeClassifier()构造函数部分参数及默认值

clf = KNeighborsClassifier(n_neighbors=5,weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, 
metric=’minkowski’,metric_params=None, n_jobs=1, **kwargs)
  1. criterion='gini': 划分标准.默认gini,也可以改成entropy等
  2. max_depth=2: 限制整棵树的最大深度.越大越容易过拟合
  3. max_leaf_nodes=None: 最多有几个叶子结点.越大越容易归你和
  4. min_samples_leaf=1: 对于一个叶子结点,最少应该有几个样本.越小越容易过拟合
  5. min_samples_split=2: 对于一个节点,至少有多少个样本数据,才继续拆分.越小越容易过拟合

2. 回归问题

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsboston = datasets.load_boston()
X = boston.data
y = boston.target
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)# Decision Tree Regressor
from sklearn.tree import DecisionTreeRegressordt_reg = DecisionTreeRegressor()
dt_reg.fit(X_train, y_train)dt_reg.score(X_test, y_test)
# 0.58605479243964098
dt_reg.score(X_train, y_train)
# 1.0

总结

优缺点

1. 优点

  • 计算复杂度不高,输出结果易于理解,可解释性强
  • 对中间值的缺失不敏感
  • 可以处理不相关特征和数据

2. 缺点

  • 可能会产生过拟合的问题
  • 适用数据类型:数值型和标称型(是或否)

问题

  1. 书上提到:“预剪枝显著减少了决策树的训练时间开销和测试时间开销‘”。以西瓜的例子来讲,预剪枝需要在验证集计算如果不再以当前属性划分,验证集的精度是多少;如果以当前属性划分,验证集的精度是多少;然后通过两个精度对比,决定是否继续划分。这不是增加了训练时间吗?本来只需要直接划分就好了。是因为如果当前节点不再划分,就没有后续子节点了,所以树的深度小了,所以训练时间开销降低吗?

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

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

相关文章

Flink内存模型

一、内存布局 1、直观图2、树状图 二、内存解释 1、Flink使用的内存 (1)JVM堆上内存说明:堆上内存管理序列化之后的数据,如果需要处理的数据超出了内存限制,则会将部分数据存储到硬盘上。堆上内存在写磁盘或网络传输时至少需要一次内存复制。a.框架堆上内存Framework Heap…

[附源码]Java计算机毕业设计SSMOA自动化办公系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

DenseNet - 稠密神经网络(CNN卷积神经网络)

文章目录DenseNet - 稠密神经网络稠密块体稠密块中的卷积层稠密块过渡层DenseNet模型训练模型小结DenseNet - 稠密神经网络 ResNet极大地改变了如何参数化深层网络中函数的观点。 稠密连接网络(DenseNet) [Huang et al., 2017]在某种程度上是ResNet的逻…

阿里巴巴面试题- - -多线程并发篇(四十一)

前言:七月末八月初的时候,秋招正式打响,公司会放出大量的全职和实习岗位。为了帮助秋招的小伙伴们,学长这里整理了一系列的秋招面试题给大家,所以小伙伴们不用太过焦虑,相信你们一定能超常发挥,收到心仪公司的Offer~~ 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elast…

SptingBoot基于Echarts生成折线图,柱状图。看完必会,超详细~~

SptingBoot基于Echarts生成折线图,柱状图前言用到的技术与开源代码1.PhantomJS2.Echartsconvert 开源项目2.SpringBoot实现统计图生成1.pom.xml重要依赖2.图片数据模板3.JAVA代码结尾前言 近期产品团伙给了一个生成PDF数据报的需求,PDF中需要生成折线图…

MySQL死锁排查步骤

系列文章目录 第一章:sql_mode模式 第二章:optimize table、analyze table、alter table、gh-ost 第三章:InnoDB MVCC原理 第四章:sql语句执行过程 第五章:Percona Toolkit工具简介 第六章:MySQL索引 第七…

TRC丨艾美捷TRC 波普瑞韦代谢物 M4说明书

艾美捷TRC 波普瑞韦代谢物 M4—丙型肝炎病毒 NS3 丝氨酸蛋白酶抑制剂 Boceprevir (B675500) 的代谢物。 艾美捷TRC 波普瑞韦代谢物 M4化学性质: 目录号B674520 化学名称波普瑞韦代谢物 M4 同义词(1R,2S,5S)-3-[(2S)-2-[[[[1,1-二甲基乙基]氨基]羰基]氨基]-3,3-二…

【C++笔试强训】第四天

🎇C笔试强训 博客主页:一起去看日落吗分享博主的C刷题日常,大家一起学习博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话:夜色难免微凉,前方必有曙光 🌞。 💦&a…

【Day28】力扣算法(超详细思路+注释) [1790. 仅执行一次字符串交换能否使两个字符串相等 ] [328. 奇偶链表 ][148. 排序链表]

刷题打卡,第 二十八 天题目一、1790. 仅执行一次字符串交换能否使两个字符串相等题目二、328. 奇偶链表题目三、148. 排序链表题目一、1790. 仅执行一次字符串交换能否使两个字符串相等 原题链接:1790. 仅执行一次字符串交换能否使两个字符串相等 题目…

消息队列的一些思考

前言 像我们Feign进行服务远程调用就会出现上述情况,服务调用是同步的,需要保证整个链路成功执行完才能成功下单,需要考虑网络抖动等影响,还有雪崩的现象——>同步通信会产生不稳定的影响导致用户体验较差 (41条消息) Dubbo_…

【前端笔试之输入输出问题汇总】系列1

1、题目1:涉及到new Array()以及map方面的一些特性 const array new Array(5).map((item) > {return item {name: 1} }) console.log(array)//[empty*5]一般我们认为会输出[name,name,name,name,name]。但是输出的却是empty。 因为new Array(5)生成的数组在每…

CAD导入Revit缺少东西原因-Revit中如何批量导出CAD图纸

一、CAD导入Revit缺少东西原因汇总 在Revit中导入CAD进行模型搭建是建模过程中常用的方法,但是有时会遇到导入的CAD缺少东西的情况,下面介绍几种导致这种问题的原因 1.CAD导入的时候,不是设置为全部可见。 CAD导入Revit中时,“图层…

护眼灯色温多少对眼睛好?推荐色温4000K暖白光的护眼灯

色温就是指温度的颜色,通常人眼所见的光线,由7中色光的光谱所组成,而护眼灯的光源越接近自然光就越好,一般要求色温在4000K左右比较合适,灯光为暖黄光,既温馨有符合相应的亮度,可以起到很好保护…

ROS2在ROS1 的基础的改进点

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、为什么要推出ROS2【重构ROS1】二、ROS1存在的问题三、ROS1与ROS2架构对比四、ROS2新概念例举五、ROS安装版本(…

【SpringCloud学习笔记】Feign

Feign 的使用 什么是Feign Feign是声明性的web服务客户端。它使编写web服务客户端更加容易,它封装类Ribbon和RestTemplate Feign vs OpenFeign 1、Feign是Netflix公司写的,是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端,是Spring…

C/C++里危险的宏(Macro)

#define SQUARE(x) x*x 上述宏定义SQUARE(x)用于求“参数”x的平方,这个宏很容易被使用者误认为是函数。宏是由预处理器处理的,它有着函数的形式却没有函数调用的代价。我们不建议初学者使用宏,因为使用宏的收益远不足以抵消其带给初学者的风…

基于本地存储LVM新建虚机方案

文章目录基于本地存储LVM新建虚机方案date: 2021/12/22auth: mmwei3一、环境信息如下:二、需求方案:1、虚机(卷启动)系统盘数据盘 三者在同一计算节点。2、虚机可以挂本计算节点的数据盘也可以挂载其他计算节点的数据盘。3、虚机可以使用本节点上的HDD做…

大数据必学Java基础(七十六):创建线程的三种方式

文章目录 创建线程的三种方式 一、继承Thread类 二、实现Runnable接口 三、实现Callable接口 创建线程的三种方式 一、继承Thread类 在学习多线程之前,以前的代码是单线程的吗? 不是,以前也是有三个线程同时执行的。 现在我想自己制造…

《单元测试》Junit5入门教程——非常详细,入门即精通

本文为在霍格沃兹测试开发学社中学习到的一些技术,写出来分享给大家,希望有志同道合的小伙伴可以一起交流技术,一起进步~ 单元测试-Junit5入门教程一、添加Junit5依赖二、Junit5 常用注解2.1、Test2.2、BeforeAll2.3、AfterAll2.4、BeforeEac…

JavaWeb学习5:Maven

Maven的学习为什么要学习这个技术?在javaweb开发中,需要使用大量的jar包,这种jar包需要手动的导入 如何让一个东西自动导入和配置jar包 所以Maven诞生了maven就是一个架构管理工具 1、Maven项目架构管理工具 Maven的核心思想:约定大于配置,有约束,不要去违反。 Maven会规…