数据挖掘算法原理与实践:决策树

第2关:决策树算法原理

任务描述

本关任务:根据本关所学知识,完成 calcInfoGain 函数。

相关知识

为了完成本关任务,你需要掌握:

  1. 信息熵;
  2. 条件熵;
  3. 信息增益。
信息熵

信息是个很抽象的概念。人们常常说信息很多,或者信息较少,但却很难说清楚信息到底有多少。比如一本五十万字的中文书到底有多少信息量。

直到1948年,香农提出了“信息熵”的概念,才解决了对信息的量化度量问题。信息熵这个词是香农从热力学中借用过来的。热力学中的热熵是表示分子状态混乱程度的物理量。香农用信息熵的概念来描述信源的不确定度。信源的不确定性越大,信息熵也越大

从机器学习的角度来看,信息熵表示的是信息量的期望值。如果数据集中的数据需要被分成多个类别,则信息量 I(xi​) 的定义如下(其中 xi​ 表示多个类别中的第 i 个类别,p(xi​) 数据集中类别为 xi​ 的数据在数据集中出现的概率表示):

I(Xi​)=−log2​p(xi​)

由于信息熵是信息量的期望值,所以信息熵 H(X) 的定义如下(其中 n 为数据集中类别的数量):

H(X)=−i=1∑n​p(xi​)log2​p(xi​)

从这个公式也可以看出,如果概率是 0 或者是 1 的时候,熵就是 0。(因为这种情况下随机变量的不确定性是最低的),那如果概率是 0.5 也就是五五开的时候,此时熵达到最大,也就是 1。(就像扔硬币,你永远都猜不透你下次扔到的是正面还是反面,所以它的不确定性非常高)。所以呢,熵越大,不确定性就越高

条件熵

在实际的场景中,我们可能需要研究数据集中某个特征等于某个值时的信息熵等于多少,这个时候就需要用到条件熵。条件熵 H(Y|X) 表示特征X为某个值的条件下,类别为Y的熵。条件熵的计算公式如下:

H(Y∣X)=i=1∑n​pi​H(Y∣X=xi​)

当然条件熵的一个性质也熵的性质一样,概率越确定,条件熵就越小,概率越五五开,条件熵就越大。

信息增益

现在已经知道了什么是熵,什么是条件熵。接下来就可以看看什么是信息增益了。所谓的信息增益就是表示我已知条件 X 后能得到信息 Y 的不确定性的减少程度。

就好比,我在玩读心术。你心里想一件东西,我来猜。我已开始什么都没问你,我要猜的话,肯定是瞎猜。这个时候我的熵就非常高。然后我接下来我会去试着问你是非题,当我问了是非题之后,我就能减小猜测你心中想到的东西的范围,这样其实就是减小了我的熵。那么我熵的减小程度就是我的信息增益。

所以信息增益如果套上机器学习的话就是,如果把特征 A 对训练集 D 的信息增益记为 g(D, A) 的话,那么 g(D, A) 的计算公式就是:

g(D,A)=H(D)−H(D,A)

为了更好的解释熵,条件熵,信息增益的计算过程,下面通过示例来描述。假设我现在有这一个数据集,第一列是编号,第二列是性别,第三列是活跃度,第四列是客户是否流失的标签(0: 表示未流失,1: 表示流失)。

编号性别活跃度是否流失
10
20
31
40
50
60
71
80
91
100
110
121
131
140
150

假如要算性别和活跃度这两个特征的信息增益的话,首先要先算总的熵和条件熵。总的熵其实非常好算,就是把标签作为随机变量 X。上表中标签只有两种(01)因此随机变量 X 的取值只有 0 或者 1。所以要计算熵就需要先分别计算标签为 0 的概率和标签为 1 的概率。从表中能看出标签为 0 的数据有 10 条,所以标签为 0 的概率等于 2/3。标签为 1 的概率为 1/3。所以熵为:

−(1/3)∗log(1/3)−(2/3)∗log(2/3)=0.9182

接下来就是条件熵的计算,以性别为男的熵为例。表格中性别为男的数据有 8 条,这 8 条数据中有 3 条数据的标签为 1,有 5 条数据的标签为 0。所以根据条件熵的计算公式能够得出该条件熵为:

−(3/8)∗log(3/8)−(5/8)∗log(5/8)=0.9543

根据上述的计算方法可知,总熵为:

−(5/15)∗log(5/15)−(10/15)∗log(10/15)=0.9182

性别为男的熵为:

−(3/8)∗log(3/8)−(5/8)∗log(5/8)=0.9543

性别为女的熵为:

−(2/7)∗log(2/7)−(5/7)∗log(5/7)=0.8631

活跃度为低的熵为:

−(4/4)∗log(4/4)−0=0

活跃度为中的熵为:

−(1/5)∗log(1/5)−(4/5)∗log(4/5)=0.7219

活跃度为高的熵为:

−0−(6/6)∗log(6/6)=0

现在有了总的熵和条件熵之后就能算出性别和活跃度这两个特征的信息增益了。

性别的信息增益=总的熵-(8/15)性别为男的熵-(7/15)性别为女的熵=0.0064

活跃度的信息增益=总的熵-(6/15)活跃度为高的熵-(5/15)活跃度为中的熵-(4/15)活跃度为低的熵=0.6776

那信息增益算出来之后有什么意义呢?回到读心术的问题,为了我能更加准确的猜出你心中所想,我肯定是问的问题越好就能猜得越准!换句话来说我肯定是要想出一个信息增益最大(减少不确定性程度最高)的问题来问你。其实 ID3 算法也是这么想的。ID3 算法的思想是从训练集 D 中计算每个特征的信息增益,然后看哪个最大就选哪个作为当前结点。然后继续重复刚刚的步骤来构建决策树。

编程要求

根据提示,在右侧编辑器 Begin-End 部分补充代码,完成 calcInfoGain 函数实现计算信息增益。

calcInfoGain函数中的参数:

  • feature:测试用例中字典里的feature,类型为ndarray
  • label:测试用例中字典里的label,类型为ndarray
  • index:测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。

测试说明

平台会对你编写的代码进行测试,期望您的代码根据输入来输出正确的信息增益,以下为其中一个测试用例:

测试输入: {'feature':[[0, 1], [1, 0], [1, 2], [0, 0], [1, 1]], 'label':[0, 1, 0, 0, 1], 'index': 0}

预期输出: 0.419973

提示: 计算 log 可以使用 NumPy 中的 log2 函数

代码:
import numpy as np# 计算信息熵
def calcInfoEntropy(feature, label):'''计算信息熵:param feature:数据集中的特征,类型为ndarray:param label:数据集中的标签,类型为ndarray:return:信息熵,类型float'''#*********** Begin ***********#label_set = set(label)#print("the type of label_set is: ",type(label_set))'''print( label_set){0, 1}{0}{0, 1}'''result=0#每个标签出现的概率,得出对应的p;[[0,3/5],[1,2/5],[0,3/5]...]for l in label_set:#遍历集合中的每一个元素count = 0for j in range(len(label)):#print(len(label))=5if label[j] == l:count += 1p = count/len(label)result+=-p*np.log2(p)#H(X)return result#*********** End *************## 计算条件熵
def calcHDA(feature, label, index, value):'''计算信息熵:param feature:数据集中的特征,类型为ndarray:param label:数据集中的标签,类型为ndarray:param index:需要使用的特征列索引,类型为int:param value:index所表示的特征列中需要考察的特征值,类型为int:return:信息熵,类型float'''#*********** Begin ***********#count = 0sub_feature = []#listsub_label = []#print(len(feature)):5#print(feature):[[0, 1], [1, 0], [1, 2], [0, 0], [1, 1]] 两列分别代表性别和活跃度for i in range(len(feature)):#i=0/1/2/3/4#print(feature[i][index]) 0 1 1 0 1if feature[i][index] == value:#若index=1,value=count += 1sub_feature.append(feature[i])#提取出符合特征的feature'''print(feature[i])[1, 0][1, 2][1, 1]'''sub_label.append(label[i])#提取出符合特征的feature的对应标签'''print(label[i])101'''pHA = count/len(feature)e = calcInfoEntropy(sub_feature,sub_label)return pHA*e    #*********** End *************#def calcInfoGain(feature, label, index):'''计算信息增益:param feature:测试用例中字典里的feature:param label:测试用例中字典里的label:param index:测试用例中字典里的index,即feature部分特征列的索引:return:信息增益,类型float'''#*********** Begin ***********#base_e = calcInfoEntropy(feature,label)#print("base_e= ",base_e):base_e=  0.5287712379549449f = np.array(feature)'''print(f)[[0 1][1 0][1 2][0 0][1 1]]'''f_set = set(f[:, index])#提取标签#print(f_set) :{0, 1}sum_HDA = 0for a in f_set:sum_HDA += calcHDA(feature, label, index, a)return base_e-sum_HDA#*********** End *************#

第3关:动手实现 ID3 决策树

任务描述

本关任务:补充 python 代码,完成 DecisionTree 类中的 fitpredict 函数。

相关知识

为了完成本关任务,你需要掌握:

  1. ID3 算法构造决策树的流程;
  2. 如何使用构造好的决策树进行预测。
ID3 算法构造决策树的流程

ID3 算法其实就是依据特征的信息增益来构建树的。其大致步骤就是从根结点开始,对结点计算所有可能的特征的信息增益,然后选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子结点,然后对子结点递归执行上述的步骤直到信息增益很小或者没有特征可以继续选择为止。

因此,ID3 算法伪代码如下:

 
  1. #假设数据集为D,标签集为A,需要构造的决策树为tree
  2. def ID3(D, A):
  3. if D中所有的标签都相同:
  4. return 标签
  5. if 样本中只有一个特征或者所有样本的特征都一样:
  6. 对D中所有的标签进行计数
  7. return 计数最高的标签
  8. 计算所有特征的信息增益
  9. 选出增益最大的特征作为最佳特征(best_feature)
  10. 将best_feature作为tree的根结点
  11. 得到best_feature在数据集中所有出现过的值的集合(value_set)
  12. for value in value_set:
  13. 从D中筛选出best_feature=value的子数据集(sub_feature)
  14. 从A中筛选出best_feature=value的子标签集(sub_label)
  15. #递归构造tree
  16. tree[best_feature][value] = ID3(sub_feature, sub_label)
  17. return tree
如何使用构造好的决策树进行预测

决策树的预测思想非常简单,假设现在已经构建出了一棵用来决策是否买西瓜的决策树。

并假设现在在水果店里有这样一个西瓜,其属性如下:

瓤是否够红够不够冰是否便宜是否有籽

那买不买这个西瓜呢?只需把西瓜的属性代入决策树即可。决策树的根结点是瓤是否够红,所以就看西瓜的属性,经查看发现够红,因此接下来就看够不够冰。而西瓜不够冰,那么看是否便宜。发现西瓜是便宜的,所以这个西瓜是可以买的。

因此使用决策树进行预测的伪代码也比较简单,伪代码如下:

 
  1. #tree表示决策树,feature表示测试数据
  2. def predict(tree, feature):
  3. if tree是叶子结点:
  4. return tree
  5. 根据feature中的特征值走入tree中对应的分支
  6. if 分支依然是课树:
  7. result = predict(分支, feature)
  8. return result

编程要求

根据提示,在右侧编辑器 Begin-End 部分补充代码, 填写 fit(self, feature, label) 函数,实现 ID3 算法,要求决策树保存在 self.tree 中。其中:

  • feature:训练集数据,类型为ndarray,数值全为整数
  • label:训练集标签,类型为ndarray,数值全为整数

填写 predict(self, feature) 函数,实现预测功能,并将标签返回,其中:

  • feature:测试集数据,类型为 ndarray,数值全为整数。(PS:feature中有多条数据)

测试说明

只需完成 fitpredict 函数即可,程序内部会调用您所完成的fit函数构建模型并调用 predict 函数来对数据进行预测。预测的准确率高于 0.92 视为过关。(PS:若 self.tree is None 则会打印决策树构建失败)

代码:
import numpy as np# 计算熵
def calcInfoEntropy(label):'''input:label(narray):样本标签output:InfoEntropy(float):熵'''label_set = set(label)InfoEntropy = 0for l in label_set:count = 0for j in range(len(label)):if label[j] == l:count += 1# 计算标签在数据集中出现的概率p = count / len(label)# 计算熵InfoEntropy -= p * np.log2(p)return InfoEntropy#计算条件熵
def calcHDA(feature,label,index,value):'''input:feature(ndarray):样本特征label(ndarray):样本标签index(int):需要使用的特征列索引value(int):index所表示的特征列中需要考察的特征值output:HDA(float):信息熵'''count = 0# sub_feature和sub_label表示根据特征列和特征值分割出的子数据集中的特征和标签sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][index] == value:count += 1sub_feature.append(feature[i])sub_label.append(label[i])pHA = count / len(feature)e = calcInfoEntropy(sub_label)HDA = pHA * ereturn HDA#计算信息增益
def calcInfoGain(feature, label, index):'''input:feature(ndarry):测试用例中字典里的featurelabel(ndarray):测试用例中字典里的labelindex(int):测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。output:InfoGain(float):信息增益'''base_e = calcInfoEntropy(label)f = np.array(feature)# 得到指定特征列的值的集合f_set = set(f[:, index])sum_HDA = 0# 计算条件熵for value in f_set:sum_HDA += calcHDA(feature, label, index, value)# 计算信息增益InfoGain = base_e - sum_HDAreturn InfoGain# 获得信息增益最高的特征
def getBestFeature(feature, label):'''input:feature(ndarray):样本特征label(ndarray):样本标签output:best_feature(int):信息增益最高的特征'''#*********Begin*********#max_infogain = 0best_feature = 0for i in range(len(feature[0])):infogain = calcInfoGain(feature, label, i)if infogain > max_infogain:max_infogain = infogainbest_feature = i#*********End*********#return best_feature#创建决策树
def createTree(feature, label):'''input:feature(ndarray):训练样本特征label(ndarray):训练样本标签output:tree(dict):决策树模型    '''#*********Begin*********## 样本里都是同一个label没必要继续分叉了if len(set(label)) == 1:return label[0]# 样本中只有一个特征或者所有样本的特征都一样的话就看哪个label的票数高if len(feature[0]) == 1 or len(np.unique(feature, axis=0)) == 1:vote = {}for l in label:if l in vote.keys():vote[l] += 1else:vote[l] = 1max_count = 0vote_label = Nonefor k, v in vote.items():if v > max_count:max_count = vvote_label = kreturn vote_label# 根据信息增益拿到特征的索引best_feature = getBestFeature(feature, label)tree = {best_feature: {}}f = np.array(feature)# 拿到bestfeature的所有特征值f_set = set(f[:, best_feature])# 构建对应特征值的子样本集sub_feature, sub_labelfor v in f_set:sub_feature = []sub_label = []for i in range(len(feature)):if feature[i][best_feature] == v:sub_feature.append(feature[i])sub_label.append(label[i])# 递归构建决策树tree[best_feature][v] = createTree(sub_feature, sub_label)#*********End*********#return tree#决策树分类
def dt_clf(train_feature,train_label,test_feature):'''input:train_feature(ndarray):训练样本特征train_label(ndarray):训练样本标签test_feature(ndarray):测试样本特征output:predict(ndarray):测试样本预测标签     '''#*********Begin*********#result = []tree = createTree(train_feature,train_label)def classify(tree, feature):if not isinstance(tree, dict):return treet_index, t_value = list(tree.items())[0]f_value = feature[t_index]if isinstance(t_value, dict):classLabel = classify(tree[t_index][f_value], feature)return classLabelelse:return t_valuefor feature in test_feature:result.append(classify(tree, feature))predict = np.array(result)#*********End*********#return predict

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

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

相关文章

源代码防泄露可以通过哪些方法实现?七种有效方法分享

在当今数字化时代,访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境,层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时,更需要一种综合的…

数据挖掘实战-基于深度学习RNN+CNN的能源价格预测模型

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

网络安全之交换基础

交换属于二层技术。路由器(router)是三层设备,可以基于IP地址转发,但需要路由表来记录。 交换机(switch)是二层设备,网桥(switch)也是二层设备,这两个都是基…

算法分析 KMP算法中next值的计算、0/1背包问题

5.6.1 KMP算法中next值的计算 设模式的长度为m。用蛮力法求解 KMP算法中的 next值时&#xff0c;next[0]可直接给出&#xff0c;计算next[j](1<j<m-1)则需要在 T[0] …T[j-1]中分别取长度为j-1、..、2、1的真前缀和真后缀并比较是否相等&#xff0c;最坏情况下的时间代价…

Flume+Hadoop:打造你的大数据处理流水线

引言 在大数据处理中&#xff0c;日志数据的采集是数据分析的第一步。Apache Flume是一个分布式、可靠且可用的系统&#xff0c;用于有效地收集、聚合和移动大量日志数据到集中式数据存储。本文将详细介绍如何使用Flume采集日志数据&#xff0c;并将其上传到Hadoop分布式文件系…

SG-8018CE晶体振荡器可编程规格书

SG-8018CE系列晶体振荡器是一个高性能、多功能且具有高度集成性的解决方案&#xff0c;它满足了现代电子系统的严格要求。其广泛的频率范围0.67 MHz到170 MHz&#xff0c;且频率调节精度达到1ppm&#xff0c;1.62 V至3.63V的宽广电源电压&#xff0c;使能&#xff08;OE&#x…

Codigger:Web应用赋能的分布式操作系统让用户卓越体验

Codigger&#xff0c;作为一个分布式操作系统&#xff0c;其独特之处在于其采用的浏览器/服务器&#xff08;Browser/Server&#xff0c;简称B/S&#xff09;架构。这种架构的核心思想是&#xff0c;通过浏览器来进入工作界面&#xff0c;页面交互部分事务逻辑在前端&#xff0…

2024------MySQL数据库基础知识点总结

-- 最好的选择不是最明智的&#xff0c;而是最勇敢的&#xff0c;最能体现我们真实意愿的选择。 MySQL数据库基础知识点总结 一、概念 数据库&#xff1a;DataBase&#xff0c;简称DB。按照一定格式存储数据的一些文件的组合顾名思义: 存储数据的仓库&#xff0c;实际上就是一…

汉王科技亮相世界数字健康论坛:以AI定义第四代血压计

作为科技行业的年度盛会&#xff0c;2024年中关村论坛年会于近日在北京揭幕。 作为中关村知名的人工智能企业&#xff0c;汉王科技携大模型的最新垂直应用、柯氏音法电子血压计等创新成果&#xff0c;在4月29日中关村论坛平行论坛“2024世界数字健康论坛”上亮相。 在《AI赋能血…

PE文件(四)FileBuffer-ImageBuffer作业

C语言实现如下功能 2.编写一个函数&#xff0c;将RVA的值转换成FOA 将文件加载到内存时&#xff0c;已知一个数据在内存中的地址&#xff0c;将此地址转化成文件在硬盘上时的相对于文件起始地址的文件偏移地址。即将虚拟内存偏移地址转换成文件偏移地址。 说明&#xff1a;这里…

安装nvm切换多个nodejs

今天实习&#xff0c;用到了公司的老项目vue2的&#xff0c;需要更换nodejs版本 我想直接安装一个16版本的&#xff0c;然后自己在webstrom中配置一下exe文件就可以了。 然而第一步就不行&#xff0c;在安装另一版本中显示 然后博主在这里介绍一下怎么使用nvm可以快速切换node…

ROS机械臂中Movelt!

Movelt!简介 一个易于集成使用的集成化开发平台 由一系列移动操作的功能包组成 1、运动规划 2、操作控制 3、3D感知 4、运动学 5、控制与导航算法 ....... 提供友好的GUI 可应用于工业、商业、研发和其他领域 ROS社区中使用度排名前三的功能包 Movelt!三大核心功能 …

成功案例(IF=7.3)| 转录组+蛋白质组+代谢组联合分析分析揭示胰腺癌中TAM2相关的糖酵解和丙酮酸代谢重构

研究背景 肿瘤的进展和发展需要癌细胞的代谢重编程&#xff0c;癌细胞能量代谢模式的改变可以满足快速增殖和适应肿瘤微环境的需要。肿瘤微环境&#xff08;TME&#xff09;中的代谢状态受到多种因素的影响&#xff0c;包括血管生成、与其他细胞的相互作用和系统代谢。代谢异质…

临时邮箱API发送邮件的安全性?如何保障?

临时邮箱API发送邮件的步骤有哪些&#xff1f;设置邮箱API方法&#xff1f; 电子邮件作为一种重要的通信方式&#xff0c;而临时邮箱API作为一种新兴的邮件发送技术&#xff0c;其安全性更是成为大家关注的焦点。那么&#xff0c;临时邮箱API发送邮件的安全性究竟如何呢&#…

doris经典bug

在部署完登录web页面查看的时候会发现只有一个节点可以读取信息剩余的节点什么也没读取到 在发现问题后&#xff0c;我们去对应的节点去看log日志&#xff0c;发现它自己绑定到前端的地址上了 现在我们已经发现问题了&#xff0c;以下就开始解决问题 重置doris 首先对be进行操…

IIoT:数据融合在工业物联网中的应用——青创智通

工业物联网解决方案-工业IOT-青创智通 随着科技的不断发展&#xff0c;工业物联网&#xff08;IIoT&#xff09;已经逐渐渗透到各个行业&#xff0c;为企业的生产和管理带来了前所未有的便利。 然而&#xff0c;与此同时&#xff0c;海量的数据也为企业带来了挑战。如何将这些…

宜选影票在线选座电影票小程序开发如何获取api接口?

要开发一个在线选座电影票小程序并获取API接口&#xff0c;你需要遵循几个关键步骤。以下是通常的流程&#xff1a; 明确需求和目标&#xff1a; 在开始之前&#xff0c;明确你的小程序需要哪些功能&#xff0c;例如电影查询、场次查询、在线选座、购票支付等。确定你需要从AP…

07_Flutter使用NestedScrollView+TabBarView滚动位置共享问题修复

07_Flutter使用NestedScrollViewTabBarView滚动位置共享问题修复 一.案发现场 可以看到&#xff0c;上图中三个列表的滑动位置共享了&#xff0c;滑动其中一个列表&#xff0c;会影响到另外两个&#xff0c;这显然不符合要求&#xff0c;先来看下布局&#xff0c;再说明产生这个…

5.7代码

1.环境治理 分析&#xff1a;最开始进入了一个误区&#xff0c;觉得都有通路了直接算通路就可以&#xff0c;后来才发现居然是最小路径的总和&#xff0c;所以大概是每减一次都要算一次各点之间的最小路径了&#xff0c;然后是循环&#xff0c;到需要的条件为止 总的来说思路不…

VMware 替代专题|14 个常见问题,解读 VMware 替代的方方面面

随着 VMware by Broadcom 调整订阅模式和产品组合&#xff0c;不少用户也将 VMware 替代提上日程。为了帮助用户顺利完成从 VMware 替代方案评估到产品落地的一系列环节&#xff0c;我们通过这篇博客&#xff0c;对 VMware 替代场景下用户经常遇到的问题进行了梳理和解答。 更…