决策树(descision tree)

news2024/12/24 18:44:19

一:决策树的基础介绍

决策树(descision tree)是一种基本的分类与回归的方法。决策树是一种对实例进行预测的树型结构。

下面是一个完整的二叉决策树,根据西瓜的几个特征判断西瓜的好坏。

纹理<=1.5代表第一个判断条件,根据纹理<=1.5是否小于1.5将整个样本集分为两边。

左边True代表左侧的所有的样本都满足判断条件,右侧False相反。

𝑔𝑖𝑛𝑖代表分类收获的提升(关于决策树分裂的算法,后续会介绍)。

samples=17代表样本的数量为17。value=[9,8]代表好瓜坏瓜的数量为9个和8个。

class=好瓜代表如果在该节点进行预测,那么预测的结构是好瓜。

通过树不断地分裂我们就可以得到一个完整决策树,然后就可以使用该决策树对西瓜的好坏进行预测啦

二、决策树的分裂算法

上面关于一个分类决策树的介绍中有关于决策树分裂的算法相信大家会有疑问。怎么进行分裂,为什么要这样进行分类,怎么选择特征分裂?常见的分类决策树分裂算法有:

1:信息增益

2:信息增益比

3:gini指数

1:信息增益

为了解释信息增益,我们先来介绍下熵与条件熵。在信息论中,熵(entropy)是表示随机变量不确定性的度量。假设Y是一个有限个值得离散随机变量,其概率分布为:

P(Y = y_i)=p_i

则随机变量Y的熵为:

H(Y)=-\sum_{i=1}^n{p_ilog{p_i}}

通常log的底我们会取2或者e。为了防止  $p_i=0$  ,我们定义0𝑙𝑜𝑔0=0。

从熵的定义中我们可以知道熵越大,那么随机变量的不确定性就越大:

0\leq H(Y)\leq log(n)

当随机变量Y的取值为0,1时,即只有2个类别。假设Y的分布为:

P(Y=1)=p, P(Y=0)=1-p , 其中:0\leq p \leq 1

此时随机变量Y的熵为:

H(Y) = -plog_2(p)-(1-p)log_2(1-p)

当𝑝越接近于0.5时,熵越大,反之熵越小。


上面时关于熵的介绍,下面我们介绍下条件熵:

假设有随机变量(X,Y),其联合概率分布为:

P(X=x_i,Y=y_j)=p_{ij}

条件熵𝐻(𝑌|𝑋)表示在已知随机变量𝑋的情况下随机变量𝑌的不确定性。其公式为:

P(Y|X)=\sum_{i=1}^n{p_iH(Y|X=x_i)}

这里$p_i=P(X=x_i)$

熵和条件熵都介绍完毕了,现在到我们的信息增益了。信息增益就是得知特征X的信息而使得Y的信息不确定性减少的程度。说人话就是当我们知道了特征X之后我们对Y预测的把握提升有多少。完整的定义如下:

特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵𝐻(𝐷|𝐴)之差,即:

g(D,A)=H(D)-H(D|A)

下面我们举个小例子用代码来计算信息增益。数据来自于西瓜书决策树章节

import pandas as pd
import numpy as np
from math import log
data=pd.read_csv(r"/home/mw/input/data2794/西瓜数据集.csv")
data.head()
色泽根蒂敲声纹理脐部触感target
0青绿蜷缩浊响清晰凹陷硬滑
1乌黑蜷缩沉闷清晰凹陷硬滑
2乌黑蜷缩浊响清晰凹陷硬滑
3青绿蜷缩沉闷清晰凹陷硬滑
4浅白蜷缩浊响清晰凹陷硬滑
def calShanEnt(dataset,col):
    tarset=set(dataset[col])
    res=0
    for i in tarset:
        pi=np.sum(dataset[col] == i)/len(dataset)
        res=res-pi* log(pi, 2)
    return res


def ID3(dataset,fea):
    baseEnt = calShanEnt(dataset, "target")
    newEnt = 0
    value_set=set(dataset[fea])
    for v in value_set:
        newEnt += np.sum(dataset[fea] == v) / len(dataset) * calShanEnt(dataset[dataset[fea] == v],"target")
    return baseEnt-newEnt
ID3(data,"根蒂")
# 0.14267495956679288

可以看到,在给定西瓜"根蒂"条件的基础上,信息增益为0.142


关于信息增益的介绍也已经介绍,该回到我们开始的环节了,怎么进行分裂,选择什么特征进行分裂

使用信息增益进行分裂时我们的特征选择方法是:对训练集(或者子集)D,计算其每个特征的信息增益,并且比较大小,选择信息增益最大的特征

方法也是很直接,既然给定每个特征都可以得到一个新增增益,那哪个特征的信息增益大,我们选择哪个特征不就好了?于是:

def chooseBestFea(dataset):
    features=[i for i in dataset.columns if i!='target']
    bestFet=features[0]
    bestInfoGain=-1
    for fea in features:
        gain=ID3(dataset,fea)
        if gain>bestInfoGain:
            bestInfoGain=gain
            bestFet=fea
    print(set(dataset[bestFet]))
    print(bestInfoGain)
    return bestFet


chooseBestFea(data)

'''
{'清晰', '模糊', '稍糊'}
0.3805918973682686
'纹理'
'''

可以看到,选择"纹理"进行分裂信息增益最大(0.38059189736826)。因此我们可以根据特征"纹理"将整个样本集分为三份,分别是"纹理=模糊","纹理=清晰","纹理=稍糊"

2:信息增益比

在使用信息增益的时候,可能存在这样一种情况,它的特征类别特别的多。(极端情况下,特征类别数量等于样本数据)。这种情况下,在该特征的情况下,信息增益变得很大,但是其实这种情况下,泛化能力会变低。考虑到这种情况,还有一种修正的方法,那就是信息增益比。

定义:

特征A对训练数据集D的信息增益比  $g_R(D,A)$  为信息增益g(D,A)与训练集D关于特征A的值的熵 H_A(D) 之比,即:

g_R(D,A)=\frac{g(D,A)}{H_A(D)}

其中, $H_A(D)=-\sum_{i=1}^n \frac{D_i}{D}log_2 \frac{D_i}{D}$   ,n是特征A取值的个数。可以看到当特征A越分散时HA(D)𝐻𝐴(𝐷)即特征A的熵越大。相对应的该特征就越不会被选择。

def C4_5(dataset,fea):
    gain=ID3(dataset,fea)
    IVa=calShanEnt(dataset,fea)
    return gain/IVa
C4_5(data,"纹理")
# 0.2630853587192754



def chooseBestFea(dataset):
    features=[i for i in dataset.columns if i!='target']
    bestFet=features[0]
    bestInfoGain=-1
    for fea in features:
        gain=C4_5(dataset,fea)
        if gain>bestInfoGain:
            bestInfoGain=gain
            bestFet=fea
    print(set(dataset[bestFet]))
    print(bestInfoGain)
    return bestFet
chooseBestFea(data)

'''
{'清晰', '模糊', '稍糊'}
0.2630853587192754
'纹理'
'''

可以看到采用这种方法来分裂,"纹理"还是最先分裂得特征。不过此时信息增益比为0.2630853

3:Gini指数(基尼指数)

除了上述得信息增益和信息增益比之外,还有一个别的常见分裂方法,那就是基尼指数。

定义:

分类问题中,假设有K个类,样本属于第k个类别得概率为  $p_k$  ,则概率分布得基尼指数为:

Gini(p)=\sum_{k=1}^K{p_k(1-p_k)}=1-\sum_{k=1}^K{p_k^2}

对于给定样本集合D,其基尼指数为:

Gini(p)=1-\sum_{k=1}^K({\frac{|C_k|}{|D|}})^2

其中  $C_K$  表示的是属于第𝑘类样本的集合,K是样本类别的个数。

如果样本集合D根据特征A是否取某一可能的值𝛼被分割成  $D_1$  和  $D_2$  两个部分,即:

D_1=\{(x,y)\in D|{A(x)=\alpha }\},D_2=D-D_1

则在特征A的条件下,集合D的基尼指数为:

Gini(D,A) = \frac{D_1}{D}Gini(D_1)+\frac{D_2}{D}Gini(D_2)

注:使用Gini指数指导一般只分裂为二叉树

与上面的两个方法相比,Gini指数进行分裂不仅要选择特征,而且要选择特征值。还是用代码来表示:

def Gini(dataset,col):
    tarset = set(dataset[col])
    gini=1
    for i in tarset:
        gini=gini-(np.sum(dataset[col] == i)/len(dataset))**2
    return gini



Gini(data,"target")
# 0.49826989619377154



def CART(dataset,fea):
    value_set=set(dataset[fea])
    Gini_min= 100
    fea_min=""
    for v in value_set:
        Gini_index=np.sum(dataset[fea] == v) / len(dataset) * Gini(dataset[dataset[fea] == v],"target")+ \
        np.sum(dataset[fea] != v) / len(dataset) * Gini(dataset[dataset[fea] != v],"target")
        if Gini_index<Gini_min:
            Gini_min=Gini_index
            fea_min=v
        
    return Gini_min,fea_min

使用"纹理"特征时,最优的分裂特征值为"清晰",可以通过该"纹理==清晰"和"纹理!=清晰"将样本分为两个区间

CART(data,"纹理")
# (0.28594771241830064, '清晰')



def chooseBestFea(dataset):
    features=[i for i in dataset.columns if i!='target']
    bestFet=features[0]
    bestFetFea=""
    bestInfoGain=1
    
    for fea in features:
        value_set=set(dataset[fea])
        gain,value_fea=CART(dataset,fea)
        if gain<bestInfoGain:
            bestInfoGain=gain
            bestFet=fea
            bestFetFea=value_fea
    return bestFet,bestFetFea


chooseBestFea(data)
# ('纹理', '清晰')



### 使用三种方法建立一个决策树

import pandas as pd
from math import log
import numpy as np

class DT:
    def __init__(self, data, model):
        self.data = data
        self.model = model

    def calShanEnt(self, dataset, col):
        tarset = set(dataset[col])
        res = 0
        for i in tarset:
            pi = np.sum(dataset[col] == i) / len(dataset)
            res = res - pi * log(pi, 2)
        return res

    def ID3(self, dataset, fea):
        baseEnt = self.calShanEnt(dataset, "target")
        newEnt = 0
        value_set = set(dataset[fea])
        for v in value_set:
            newEnt += np.sum(dataset[fea] == v) / len(dataset) * self.calShanEnt(dataset[dataset[fea] == v], "target")
        return baseEnt - newEnt

    def C4_5(self, dataset, fea):
        gain = self.ID3(dataset, fea)
        IVa = self.calShanEnt(dataset, fea)
        return gain / IVa

    def Gini(self, dataset, col):
        tarset = set(dataset[col])
        gini = 1
        for i in tarset:
            gini = gini - (np.sum(dataset[col] == i) / len(dataset)) ** 2
        return gini

    def CART(self, dataset, fea):
        value_set = set(dataset[fea])
        Gini_min = 100
        fea_min = ""
        for v in value_set:
            Gini_index = np.sum(dataset[fea] == v) / len(dataset) * self.Gini(dataset[dataset[fea] == v], "target") + \
                         np.sum(dataset[fea] != v) / len(dataset) * self.Gini(dataset[dataset[fea] != v], "target")
            if Gini_index < Gini_min:  # 越小越好
                Gini_min = Gini_index
                fea_min = v
        return -Gini_min, fea_min  ##由于另外连个方法都是最大的值进行分裂,而Gini指数是最小,因此取负数,这样-Gini_min越大越好

    def chooseBestFea(self, dataset):
        features = [i for i in dataset.columns if i != 'target']
        bestFet = features[0]
        bestFetFea = ""
        bestInfoGain = -1
        value_fea = ""
        for fea in features:
            if self.model == "C4_5":
                gain = self.C4_5(dataset, fea)
            elif self.model == "ID3":
                gain = self.ID3(dataset, fea)
            elif self.model == "CART":
                gain, value_fea = self.CART(dataset, fea)
            else:
                raise ("输入的model值之只能是:C4_5,ID3,CART,但是实际输入的值为:", self.model)
            if gain > bestInfoGain:
                bestInfoGain = gain
                bestFet = fea
                bestFetFea = value_fea
        return bestFet, bestFetFea

    def creatTree(self, dataset):
        if len(dataset.columns) == 1:
            return dataset['target'].value_counts().index[0]
        if len(set(dataset['target'])) == 1:
            return list(dataset['target'])[0]
        bestFea, bestFetFea = self.chooseBestFea(dataset)
        myTree = {bestFea: {}}
        if bestFetFea == "":
            for i in set(dataset[bestFea]):
                new_data = dataset[dataset[bestFea] == i].reset_index(drop=True)
                myTree[bestFea][i] = self.creatTree(new_data)
        else:
            new_data = dataset[dataset[bestFea] == bestFetFea].reset_index(drop=True)
            myTree[bestFea][bestFetFea] = self.creatTree(new_data)
            new_data2 = dataset[dataset[bestFea] != bestFetFea].reset_index(drop=True)
            myTree[bestFea]["不等于" + bestFetFea] = self.creatTree(new_data2)

        return myTree
data_path=r"../input/data2794"
data = pd.read_csv(r"../input/data2794"+"/西瓜数据集.csv")    
model = DT(data, "CART")
tree=model.creatTree(data)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JDK17 | 16】Java 17 深入剖析:密封类(二)

一、密封类的使用场景和优势 什么是密封类&#xff1f; 密封类&#xff08;sealed class&#xff09;是 Java 17 引入的一种新特性&#xff0c;允许开发者控制哪些类可以继承或实现某个类或接口。通过使用密封类&#xff0c;开发者可以定义一组特定的子类&#xff0c;从而提供…

【springboot9733】基于springboot+vue的藏区特产销售平台

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 “互联网”的战略实施后&#xff0c;很多行业的信息化水…

好用的AI工具

目录 1.常用AI工具 1.1.语音助手 1.1.1. 华为小艺 1.1.2. 小米小爱同学 1.2.智能客服 1.2.1. 银行客服 1.2.2. 酒店语音电话 1.3.编程助手 1.3.1. 百度Comate 1.3.2. 华为CodeArts 2.创新AI应用 2.1. 生成式AI 2.2. 自动驾驶技术 2.3. 医疗AI 2.4. 智能客服机器…

简单的maven nexus私服学习

简单的maven nexus私服学习 1.需求 我们现在使用的maven私服是之前同事搭建的&#xff0c;是在公司的一台windows电脑上面&#xff0c;如果出问题会比较难搞&#xff0c;所以现在想将私服迁移到我们公司的测试服务器上&#xff0c;此处简单了解一下私服的一些配置记录一下&am…

conda新建环境中存在大量ros相关python包

1 问题现象 新建的conda环境&#xff0c;执行pip list&#xff0c;出现了大量的ros相关包&#xff0c;环境不纯净。重新安装anaconda没有用。 2 问题原因 2.1 执行python -m site 执行python -m site获得以下结果 其中sys.path包含了’/opt/ros/noetic/lib/python3/dist-…

想要项目顺利进行,企业如何做好节点计划管理?

项目的成功实施对于企业的发展和竞争力提升至关重要。然而&#xff0c;要确保项目顺利进行并非易事&#xff0c;其中做好节点计划管理是关键所在。一个精心策划和有效执行的节点计划&#xff0c;能够为项目的推进提供清晰的路线图&#xff0c;帮助企业合理分配资源、控制进度、…

VR虚拟场景:重塑沉浸式购物体验的新篇章

在科技日新月异的今天&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正以前所未有的速度改变着我们的生活方式&#xff0c;特别是在消费领域&#xff0c;它正引领着一场前所未有的购物体验革命。通过构建高度逼真的虚拟场景&#xff0c;VR技术为消费者打造了一个超越现实…

修改 antd a-popover气泡卡片弹窗背景颜色

antdv 中 a-popover 样式修改不生效的问题 因为 popover 元素添加到了 body 下面&#xff0c;增加下面这几行代码&#xff0c;将 popover 添加到它原本的父级下面&#xff0c;然后用 ::v-deep 去修改样式就可以 1.效果图 2.代码 主要的代码就是 :getPopupContainer"(tri…

【笔记】Day2.4表设计说明

主键ID一般使用bigint类型 运送类型 使用比int更小的tinyint类型 eg&#xff1a;普快代表1 特快代表2&#xff08;没写反&#xff09; 关联城市 varchar 2代表京津冀 3代表江浙沪 4代表川渝 首重和续重都有小数点 故使用double 轻抛系数都为整数 故使用int 创建时间和修改…

Perforce静态分析工具2024.2新增功能:Helix QAC全新CI/CD集成支持、Klocwork分析引擎改进和安全增强

Perforce Helix QAC和Klocwork的最新版本对静态分析工具进行了重大改进&#xff0c;通过尽早修复错误、降低开发成本和加快发布速度&#xff0c;使开发团队实现左移。 本文中&#xff0c;我们将概述2024.2版本的新特性和新功能。 CI/CD和左移以实现持续合规性 现代软件开发实…

《Programming from the Ground Up》阅读笔记:p217-p238

《Programming from the Ground Up》学习第11天&#xff0c;p217-p238总结&#xff0c;总计22页。 一、技术总结 1.C compiling p216, C compiling is split into two stages - the preprocessor and the main compiler。 注&#xff1a;感觉这个写法不好&#xff0c;因为p…

开源AI智能名片链动2+1模式S2B2C商城小程序源码与工业4.0的融合发展:机遇与挑战

摘要&#xff1a;本文探讨了工业4.0的三大主题&#xff0c;即智能工厂、智能生产和智能物流&#xff0c;分析在各主题下开源AI智能名片链动21模式S2B2C商城小程序源码与之融合的可能性、带来的机遇以及面临的挑战&#xff0c;旨在为相关产业的协同发展提供理论参考。 一、引言 …

计算机网络:计算机网络概述 —— 描述计算机网络的参数

文章目录 数据量性能指标速率带宽数据传输速率 吞吐量时延分析时延问题 时延带宽积往返时间利用率丢包率丢包的情况 抖动可用性可靠性安全性 计算机网络是现代信息社会的基础设施&#xff0c;其性能和可靠性对各类应用至关重要。为了理解和优化计算机网络&#xff0c;我们需要深…

uniapp学习(004-1 组件 Part.2生命周期)

零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战&#xff0c;开发打包微信小程序、抖音小程序、H5、安卓APP客户端等 总时长 23:40:00 共116P 此文章包含第31p-第p35的内容 文章目录 组件生命周期我们主要使用的三种生命周期setup(创建组件时执行)不可以操作dom节点…

手撕数据结构 —— 单链表(C语言讲解)

目录 1.为什么要有链表 2.什么是链表 3.链表的分类 4.无头单向非循环链表的实现 SList.h中接口总览 具体实现 链表节点的定义 打印链表 申请结点 尾插 头插 尾删 头删 查找 在pos位置之前插入 在pos位置之后插入 删除pos位置 删除pos位置之后的值 5.完整代码…

把自己的代码安装到系统环境中/conda环境

1. 安装setuptools库 2. 创建一个如下的setup.py程序 # codingutf-8 from setuptools import setupsetup(author"zata",description"This is a nir analyse api, writen by zata", ### 一句话概括一下name"nirapi", ### 给你的包取一个名字…

小熊猫C/C++的安装使用及配置教程

文章目录 软件介绍小熊猫C下载地址安装下载完得到可执行文件选择语言阅读协议接受条款组件默认即可最好不要占用系统盘 配置-使用打开会选择主题和默认语言创建项目创建源文件编译及运行 软件介绍 小熊猫C是一个简单易用的集成开发环境(IDE)。 学校里几乎用的都是Dev C这种轻量…

【数学分析笔记】第5章第1节 微分中值定理(1)

5. 微分中值定理及其应用 5.1 微分中值定理 5.1.1 极值与极值点 【定义5.1.1】 f ( x ) f(x) f(x)定义域为 ( a , b ) (a,b) (a,b)&#xff0c; x 0 ∈ ( a , b ) x_0\in(a,b) x0​∈(a,b)&#xff0c;若 ∃ O ( x 0 , ρ ) ⊂ ( a , b ) \exists O(x_0,\rho)\subset(a,b) ∃…

自动猫砂盆“智商税”还是“真香”?2024自动猫砂盆保姆级干货

平时忙着上班&#xff0c;或者一遇到出差就要离家四五天&#xff0c;没办法给毛孩子的猫砂盆铲屎&#xff0c;导致粪便堆积太久。很多铲屎官也了解到有自动猫砂盆这种东西&#xff0c;但是生怕是智商税&#xff0c;总觉得忍忍手铲也可以&#xff0c;要知道&#xff0c;猫咪的便…

众数信科 AI智能体政务服务解决方案——寻知智能笔录系统

政务服务解决方案 寻知智能笔录方案 融合民警口供录入与笔录生成需求 2分钟内生成笔录并提醒错漏 助办案人员二次询问 提升笔录质量和效率 寻知智能笔录系统 众数信科AI智能体 产品亮点 分析、理解行业知识和校验规则 AI实时提醒用户文书需注意部分 全文校验格式、内容…