决策树模型 - (ID3算法、C4.5算法) - Python代码实现

目录

算法简介

信息熵(Entropy)

信息增益(Information gain) - ID3算法

信息增益率(gain ratio) - C4.5算法

源数据

代码实现 - ID3算法

代码实现 - C4.5算法

画决策树代码-treePlotter


算法简介

决策数(Decision Tree)在机器学习中也是比较常见的一种算法,属于监督学习中的一种。其中ID3算法是以信息熵和信息增益作为衡量标准的分类算法。

信息熵(Entropy)

熵的概念主要是指信息的混乱程度,变量的不确定性越大,熵的值也就越大,熵的公式可以表示为:

信息增益(Information gain) - ID3算法

信息增益指的是根据特征划分数据前后熵的变化,可以用下面的公式表示: 

根据不同特征分类后熵的变化不同,信息增益也不同,信息增益越大,区分样本的能力越强,越具有代表性。 这是一种自顶向下的贪心策略,即在ID3中根据“最大信息增益”原则选择特征。

ID3采用信息增益来选择特征,存在一个缺点,它一般会优先选择有较多属性值的特征,因为属性值多的特征会有相对较大的信息增益。(这是因为:信息增益反映的给定一个条件以后不确定性减少的程度,必然是分得越细的数据集确定性更高,也就是条件熵越小,信息增益越大)。

信息增益率(gain ratio) - C4.5算法

为了避免ID3的不足,C4.5中是用信息增益率(gain ratio)来作为选择分支的准则。对于有较多属性值的特征,信息增益率的分母Split information(S,A),我们称之为分裂信息,会稀释掉它对特征选择的影响。分裂信息(公式1)和信息增益率(公式2)的计算如下所示。

                         

源数据

收入身高长相体型是否见面
一般
一般
一般一般一般一般
一般
一般

这是一位单身女性根据对方的一些基本条件,判断是否去约会的数据,此处展示前五行。我们要通过这位女士历史的数据建立决策树模型,使得尽量给这位女性推送她比较愿意约会的异性信息。

代码实现 - ID3算法

from math import log
import operator
import numpy as np
import pandas as pd
from pandas import DataFrame,Series# 计算数据的熵(entropy)-原始熵
def dataentropy(data, feat):  lendata=len(data)  # 数据条数labelCounts={} # 数据中不同类别的条数for featVec in data:category=featVec[-1] # 每行数据的最后一个字(叶子节点)if category not in labelCounts.keys():labelCounts[category]=0 labelCounts[category]+=1  # 统计有多少个类以及每个类的数量entropy=0for key in labelCounts:prob=float(labelCounts[key])/lendata # 计算单个类的熵值entropy-=prob*log(prob,2) # 累加每个类的熵值return entropy# 处理后导入数据数据
def Importdata(datafile): dataa = pd.read_excel(datafile)#datafile是excel文件,所以用read_excel,如果是csv文件则用read_csv#将文本中不可直接使用的文本变量替换成数字productDict={'高':1,'一般':2,'低':3, '帅':1,  '丑':3,  '胖':3,  '瘦':1,  '是':1,  '否':0}dataa['income'] = dataa['收入'].map(productDict)#将每一列中的数据按照字典规定的转化成数字dataa['hight'] = dataa['身高'].map(productDict)dataa['look'] = dataa['长相'].map(productDict)dataa['shape'] = dataa['体型'].map(productDict)dataa['is_meet'] = dataa['是否见面'].map(productDict)data = dataa.iloc[:,5:].values.tolist()#取量化后的几列,去掉文本列b = dataa.iloc[0:0,5:-1]labels = b.columns.values.tolist()#将标题中的值存入列表中return data,labels# 按某个特征value分类后的数据
def splitData(data,i,value): splitData=[]for featVec in data:if featVec[i]==value:rfv =featVec[:i]rfv.extend(featVec[i+1:])splitData.append(rfv)return splitData# 选择最优的分类特征
def BestSplit(data):  numFea = len(data[0])-1#计算一共有多少个特征,因为最后一列一般是分类结果,所以需要-1baseEnt = dataentropy(data,-1)   # 定义初始的熵,用于对比分类后信息增益的变化bestInfo = 0bestFeat = -1for i in range(numFea):featList = [rowdata[i] for rowdata in data]uniqueVals = set(featList)newEnt = 0for value in uniqueVals:subData = splitData(data,i,value)#获取按照特征value分类后的数据prob =len(subData)/float(len(data))newEnt +=prob*dataentropy(subData,i)  # 按特征分类后计算得到的熵info = baseEnt - newEnt  # 原始熵与按特征分类后的熵的差值,即信息增益if (info>bestInfo):   # 若按某特征划分后,若infoGain大于bestInf,则infoGain对应的特征分类区分样本的能力更强,更具有代表性。 bestInfo=info #将infoGain赋值给bestInf,如果出现比infoGain更大的信息增益,说明还有更好地特征分类bestFeat = i #将最大的信息增益对应的特征下标赋给bestFea,返回最佳分类特征return bestFeat #按分类后类别数量排序,取数量较大的
def majorityCnt(classList):    c_count={}for i in classList:if i not in c_count.keys():c_count[i]=0c_count[i]+=1ClassCount = sorted(c_count.items(),key=operator.itemgetter(1),reverse=True)#按照统计量降序排序return ClassCount[0][0]#reverse=True表示降序,因此取[0][0],即最大值#建树
def createTree(data,labels):classList = [rowdata[-1] for rowdata in data]  # 取每一行的最后一列,分类结果(1/0)if classList.count(classList[0])==len(classList):return classList[0]if len(data[0])==1:return majorityCnt(classList)bestFeat = BestSplit(data) #根据信息增益选择最优特征bestLab = labels[bestFeat]myTree = {bestLab:{}} #分类结果以字典形式保存del(labels[bestFeat])featValues = [rowdata[bestFeat] for rowdata in data]uniqueVals = set(featValues)for value in uniqueVals:subLabels = labels[:]myTree[bestLab][value] = createTree(splitData(data,bestFeat,value),subLabels)return myTreeif __name__=='__main__':datafile = u'E:\\pythondata\\tree.xlsx'#文件所在位置,u为防止路径中有中文名称data, labels=Importdata(datafile)  # 导入数据print(createTree(data, labels))  # 输出决策树模型结果

运行结果:

{'hight': {1: {'look': {1: {'income': {1: {'shape': {1: 1, 2: 1}}, 2: 1, 3: {'shape': {1: 1, 2: 0}}}}, 2: 1, 3: {'income': {1: 1, 2: 0}}}}, 2: {'income': {1: 1, 2: {'look': {1: 1, 2: 0}}, 3: 0}}, 3: {'look': {1: {'shape': {3: 0, 1: 1}}, 2: 0, 3: 0}}}}

对应的决策树:

代码实现 - C4.5算法

C4.5算法和ID3算法逻辑很相似,只是ID3算法是用信息增益来选择特征,而C4.5算法是用的信息增益率,因此对代码的影响也只有BestSplit(data)函数的定义部分,只需要加一个信息增益率的计算即可,BestSplit(data)函数定义代码更改后如下:

# 选择最优的分类特征
def BestSplit(data):  numFea = len(data[0])-1#计算一共有多少个特征,因为最后一列一般是分类结果,所以需要-1baseEnt = dataentropy(data,-1)   # 定义初始的熵,用于对比分类后信息增益的变化bestGainRate = 0bestFeat = -1for i in range(numFea):featList = [rowdata[i] for rowdata in data]uniqueVals = set(featList)newEnt = 0for value in uniqueVals:subData = splitData(data,i,value)#获取按照特征value分类后的数据prob =len(subData)/float(len(data))newEnt +=prob*dataentropy(subData,i)  # 按特征分类后计算得到的熵info = baseEnt - newEnt  # 原始熵与按特征分类后的熵的差值,即信息增益splitonfo = dataentropy(subData,i) #分裂信息if splitonfo == 0:#若特征值相同(eg:长相这一特征的值都是帅),即splitonfo和info均为0,则跳过该特征continueGainRate = info/splitonfo #计算信息增益率if (GainRate>bestGainRate):   # 若按某特征划分后,若infoGain大于bestInf,则infoGain对应的特征分类区分样本的能力更强,更具有代表性。 bestGainRate=GainRate #将infoGain赋值给bestInf,如果出现比infoGain更大的信息增益,说明还有更好地特征分类bestFeat = i #将最大的信息增益对应的特征下标赋给bestFea,返回最佳分类特征return bestFeat 

运行结果:

{'hight': {1: {'look': {1: {'income': {1: {'shape': {0: 0, 1: 1}}, 2: 1, 3: {'shape': {0: 0, 1: 1}}}}, 2: 1, 3: {'shape': {0: 0, 1: 1}}}}, 2: {'shape': {0: 0, 1: 1}}, 3: {'shape': {1: 0, 3: {'look': {0: 0, 1: 1}}}}}}

画决策树代码-treePlotter

决策树可以代码实现的,不需要按照运行结果一点一点手动画图。

import treePlotter
treePlotter.createPlot(myTree)

其中treePlotter模块是如下一段代码,可以保存为.py文件,放在Python/Lib/site-package目录下,然后用的时候import 【文件名】就可以了。

treePlotter模块代码:

#绘制决策树
import matplotlib.pyplot as plt# 定义文本框和箭头格式,boxstyle用于指定边框类型,color表示填充色
decisionNode = dict(boxstyle="round4", color='#ccccff')  #定义判断结点为圆角长方形,填充浅蓝色
leafNode = dict(boxstyle="circle", color='#66ff99')  #定义叶结点为圆形,填充绿色
arrow_args = dict(arrowstyle="<-", color='ffcc00')  #定义箭头及颜色#绘制带箭头的注释
def plotNode(nodeTxt, centerPt, parentPt, nodeType):createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction',xytext=centerPt, textcoords='axes fraction',va="center", ha="center", bbox=nodeType, arrowprops=arrow_args)#计算叶结点数
def getNumLeafs(myTree):numLeafs = 0firstStr = myTree.keys()[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':numLeafs += getNumLeafs(secondDict[key])else:numLeafs += 1return numLeafs#计算树的层数
def getTreeDepth(myTree):maxDepth = 0firstStr = myTree.keys()[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':thisDepth = 1 + getTreeDepth(secondDict[key])else:thisDepth = 1if thisDepth > maxDepth:maxDepth = thisDepthreturn maxDepth#在父子结点间填充文本信息
def plotMidText(cntrPt, parentPt, txtString):xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0]yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1]createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)def plotTree(myTree, parentPt, nodeTxt):numLeafs = getNumLeafs(myTree)depth = getTreeDepth(myTree)firstStr = myTree.keys()[0]cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW, plotTree.yOff)plotMidText(cntrPt, parentPt, nodeTxt)  #在父子结点间填充文本信息plotNode(firstStr, cntrPt, parentPt, decisionNode)  #绘制带箭头的注释secondDict = myTree[firstStr]plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalDfor key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':plotTree(secondDict[key], cntrPt, str(key))else:plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalWplotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalDdef createPlot(inTree):fig = plt.figure(1, facecolor='white')fig.clf()axprops = dict(xticks=[], yticks=[])createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)plotTree.totalW = float(getNumLeafs(inTree))plotTree.totalD = float(getTreeDepth(inTree))plotTree.xOff = -0.5 / plotTree.totalW;plotTree.yOff = 1.0;plotTree(inTree, (0.5, 1.0), '')plt.show()

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

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

相关文章

重复值处理 - 清洗 DataFrame 中的各种重复类型 - Python代码

目录 所有列是否完全重复 指定某一列是否重复 根据多列判断是否重复&#xff0c;防止误删数据 其他数据预处理方法 通过八爪鱼或者火车头等采集器从全网抓取的数据中&#xff0c;总会存在各种各样的重复数据&#xff0c;为保证数据在使用过程中的准确性&#xff0c;总要先进…

Silverlight带关闭动画的内容控件,可移动的内容控件(一)

本例给大家介绍两个自定义控件&#xff0c;一个有显示和关闭两种状态&#xff0c;在状态切换时有动画效果。另外一个是可以拖动的内容控件&#xff0c;可以制作能拖动的面板。 A&#xff0e;带关闭动画的内容控件。 .xaml View Code <ResourceDictionary xmlns"htt…

Autodesk云计算系列视频 --- 云计算与Civil 3D

前面的视频介绍了云计算与AutoCAD/Revit/Inventor的结合&#xff0c;这一节是云计算与Civil 3D的结合例子&#xff1a; 演示中使用的云计算程序源代码可以从下面链接下载&#xff1a; The sample code used in the demonstration is available here. 转载于:https://www.cnblo…

模型评价 - 机器学习与建模中怎么克服过拟合问题?

上一篇博客链接&#xff1a; 机器学习与建模中 - 判断数据模型拟合效果的三种方法 在上一篇博客中&#xff0c;我们谈到了使用损失函数来判断模型的拟合效果。但是拟合效果比较好的模型不一定是最好的模型&#xff0c;建模的最终目的是为了预测&#xff0c;因此预测最精准的模…

因子分析模型

主成分分析和因子分析 #包载入 library(corrplot) library(psych) library(GPArotation) library(nFactors) library(gplots) library(RColorBrewer)1234567 主成分分析 主成分分析&#xff08;PCA&#xff09;是对针对大量相关变量提取获得很少的一组不相关的变量&#xff…

因子分析模型 - 案例按步骤详解 - (SPSS建模)

一、SPSS中的因子分析。 步骤: &#xff08;1&#xff09;定义变量&#xff1a;x1-财政用于农业的支出的比重,x2-第二、三产业从业人数占全社会从业人数的比重&#xff0c;x3-非农村人口比重&#xff0c;x4-乡村从业人员占农村人口的比重&#xff0c;x5-农业总产值占农林牧总…

神经网络 - 用单层感知器实现多个神经元的分类 - (Matlab建模)

训练样本矩阵&#xff1a; P [0.1 0.7 0.8 0.8 1.0 0.3 0.0 –0.3 –0.5 –1.5; 1.2 1.8 1.6 0.6 0.8 0.5 0.2 0.8 –1.5 –1.3]; 训练样本对应的分类&#xff1a; T [1 1 1 0 0 1 1 1 0 0 ;0 0 0 0 0 1 1 1 1 1]; 用MATLAB实现分类&…

缺失值处理 - 定位空值并用空值的上一个值填充 - (Excel)

今天小助理很烦恼&#xff0c;说要处理一批汇率的数据&#xff0c;用近邻日期的汇率填充汇率为空的日期的汇率&#xff0c;这句话比较拗口&#xff0c;我们用数据解释一下。 比如下表&#xff0c;10月6日和10月8日9日的汇率没有采集到&#xff0c;那么我们就用10月5日的汇率填…

C#开发基础类库

下载地址&#xff1a;http://files.cnblogs.com/dashi/Sxmobi.rar转载于:https://www.cnblogs.com/dashi/archive/2011/09/09/2172506.html

因子分析模型 - 因子分析法原理与代码实现 -(Python,R)

因子分析基本思想 和主成分分析相似&#xff0c;首先从原理上说&#xff0c;主成分分析是试图寻找原有自变量的一个线性组合&#xff0c;取出对线性关系影响较大的原始数据&#xff0c;作为主要成分。 因子分析&#xff0c;是假设所有的自变量可以通过若干个因子&#xff08;中…

ACDSee Photo Manager 12 中文绿色版

用WinRAR解压即玩&#xff0c;无需安装。可以拷贝到USB硬盘&#xff0c;便于携带 凭借易于使用且速度极快的特点&#xff0c;ACDSee 12提供了整理相片、优化拍摄以及与亲朋好友分享往事所需的全部功能。 幻灯片浏览 支持幻灯片浏览图片&#xff0c;并支持背景音乐和多种多样的图…

排序算法 - 6种 - 超炫的动画演示 - Python实现

1.冒泡排序 思路&#xff1a;遍历列表&#xff0c;每一轮每次比较相邻两项&#xff0c;将无序的两项交换&#xff0c;下一轮遍历比前一轮比较次数减1。 def bubble_sort(a_list):for passnum in range(len(a_list)-1, 0, -1):for i in range(passnum):if a_list[i] > a_list…

因子分析模型 - Python 做因子分析简直比 SPSS 还简单 - ( Python、SPSS)

为什么&#xff1f; SPSS 那么简单还免费&#xff0c;为什么还要用 Python 做因子分析&#xff08;factor analysis&#xff09;呢&#xff1f;工作狗表示&#xff0c;建模的目的是要卖钱的&#xff0c;也就是要嵌入到公司开发的产品上去&#xff0c;用 Python 写因子分析&…

缺失值处理 - 拉格朗日插值法 - Python代码

目录 缺失值处理 拉格朗日差值法的理论基础 拉格朗日插值法代码实现 其他数据预处理方法 缺失值处理 处理缺失值常用的办法可分为三类&#xff1a;删除记录、数据插补、不处理。 其中常见的数据插补法有&#xff1a; 如果通过删除小部分的数据就可以达到既定的目标&#…

做po_requisitions_interface_all接口开发问题

po_requisitions_interface_all这个接口表的字段charge_account_id来源于: 1、组织参数的Material Account 2、工单类型的Outside Processing Account 转载于:https://www.cnblogs.com/songdavid/archive/2011/09/19/2181757.html

[Hands On ML] 3. 分类(MNIST手写数字预测)

文章目录1. 数据预览2. 数据集拆分3. 二分类4. 性能评估4.1 交叉验证4.2 准确率、召回率4.3 受试者工作特征&#xff08;ROC&#xff09;曲线5. 多分类6. 误差分析6.1 检查混淆矩阵本文为《机器学习实战&#xff1a;基于Scikit-Learn和TensorFlow》的读书笔记。 中文翻译参考 …

支持向量机 - 从原理到算法的实现

思想&#xff1a;寻找能够成功分开两类样本并且具有最大分类间隔的最优超平面。 1.原理解析 空间中任何一个平面的方程都可以表示为wxb 0,如上图&#xff0c;设最优超平面方程H为wxb0,支持向量x-到H的距离为,要使分类间隔最大&#xff0c;即该距离最大&#xff0c;而该距离只与…

Struts2初始化过程代码分析

根据web.xml的配置 调用FilterDispatcher.init(FilterConfig filterConfig) 1. 创建org.apache.struts2.Dispatcher&#xff0c;并调用init()方法 1.1. 创建com.opensymphony.xwork2.config.ConfigurationManager,其中属性List<ContainerProvider> containerProviders存放…

LeetCode 1292. 元素和小于等于阈值的正方形的最大边长(DP)

1. 题目 给你一个大小为 m x n 的矩阵 mat 和一个整数阈值 threshold。 请你返回元素总和小于或等于阈值的正方形区域的最大边长&#xff1b; 如果没有这样的正方形区域&#xff0c;则返回 0 。 示例 1&#xff1a; 输入&#xff1a;mat [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[…

从这十大算法开始学习机器学习与建模

本文介绍了机器学习新手需要了解的 10 大算法&#xff0c;包括线性回归、Logistic 回归、朴素贝叶斯、K 近邻算法等。 在机器学习中&#xff0c;有一种叫做「没有免费的午餐」的定理。简而言之&#xff0c;它指出没有任何一种算法对所有问题都有效&#xff0c;在监督学习&…