决策树的python实现

决策树的Python实现

2017-04-07 Anne Python技术博文

前言:

决策树的一个重要的任务 是为了理解数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集合,并从中提取出一系列规则,这些机器根据数据集创建规则的过程,就是机器学习的过程。

决策树优点:

1:计算复杂度不高

2:输出结果易于理解

3:对中间值的缺失不敏感

4:可以处理不相关特征数据

缺点:可能会产生过度匹配问题

使用数据类型:数值型和标称型

基于Python逐步实现Decision Tree(决策树),分为以下几个步骤:

  • 加载数据集
  • 熵的计算
  • 根据最佳分割feature进行数据分割
  • 根据最大信息增益选择最佳分割feature
  • 递归构建决策树
  • 样本分类

1.加载数据集

  1. from numpy import *
  2. #load "iris.data" to workspace
  3. traindata = loadtxt("D:\ZJU_Projects\machine learning\ML_Action\Dataset\Iris.data",delimiter = ‘,‘,usecols = (0,1,2,3),dtype = float)
  4. trainlabel = loadtxt("D:\ZJU_Projects\machine learning\ML_Action\Dataset\Iris.data",delimiter = ‘,‘,usecols = (range(4,5)),dtype = str)
  5. feaname = ["#0","#1","#2","#3"] # feature names of the 4 attributes (features)

2. 熵的计算

entropy是香农提出来的(信息论大牛),定义见wiki

注意这里的entropy是H(C|X=xi)而非H(C|X), H(C|X)的计算见第下一个点,还要乘以概率加和

Code:

  1. from math import log
  2. def calentropy(label):
  3. n = label.size # the number of samples
  4. #print n
  5. count = {} #create dictionary "count"
  6. for curlabel in label:
  7. if curlabel not in count.keys():
  8. count[curlabel] = 0
  9. count[curlabel] += 1
  10. entropy = 0
  11. #print count
  12. for key in count:
  13. pxi = float(count[key])/n #notice transfering to float first
  14. entropy -= pxi*log(pxi,2)
  15. return entropy
  16. #testcode:
  17. #x = calentropy(trainlabel)

3. 根据最佳分割feature进行数据分割

假定我们已经得到了最佳分割feature,在这里进行分割(最佳feature为splitfea_idx)

第二个函数idx2data是根据splitdata得到的分割数据的两个index集合返回datal (samples less than pivot), datag(samples greater than pivot), labell, labelg。 这里我们根据所选特征的平均值作为pivot

Code:

  1. #split the dataset according to label "splitfea_idx"
  2. def splitdata(oridata,splitfea_idx):
  3. arg = args[splitfea_idx] #get the average over all dimensions
  4. idx_less = [] #create new list including data with feature less than pivot
  5. idx_greater = [] #includes entries with feature greater than pivot
  6. n = len(oridata)
  7. for idx in range(n):
  8. d = oridata[idx]
  9. if d[splitfea_idx] < arg:
  10. #add the newentry into newdata_less set
  11. idx_less.append(idx)
  12. else:
  13. idx_greater.append(idx)
  14. return idx_less,idx_greater
  15. #testcode:2
  16. #idx_less,idx_greater = splitdata(traindata,2)
  17. #give the data and labels according to index
  18. def idx2data(oridata,label,splitidx,fea_idx):
  19. idxl = splitidx[0] #split_less_indices
  20. idxg = splitidx[1] #split_greater_indices
  21. datal = []
  22. datag = []
  23. labell = []
  24. labelg = []
  25. for i in idxl:
  26. datal.append(append(oridata[i][:fea_idx],oridata[i][fea_idx+1:]))
  27. for i in idxg:
  28. datag.append(append(oridata[i][:fea_idx],oridata[i][fea_idx+1:]))
  29. labell = label[idxl]
  30. labelg = label[idxg]
  31. return datal,datag,labell,labelg

这里args是参数,决定分裂节点的阈值(每个参数对应一个feature,大于该值分到>branch,小于该值分到<branch),我们可以定义如下:

  1. args = mean(traindata,axis = 0)

测试:按特征2进行分类,得到的less和greater set of indices分别为:

也就是按args[2]进行样本集分割,<和>args[2]的branch分别有57和93个样本。

4. 根据最大信息增益选择最佳分割feature

信息增益为代码中的info_gain, 注释中是熵的计算

Code:

  1. #select the best branch to split
  2. def choosebest_splitnode(oridata,label):
  3. n_fea = len(oridata[0])
  4. n = len(label)
  5. base_entropy = calentropy(label)
  6. best_gain = -1
  7. for fea_i in range(n_fea): #calculate entropy under each splitting feature
  8. cur_entropy = 0
  9. idxset_less,idxset_greater = splitdata(oridata,fea_i)
  10. prob_less = float(len(idxset_less))/n
  11. prob_greater = float(len(idxset_greater))/n
  12. #entropy(value|X) = \sum{p(xi)*entropy(value|X=xi)}
  13. cur_entropy += prob_less*calentropy(label[idxset_less])
  14. cur_entropy += prob_greater * calentropy(label[idxset_greater])
  15. info_gain = base_entropy - cur_entropy #notice gain is before minus after
  16. if(info_gain>best_gain):
  17. best_gain = info_gain
  18. best_idx = fea_i
  19. return best_idx
  20. #testcode:
  21. #x = choosebest_splitnode(traindata,trainlabel)

这里的测试针对所有数据,分裂一次选择哪个特征呢?

5. 递归构建决策树

详见code注释,buildtree递归地构建树。

递归终止条件:

①该branch内没有样本(subset为空) or

②分割出的所有样本属于同一类 or

③由于每次分割消耗一个feature,当没有feature的时候停止递归,返回当前样本集中大多数sample的label

  1. #create the decision tree based on information gain
  2. def buildtree(oridata, label):
  3. if label.size==0: #if no samples belong to this branch
  4. return "NULL"
  5. listlabel = label.tolist()
  6. #stop when all samples in this subset belongs to one class
  7. if listlabel.count(label[0])==label.size:
  8. return label[0]
  9. #return the majority of samples‘ label in this subset if no extra features avaliable
  10. if len(feanamecopy)==0:
  11. cnt = {}
  12. for cur_l in label:
  13. if cur_l not in cnt.keys():
  14. cnt[cur_l] = 0
  15. cnt[cur_l] += 1
  16. maxx = -1
  17. for keys in cnt:
  18. if maxx < cnt[keys]:
  19. maxx = cnt[keys]
  20. maxkey = keys
  21. return maxkey
  22. bestsplit_fea = choosebest_splitnode(oridata,label) #get the best splitting feature
  23. print bestsplit_fea,len(oridata[0])
  24. cur_feaname = feanamecopy[bestsplit_fea] # add the feature name to dictionary
  25. print cur_feaname
  26. nodedict = {cur_feaname:{}}
  27. del(feanamecopy[bestsplit_fea]) #delete current feature from feaname
  28. split_idx = splitdata(oridata,bestsplit_fea) #split_idx: the split index for both less and greater
  29. data_less,data_greater,label_less,label_greater = idx2data(oridata,label,split_idx,bestsplit_fea)
  30. #build the tree recursively, the left and right tree are the "<" and ">" branch, respectively
  31. nodedict[cur_feaname]["<"] = buildtree(data_less,label_less)
  32. nodedict[cur_feaname][">"] = buildtree(data_greater,label_greater)
  33. return nodedict
  34. #testcode:
  35. #mytree = buildtree(traindata,trainlabel)
  36. #print mytree

Result:

mytree就是我们的结果,#1表示当前使用第一个feature做分割,‘<‘和‘>‘分别对应less 和 greater的数据。

6. 样本分类

根据构建出的mytree进行分类,递归走分支

  1. #classify a new sample
  2. def classify(mytree,testdata):
  3. if type(mytree).__name__ != ‘dict‘:
  4. return mytree
  5. fea_name = mytree.keys()[0] #get the name of first feature
  6. fea_idx = feaname.index(fea_name) #the index of feature ‘fea_name‘
  7. val = testdata[fea_idx]
  8. nextbranch = mytree[fea_name]
  9. #judge the current value > or < the pivot (average)
  10. if val>args[fea_idx]:
  11. nextbranch = nextbranch[">"]
  12. else:
  13. nextbranch = nextbranch["<"]
  14. return classify(nextbranch,testdata)
  15. #testcode
  16. tt = traindata[0]
  17. x = classify(mytree,tt)
  18. print x

Result:

为了验证代码准确性,我们换一下args参数,把它们都设成0(很小)

args = [0,0,0,0]

建树和分类的结果如下:

可见没有小于pivot(0)的项,于是dict中每个<的key对应的value都为空。

微信扫一扫
关注该公众号

时间: 2024-10-06 00:31:04

决策树的python实现的相关文章

【Python】决策树的python实现

[Python]决策树的python实现 2016-12-08 数据分析师Nieson 1. 决策树是什么? 简单地理解,就是根据一些 feature 进行分类,每个节点提一个问题,通过判断,将数据分为几类,再继续提问.这些问题是根据已有数据学习出来的,再投入新数据的时候,就可以根据这棵树上的问题,将数据划分到合适的叶子上. 2. 决策树有什么算法? 常用的几种决策树算法有ID3.C4.5.CART: ID3:选择信息熵增益最大的feature作为node,实现对数据的归纳分类. C4.5:是I

【机器学习笔记之二】决策树的python实现

本文结构: 是什么? 有什么算法? 数学原理? 编码实现算法? 1. 是什么? 简单地理解,就是根据一些 feature 进行分类,每个节点提一个问题,通过判断,将数据分为几类,再继续提问.这些问题是根据已有数据学习出来的,再投入新数据的时候,就可以根据这棵树上的问题,将数据划分到合适的叶子上. 2. 有什么算法? 常用的几种决策树算法有ID3.C4.5.CART: ID3:选择信息熵增益最大的feature作为node,实现对数据的归纳分类.C4.5:是ID3的一个改进,比ID3准确率高且快,

机器学习-决策树实现-python

今天翻自己的书库的时候,才发现了之前买的一本<机器学习导论>.随手翻了翻,就直接看到了之前看到的决策树实现的问题理论. 闲来无事,也就得写点代码来play 一下: 决策树的概念想必大家都十分熟悉,特别想我们小时候玩的跳方格的游戏.或者说我们之前玩的你猜我猜的游戏,猜不对继续猜,总有一天你会猜对额 为了确定从哪一个特征来进行判别,我们需要一个衡量标准来分类. 1…香农熵 2…信息增益 那我们来实现第一个……香农熵 from math import log def calcShannonEnt(d

《机器学习实战》学习笔记:决策树的实现

决策树是个极其易懂的算法,也是最常用的数据挖掘算法,决策树允许机器根据数据集创造规则,其实这就是机器学习的过程.专家系统中经常会使用到决策树及其变种,而且决策树给出的结果往往可以匹敌在当前领域具有几十年工作经验的专家. 优点:决策树的计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据: 缺点:可能会产生过度匹配的问题: 适用数据类型:数值型和标称型. 这一章节的主要任务是讨论决策树的方法,以及编写构造决策树的python代码,使用递归调用建立分类器,最后可使用Matp

Python 和 R 数据分析/挖掘工具互查

如果大家已经熟悉python和R的模块/包载入方式,那下面的表查找起来相对方便.python在下表中以模块.的方式引用,部分模块并非原生模块,请使用 pip install * 安装:同理,为了方便索引,R中也以::表示了函数以及函数所在包的名字,如果不含::表示为R的默认包中就有,如含::,请使用 install.packages("*") 安装. 连接器与io 数据库 类别 Python R MySQL mysql-connector-python(官方) RMySQL Oracl

《机器学习》(周志华)第4章 决策树 笔记 理论及实现——“西瓜树”

参考书籍:<机器学习>(周志华) 说       明:本篇内容为读书笔记,主要参考教材为<机器学习>(周志华).详细内容请参阅书籍——第4章 决策树.部分内容参考网络资源,在此感谢所有原创者的工作. ================================================================= 第一部分 理论基础 1. 纯度(purity) 对于一个分支结点,如果该结点所包含的样本都属于同一类,那么它的纯度为1,而我们总是希望纯度越高越好,也就是

《机器学习实战》-决策树

目录 决策树 决策树简介 决策树的构造 信息增益 划分数据集 递归构建决策树 在 Python 中使用 Matplotlib 注解绘制树形图 Matplotlib 注解 构造注解树 测试和存储分类器 测试算法:使用决策树执行分类 使用算法:决策树的存储 示例:使用决策树预测隐形眼镜类型 总结 决策树 决策树简介 在数据集中度量一致性 使用递归构造决策树 使用 Matplotlib 绘制树形图 决策树简介 让我们来玩一个游戏,你现在在你的脑海里想好某个事物,你的同桌向你提问,但是只允许问你20个问

机器学习直接放弃

机器学习 人工智能(机器学习)学习之路推荐 机器学习 GBDT+xgboost 决策树提升 Python Matplotlib.pyplot plt 中文显示 机器学习基础 基本术语 <机器学习>西瓜书 课后习题参考答案 debugging-- 原文地址:https://www.cnblogs.com/nickchen121/p/10802091.html

决策树ID3算法预测隐形眼睛类型--python实现

本节讲解如何预测患者需要佩戴的隐形眼镜类型. 1.使用决策树预测隐形眼镜类型的一般流程 (1)收集数据:提供的文本文件(数据来源于UCI数据库) (2)准备数据:解析tab键分隔的数据行 (3)分析数据:快速检查数据,确保正确地解析数据内容,使用createPlot()函数绘制最终的树形图 (4)训练算法:createTree()函数 (5)测试算法:编写测试函数验证决策树可以正确分类给定的数据实例 (6)使用算法:存储数的数据结构,以使下次使用时无需重新构造树 trees.py如下: #!/u