Python机器学习之决策树算法


Posted in Python onDecember 22, 2017

一、决策树原理

决策树是用样本的属性作为结点,用属性的取值作为分支的树结构。
决策树的根结点是所有样本中信息量最大的属性。树的中间结点是该结点为根的子树所包含的样本子集中信息量最大的属性。决策树的叶结点是样本的类别值。决策树是一种知识表示形式,它是对所有样本数据的高度概括决策树能准确地识别所有样本的类别,也能有效地识别新样本的类别。 

决策树算法ID3的基本思想:

首先找出最有判别力的属性,把样例分成多个子集,每个子集又选择最有判别力的属性进行划分,一直进行到所有子集仅包含同一类型的数据为止。最后得到一棵决策树。

J.R.Quinlan的工作主要是引进了信息论中的信息增益,他将其称为信息增益(information gain),作为属性判别能力的度量,设计了构造决策树的递归算法。

举例子比较容易理解:

对于气候分类问题,属性为:
天气(A1) 取值为: 晴,多云,雨
气温(A2)  取值为: 冷 ,适中,热
湿度(A3)  取值为: 高 ,正常
风 (A4)  取值为: 有风, 无风

每个样例属于不同的类别,此例仅有两个类别,分别为P,N。P类和N类的样例分别称为正例和反例。将一些已知的正例和反例放在一起便得到训练集。
由ID3算法得出一棵正确分类训练集中每个样例的决策树,见下图。

Python机器学习之决策树算法

决策树叶子为类别名,即P 或者N。其它结点由样例的属性组成,每个属性的不同取值对应一分枝。
若要对一样例分类,从树根开始进行测试,按属性的取值分枝向下进入下层结点,对该结点进行测试,过程一直进行到叶结点,样例被判为属于该叶结点所标记的类别。
现用图来判一个具体例子,
某天早晨气候描述为:
天气:多云
气温:冷
湿度:正常
风: 无风

它属于哪类气候呢?-------------从图中可判别该样例的类别为P类。 

ID3就是要从表的训练集构造图这样的决策树。实际上,能正确分类训练集的决策树不止一棵。Quinlan的ID3算法能得出结点最少的决策树。

ID3算法:

     1. 对当前例子集合,计算各属性的信息增益;
     2. 选择信息增益最大的属性Ak;
     3. 把在Ak处取值相同的例子归于同一子集,Ak取几个值就得几个子集;
     4.对既含正例又含反例的子集,递归调用建树算法;
     5. 若子集仅含正例或反例,对应分枝标上P或N,返回调用处。

一般只要涉及到树的情况,经常会要用到递归。 

对于气候分类问题进行具体计算有:
1、 信息熵的计算: Python机器学习之决策树算法其中S是样例的集合, P(ui)是类别i出现概率:

Python机器学习之决策树算法

|S|表示例子集S的总数,|ui|表示类别ui的例子数。对9个正例和5个反例有:
P(u1)=9/14
P(u2)=5/14
H(S)=(9/14)log(14/9)+(5/14)log(14/5)=0.94bit 

2、信息增益的计算:Python机器学习之决策树算法

其中A是属性,Value(A)是属性A取值的集合,v是A的某一属性值,Sv是S中A的值为v的样例集合,| Sv |为Sv中所含样例数。

以属性A1为例,根据信息增益的计算公式,属性A1的信息增益为

Python机器学习之决策树算法

S=[9+,5-] //原样例集中共有14个样例,9个正例,5个反例
S晴=[2+,3-]//属性A1取值晴的样例共5个,2正,3反
S多云=[4+,0-] //属性A1取值多云的样例共4个,4正,0反
S雨=[3+,2-] //属性A1取值晴的样例共5个,3正,2反
故 

Python机器学习之决策树算法

3、结果为

Python机器学习之决策树算法

属性A1的信息增益最大,所以被选为根结点。

4、建决策树的根和叶子

ID3算法将选择信息增益最大的属性天气作为树根,在14个例子中对天气的3个取值进行分枝,3 个分枝对应3 个子集,分别是:

Python机器学习之决策树算法

其中S2中的例子全属于P类,因此对应分枝标记为P,其余两个子集既含有正例又含有反例,将递归调用建树算法。

5、递归建树

分别对S1和S3子集递归调用ID3算法,在每个子集中对各属性求信息增益.
(1)对S1,湿度属性信息增益最大,以它为该分枝的根结点,再向下分枝。湿度取高的例子全为N类,该分枝标记N。取值正常的例子全为P类,该分枝标记P。
(2)对S3,风属性信息增益最大,则以它为该分枝根结点。再向下分枝,风取有风时全为N类,该分枝标记N。取无风时全为P类,该分枝标记P。

二、PYTHON实现决策树算法分类

本代码为machine learning in action 第三章例子,亲测无误。
 1、计算给定数据shangnon数据的函数:

def calcShannonEnt(dataSet): 
 #calculate the shannon value 
 numEntries = len(dataSet) 
 labelCounts = {} 
 for featVec in dataSet:  #create the dictionary for all of the data 
  currentLabel = featVec[-1] 
  if currentLabel not in labelCounts.keys(): 
   labelCounts[currentLabel] = 0 
  labelCounts[currentLabel] += 1 
 shannonEnt = 0.0 
 for key in labelCounts: 
  prob = float(labelCounts[key])/numEntries 
  shannonEnt -= prob*log(prob,2) #get the log value 
 return shannonEnt

 2. 创建数据的函数

def createDataSet(): 
 dataSet = [[1,1,'yes'], 
    [1,1, 'yes'], 
    [1,0,'no'], 
    [0,1,'no'], 
    [0,1,'no']] 
 labels = ['no surfacing','flippers'] 
 return dataSet, labels

3.划分数据集,按照给定的特征划分数据集

def splitDataSet(dataSet, axis, value): 
 retDataSet = [] 
 for featVec in dataSet: 
  if featVec[axis] == value:  #abstract the fature 
   reducedFeatVec = featVec[:axis] 
   reducedFeatVec.extend(featVec[axis+1:]) 
   retDataSet.append(reducedFeatVec) 
 return retDataSet

4.选择最好的数据集划分方式

def chooseBestFeatureToSplit(dataSet): 
 numFeatures = len(dataSet[0])-1 
 baseEntropy = calcShannonEnt(dataSet) 
 bestInfoGain = 0.0; bestFeature = -1 
 for i in range(numFeatures): 
  featList = [example[i] for example in dataSet] 
  uniqueVals = set(featList) 
  newEntropy = 0.0 
  for value in uniqueVals: 
   subDataSet = splitDataSet(dataSet, i , value) 
   prob = len(subDataSet)/float(len(dataSet)) 
   newEntropy +=prob * calcShannonEnt(subDataSet) 
  infoGain = baseEntropy - newEntropy 
  if(infoGain > bestInfoGain): 
   bestInfoGain = infoGain 
   bestFeature = i 
 return bestFeature

5.递归创建树

用于找出出现次数最多的分类名称的函数

def majorityCnt(classList): 
 classCount = {} 
 for vote in classList: 
  if vote not in classCount.keys(): classCount[vote] = 0 
  classCount[vote] += 1 
 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) 
 return sortedClassCount[0][0]

用于创建树的函数代码

def createTree(dataSet, labels): 
 classList = [example[-1] for example in dataSet] 
 # the type is the same, so stop classify 
 if classList.count(classList[0]) == len(classList): 
  return classList[0] 
 # traversal all the features and choose the most frequent feature 
 if (len(dataSet[0]) == 1): 
  return majorityCnt(classList) 
 bestFeat = chooseBestFeatureToSplit(dataSet) 
 bestFeatLabel = labels[bestFeat] 
 myTree = {bestFeatLabel:{}} 
 del(labels[bestFeat]) 
 #get the list which attain the whole properties 
 featValues = [example[bestFeat] for example in dataSet] 
 uniqueVals = set(featValues) 
 for value in uniqueVals: 
  subLabels = labels[:] 
  myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels) 
 return myTree

然后是在python 名利提示符号输入如下命令:

myDat, labels = trees.createDataSet() 
myTree = trees.createTree(myDat,labels) 
print myTree

结果是:
{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

6.实用决策树进行分类的函数

def classify(inputTree, featLabels, testVec): 
 firstStr = inputTree.keys()[0] 
 secondDict = inputTree[firstStr] 
 featIndex = featLabels.index(firstStr) 
 for key in secondDict.keys(): 
  if testVec[featIndex] == key: 
   if type(secondDict[key]).__name__ == 'dict': 
    classLabel = classify(secondDict[key], featLabels, testVec) 
   else: classLabel = secondDict[key] 
 return classLabel

在Python命令提示符,输入:
trees.classify(myTree,labels,[1,0]) 

得到结果:
'no'
Congratulation. Oh yeah. You did it.!!!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用gzip模块压缩文件的简单教程
Apr 08 Python
python写入中英文字符串到文件的方法
May 06 Python
分享一下Python 开发者节省时间的10个方法
Oct 02 Python
python数据结构之线性表的顺序存储结构
Sep 28 Python
python代码 输入数字使其反向输出的方法
Dec 22 Python
python 读取文件并把矩阵转成numpy的两种方法
Feb 12 Python
python dlib人脸识别代码实例
Apr 04 Python
Python Web框架之Django框架cookie和session用法分析
Aug 16 Python
Python模块 _winreg操作注册表
Feb 05 Python
python实现数据结构中双向循环链表操作的示例
Oct 09 Python
python定时截屏实现
Nov 02 Python
Python之matplotlib绘制饼图
Apr 13 Python
python+selenium实现登录账户后自动点击的示例
Dec 22 #Python
python实现决策树
Dec 21 #Python
python利用sklearn包编写决策树源代码
Dec 21 #Python
python实现决策树分类算法
Dec 21 #Python
Python语言描述机器学习之Logistic回归算法
Dec 21 #Python
python Crypto模块的安装与使用方法
Dec 21 #Python
python编写Logistic逻辑回归
Dec 30 #Python
You might like
用PHP读取IMAP邮件
2006/10/09 PHP
php基础知识:类与对象(5) static
2006/12/13 PHP
PHP加Nginx实现动态裁剪图片方案
2014/03/10 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
递归实现php数组转xml的代码分享
2015/05/14 PHP
利用php输出不同的心形图案
2016/04/22 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
实例讲解PHP表单验证功能
2019/02/15 PHP
js实现GridView单选效果自动设置交替行、选中行、鼠标移动行背景色
2010/05/27 Javascript
jQuery EasyUI API 中文文档 - PropertyGrid属性表格
2011/11/18 Javascript
单击浏览器右上角的X关闭窗口弹出提示的小例子
2013/06/12 Javascript
jquery使用淘宝接口跨域查询手机号码归属地实例
2013/11/28 Javascript
javascript定义变量时带var与不带var的区别分析
2015/01/12 Javascript
js关于命名空间的函数实例
2015/02/05 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
2015/07/17 Javascript
Javascript BOM学习小结(六)
2015/11/26 Javascript
javascript实现网页端解压并查看zip文件
2015/12/15 Javascript
vue按需加载组件webpack require.ensure的方法
2017/12/13 Javascript
vue mounted组件的使用
2018/06/18 Javascript
layui的table中显示图片方法
2018/08/17 Javascript
浅谈layui框架自带分页和表格重载的接口解析问题
2019/09/11 Javascript
video.js添加自定义组件的方法
2020/12/09 Javascript
vue中使用echarts的示例
2021/01/03 Vue.js
Python中的包和模块实例
2014/11/22 Python
python在windows下创建隐藏窗口子进程的方法
2015/06/04 Python
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
Python+OpenCV感兴趣区域ROI提取方法
2019/01/10 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
python 实现PIL模块在图片画线写字
2020/05/16 Python
python smtplib发送多个email联系人的实现
2020/10/09 Python
英国玛莎百货新西兰:Marks & Spencer New Zealand
2019/07/21 全球购物
学习方法演讲稿
2014/05/10 职场文书
竞选大队干部演讲稿
2014/09/11 职场文书
软弱涣散基层党组织整改方案
2014/10/25 职场文书
学前班幼儿评语大全
2014/12/29 职场文书
终止解除劳动合同证明书
2015/06/17 职场文书