决策树(descision tree)

一:决策树的基础介绍

决策树(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=0for i in tarset:pi=np.sum(dataset[col] == i)/len(dataset)res=res-pi* log(pi, 2)return resdef ID3(dataset,fea):baseEnt = calShanEnt(dataset, "target")newEnt = 0value_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=-1for fea in features:gain=ID3(dataset,fea)if gain>bestInfoGain:bestInfoGain=gainbestFet=feaprint(set(dataset[bestFet]))print(bestInfoGain)return bestFetchooseBestFea(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.2630853587192754def chooseBestFea(dataset):features=[i for i in dataset.columns if i!='target']bestFet=features[0]bestInfoGain=-1for fea in features:gain=C4_5(dataset,fea)if gain>bestInfoGain:bestInfoGain=gainbestFet=feaprint(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=1for i in tarset:gini=gini-(np.sum(dataset[col] == i)/len(dataset))**2return giniGini(data,"target")
# 0.49826989619377154def CART(dataset,fea):value_set=set(dataset[fea])Gini_min= 100fea_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_indexfea_min=vreturn 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=1for fea in features:value_set=set(dataset[fea])gain,value_fea=CART(dataset,fea)if gain<bestInfoGain:bestInfoGain=gainbestFet=feabestFetFea=value_feareturn bestFet,bestFetFeachooseBestFea(data)
# ('纹理', '清晰')### 使用三种方法建立一个决策树import pandas as pd
from math import log
import numpy as npclass DT:def __init__(self, data, model):self.data = dataself.model = modeldef calShanEnt(self, dataset, col):tarset = set(dataset[col])res = 0for i in tarset:pi = np.sum(dataset[col] == i) / len(dataset)res = res - pi * log(pi, 2)return resdef ID3(self, dataset, fea):baseEnt = self.calShanEnt(dataset, "target")newEnt = 0value_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 - newEntdef C4_5(self, dataset, fea):gain = self.ID3(dataset, fea)IVa = self.calShanEnt(dataset, fea)return gain / IVadef Gini(self, dataset, col):tarset = set(dataset[col])gini = 1for i in tarset:gini = gini - (np.sum(dataset[col] == i) / len(dataset)) ** 2return ginidef CART(self, dataset, fea):value_set = set(dataset[fea])Gini_min = 100fea_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_indexfea_min = vreturn -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 = -1value_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 = gainbestFet = feabestFetFea = value_feareturn bestFet, bestFetFeadef 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.xdnf.cn/news/1559951.html

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

相关文章

PPT技巧:保护PPT文件的方法有哪些?

PPT文件制作好之后保证文件不出错应该是很重要的&#xff0c;毕竟是要拿出去展示的&#xff0c;今天分享PPT加密方法给大家。希望能够帮助大家保护好自己的PPT文件。 打开密码 如果想要其他人需要输入正确的密码才能够打开文件查看并编辑&#xff0c;我们可以给PPT文件设置打…

Android -- [SelfView] 自定义多色渐变背景板

Android – 自定义多色渐变背景板 前言&#xff1a; Android 自带的 xml 文件内 gradient 设置渐变最多只有三种颜色&#xff0c;使用方便但范围受限&#xff0c;不能很好满足各种需求&#xff1b; 本款多色渐变背景板应运而生&#xff1a;* 1. 支持圆角模式&#xff0c;矩形模…

二、IOC容器

文章目录 1. IOC的底层原理1.1 什么是IOC1.2 IOC 底层原理1.3 画图讲解 IOC 底层原理 2. IOC接口&#xff08;BeanFactory&#xff09;3. IOC 操作 Bean 管理&#xff08;概念&#xff09;3.1 什么是Bean管理3.2 Bean管理操作的两种方式 4. IOC操作 Bean 管理&#xff08;基于 …

【Redis】Set类型常用命令

目录 一. Set集合类型简介.二. 增加元素相关命令2.1 向集合中添加元素(sadd)2.2 从集合中移动元素( smove ) 三. 查询元素相关操作.3.1 查询集合中存在的所有元素.( smembers )3.2 查询集合中是否存在member( sismember ) 四. 随机获取集合中的元素4.1 随机获取集合中的n个元素…

基于单片机的穿戴式泳池遇险紧急呼救系统的设计

本计基于单片机的穿戴式泳池遇险紧急呼救系统装置。该装置采用STC12C5A60S2单片机与心率检测模块MAX30102的一体化脉冲血氧分析仪和心率监测器&#xff0c;对人体的心跳进行了实时检测。该装置由发送端和接收端两部分组成&#xff0c;中间由LORA无线通信模块进行数据传输&#…

C语言刷题 LeetCode 30天挑战 (十)Stack 栈 (MinStack)

这个题目要求你设计一个特殊的栈&#xff08;MinStack&#xff09;&#xff0c;不仅要具备普通栈的基本功能&#xff08;push、pop 和 top&#xff09;&#xff0c;还要能够在常数时间内&#xff08;O(1) 时间复杂度&#xff09;获取栈中的最小元素&#xff08;getMin&#xff…

curl执行报【先没有那个文件或目录】解决办法

开发微信发过了curl命令后&#xff0c;执行报错 是空格导致的&#xff0c;解决办法是打开下面网址重新输入空格即可 在线curl命令转代码 删除这个空格 重新输入空格

『网络游戏』服务器向客户端分发消息【20】

对服务器添加System引用 修改脚本&#xff1a;LoginSys.cs 修改脚本&#xff1a;NetSvc.cs 修改脚本&#xff1a;ServerSession.cs 修改脚本&#xff1a;GameMsg.cs 修改脚本&#xff1a;MsgPack.cs 修改脚本&#xff1a;LoginSys.cs 修改脚本&#xff1a;ServerRoot.cs 修改脚…

java随机生成数学算式

生成随机数学算式可谓是计算机领域的一个经典的问题, 本文使用JFrame,JButton,JTextField等java图形化工具,生成一个可以随机切换题目,可以实现计时功能的一个图形化界面 源代码展示 randomMath类 package login;import javax.swing.*; import java.awt.*; import java.awt.e…

运筹说 第126期 | 存储论经典例题讲解——随机存储模型

通过上一期&#xff0c;我们已经学习了确定型存储论模型在经济管理中的应用&#xff0c;但其忽略了现实中的随机性和不确定性因素&#xff0c;本期小编选择了一些考虑不确定因素的随机存储模型的典型例题&#xff0c;进行详细讲解。 单周期的随机型存储模型 单周期的随机型存储…

基于STM32的“Flash闪存”基础 及 “SD NAND Flash”测试例程

文章目录 一、“FLASH闪存”是什么&#xff1f; 简介 分类 特点 虚拟化 二、SD NAND Flash 概述 引脚分配 数据传输模式 SD NAND寄存器 通电图 参考设计 三、STM32测试例程 本篇除了对flash闪存进行简单介绍外&#xff0c;另给读者推荐一种我本人也在用的小容量闪…

STM32 USB CUBEMX

开发背景 使用的平台&#xff1a;STM32H750 注意事项 时钟必须是48MHZ&#xff0c;其它都不行 2. 将默认任务的堆栈设大一点 如果使用操作系统&#xff0c;USB任务跑在默认任务里&#xff0c;因此需要设置默认任务的堆栈缓存是直接定义的全局变量&#xff0c;需要设置编译器…

【windows Server 2012】把我的电脑放在桌面

WinR 打开命令输入框 输入 rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0

Vue+Vant实现7天日历展示,并在切换日期时实时变换

效果图&#xff1a; 主要使用 moment.js 插件完成 HTML部分 <div class"day-content"><div class"day-content-t"><div>{{ monthVal }}</div><div click"onCalendar()">更多>></div></div><…

月入8.3K,电子厂普工转行网优,每个人都可以是潜力股!

今天主人公只有22岁&#xff0c;大专学历&#xff0c;毕业之后一直在芯片厂从事流水线工作&#xff0c;枯燥烦闷的生活让他下定决心转行&#xff0c;目前收到一份薪资8300元的offer&#xff0c;让我们一起来看看他的故事~ 1 为什么选择网优行业&#xff1f; 大学我学的软件技术…

DAY6 面向对象

概念 对象是一种特殊的数据结构&#xff0c;可以用来记住一个事物的数据&#xff0c;从而代表该事物&#xff0c;可以理解为一个模板表&#xff0c;总而言之万物皆对象&#xff0c;比如一个人、一个物体等。 怎么创建对象 先设计对象的模板&#xff0c;也就是对象的设计图&a…

影视飓风全平台下架引思:录屏分辨率与码率科普及实用软件推荐

在影视飓风10月8日发布视频《清晰度不如4年前!视频变糊是你的错觉吗》后&#xff0c;引发了很多关于视频清晰度的讨论。 有知乎用户总结提出现在在线视频被降画质的几个点&#xff1a;一是原始视频上传到服务器就被压缩&#xff0c;虽分辨率看似不变&#xff0c;但如 H.265 等高…

【SQL】收入更高的员工

目录 语法 需求 示例 分析 代码 语法 FROM Employee a, Employee b 两个表之间笛卡尔积&#xff08;Cartesian product&#xff09;的形式&#xff0c;用了逗号分隔的连接&#xff08;comma-separated join&#xff09;&#xff0c;这是早期SQL语法中用于连接表的一种方式…

TikTok 伪装度分析:揭开社交媒体的真实面纱

在现代社交媒体中&#xff0c;TikTok凭借其短视频的形式和算法推荐的机制&#xff0c;迅速吸引了大量用户。然而&#xff0c;随着用户基数的扩大&#xff0c;平台上的内容呈现出多样化的趋势&#xff0c;而“伪装度”这一概念也逐渐成为我们分析TikTok内容质量和用户行为的重要…

SpringBoot使用esayExcel根据模板导出excel

1、依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.3</version></dependency> 2、模板 3、实体类 package com.skybird.iot.addons.productionManagement.qualityTesting…