手把手生成决策树(dicision tree)
手把手生成决策树(dicision tree)
标签: Python 机器学习
主要參考资料:
Peter HARRINGTON.机器学习实战[M].李锐,李鹏,曲亚东,王斌译.北京:人民邮电出版社, 2013.
李航.统计学习方法[M].北京:清华大学出版社, 2012
原文链接:http://blog.csdn.net/xuelabizp/article/details/50979469
1.什么是决策树
决策树是一种主要的分类和回归方法。本文主要解说用于分类的决策树。
决策树就是依据相关的条件进行分类的一种树形结构,比方某高端约会站点针对女客户约会对象见面的安排过程就是一个决策树:
依据给定的数据集创建一个决策树就是机器学习的课程,创建一个决策树可能会花费较多的时间。可是使用一个决策树却很快。
创建决策树时最关键的问题就是选取哪一个特征作为分类特征。好的分类特征能够最大化的把数据集分开,将无序变为有序。
这里就出现了一个问题。怎样描写叙述一个数据集有序的程度?在信息论和概率统计中,熵表示随机变量不确定性的度量,即有序的程度。
现给出一个集合D。本文全部的讨论都以该集合为例:
序号 | 不浮出水面能否够生存 | 是否有脚蹼 | 是否为鱼类 |
---|---|---|---|
1 | 是 | 是 | 是 |
2 | 是 | 是 | 是 |
3 | 是 | 否 | 否 |
4 | 否 | 是 | 否 |
5 | 否 | 是 | 否 |
创建该集合的代码例如以下:
def create_data_set():
dataSet = [[1,1,'yes'],
[1,1,'yes'],
[1,0,'no'],
[0,1,'no'],
[0,1,'no']]
labels = ['no surfacing', 'flippers'] #不浮出水面能否够生存。是否有脚蹼
return dataSet, labels
2.熵,信息增益和信息增益比
2.1熵(entropy)
博主第一次接触“熵”这个字。是在高中的化学课上,可是感觉“熵”在化学课上的含义和信息论中的含义没什么差别。都是表示混乱的程度,熵越大,越混乱,比方一杯浑浊水的熵就比一杯纯净的水熵大。
在信息论和概率统计中。设X是一个取有限个值的离散随机变量,其概率分布为:
则随机变量X的熵定义为:
若pi=0。则规定0log0=0。须要说明的是。熵仅仅依赖于X的分布。而不依赖于X的值。依据(2)式就能够计算出上面给定的集合D的熵:
编写计算熵的函数,当中dataSet是建立决策树的数据集,每行最后一个元素表示类别:
def cal_Ent(dataSet): #依据给定数据集计算熵
num = len(dataSet)
labels = {}
for row in dataSet: #统计全部标签的个数
label = row[-1]
if label not in labels.keys():
labels[label] = 0
labels[label] += 1
Ent = 0.0
for key in labels: #计算熵
prob = float(labels[key]) / num
Ent -= prob * log(prob, 2)
return Ent
2.2信息增益(information gain)
信息增益表示得知特征X的信息而使得类Y的信息的不确定性降低的程度。
换一个角度解释一下。一杯浑浊的水Y,其熵为H1,如今将当中悬浮的一类物质X去除。这杯水的熵下降为H2,则物质X对于这杯水的信息增益就为H1−H2。
特征X对数据集D的信息增益记为g(D,X),计算公式例如以下:
当中H(D|X)为特征X给定条件下D的经验条件熵。
先解释什么是条件熵:
条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性,定义为X给定条件下Y的条件概率分布的熵对X的数学期望。
条件熵的计算公式例如以下:
当熵和条件熵中的概率由数据预计得到时,所相应的熵与条件熵分别称为经验熵和经验条件熵。
决策树选择某个特征作为其分类特征的依据就是该特征对于集合的信息增益最大,即去除该特征后,集合变得最有序。
仍旧以给定的集合D为例,依据计算信息增益准则选择最优分类特征。
以X1表示“不浮出水面能否够生存”。则
当中D1,D2表示D中X1取“是”和“否”的样本子集。
以X2表示“是否有脚蹼”,则
当中D1,D2表示D中X2取“是”和“否”的样本子集。
比較各个特征的信息增益。X1的信息增益较大,所以选择X1作为分类的最优特征。
编写选择最佳决策特征的函数,当中dataSet是建立决策树的数据集,每行最后一个元素表示类别:
#依照给定特征划分数据集,返回第axis个特征的值为value的全部数据
def split_data_set(dataSet, axis, value):
retDataSet = []
for row in dataSet:
if (row[axis]) == value:
reducedRow = row[:axis]
reducedRow.extend(row[axis+1:])
retDataSet.append(reducedRow)
return retDataSet
#选择最佳决策特征
def choose_best_feature(dataSet):
num = len(dataSet[0]) - 1 #特征数
baseEnt = cal_Ent(dataSet)
bestInfoGain = 0.0
bestFeature = -1
for i in range(num):
featlist = [example[i] for example in dataSet] #按列遍历数据集,选取一个特征的全部值
uniqueVals = set(featlist) #一个特征能够取的值
newEnt = 0.0
for value in uniqueVals:
subDataSet = split_data_set(dataSet, i, value)
prob = len(subDataSet) / float(len(dataSet))
newEnt += prob * cal_Ent(subDataSet)
infoGain = baseEnt - newEnt #信息增益
if (infoGain > bestInfoGain):
bestInfoGain = infoGain
bestFeature = i
return bestFeature
ID3决策树在生成的过程中。依据信息增益来选择特征。
2.3信息增益比(information gain ratio)
以信息增益作为划分训练数据集的特征。存在偏向于选择取值较多的特征的问题,使用信息增益比能够对这一问题进行校正。
特征X对训练数据集D的信息增益比gR(D,X)定义为其信息增益g(D,X)与训练数据集D关于特征X的值的熵HX(D)之比。
信息增益比计算公式例如以下:
当中
以给定的集合D为例,计算信息增益比。
依据信息增益比,选择X1作为分类的最优特征。
C4.5决策树在生成的过程中。依据信息增益比来选择特征。
3.实现一个决策树
3.1创建或加载数据集
首先须要创建或加载训练的数据集,第一节用的是创建数据集的方法,只是更经常使用的是利用open()
函数打开文件,加载一个数据集。
3.2生成决策树
决策树一般使用递归的方法生成。
编写递归函数有一个好习惯。就是先考虑结束条件。
生成决策树结束的条件有两个:其一是划分的数据都属于一个类,其二是全部的特征都已经使用了。在另外一种结束情况中。划分的数据有可能不全属于一个类,这个时候须要依据多数表决准则确定这个子数据集的分类。
在非结束的条件下。首先选择出信息增益最大的特征,然后依据其分类。
分类開始时,记录分类的特征到决策树中。然后在特征标签集中删除该特征。表示已经使用过该特征。依据选中的特征将数据集分为若干个子数据集,然后将子数据集作为參数递归创建决策树,终于生成一棵完整的决策树。
#多数表决法则
def majorityCnt(classList):
print classList
classCount = {}
for vote in classList: #统计数目
if vote not in classCount.keys(): classCount[vote] = 0
classCount += 1
sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return classCount[0][0]
# 生成决策树
def create_tree(dataSet, labels):
labelsCloned = labels[:]
classList = [example[-1] for example in dataSet] #[yes,yes,no,no,no]
if classList.count(classList[0]) == len(classList): #仅仅有一种类别,则停止划分
return classList[0]
if len(dataSet[0]) == 1: #没有特征,则停止划分
return majorityCnt(classList)
#print dataSet
bestFeat = choose_best_feature(dataSet)
bestFeatLabel = labelsCloned[bestFeat] #最佳特征的名字
myTree = {bestFeatLabel:{}}
del(labelsCloned[bestFeat])
featValues = [example[bestFeat] for example in dataSet] #获取最佳特征的全部属性
uniqueVals = set(featValues)
for value in uniqueVals: #建立子树
subLabels = labelsCloned[:] #深拷贝,不能改变原始列表的内容,由于每个子树都要使用
myTree[bestFeatLabel][value] = create_tree(split_data_set(dataSet, bestFeat, value), subLabels)
return myTree
生成的决策树例如以下所看到的:
3.3使用决策树
使用决策树对输入进行分类的函数也是一个递归函数。
分类函数须要三个參数:决策树。特征列表,待分类数据。特征列表是联系决策树和待分类数据的桥梁,决策树的特征通过特征列表获得其索引,再通过索引訪问待分类数据中该特征的值。
def classify(tree, featLabels, testVec):
firstJudge = tree.keys()[0]
secondDict = tree[firstJudge]
featIndex = featLabels.index(firstJudge) #获得特征索引
for key in secondDict: #进入相应的分类集合
if key == testVec[featIndex]: #按特征分类
if type(secondDict[key]).__name__ == 'dict': #假设分类结果是一个字典,则说明还要继续分类
classLabel = classify(secondDict[key], featLabels, testVec)
else: #分类结果不是字典。则分类结束
classLabel = secondDict[key]
return classLabel
3.4保存或者加载决策树
生成决策树是比較花费时间的,所以决策树生成以后存储起来。等要用的时候直接读取就可以。
def store_tree(tree, fileName): #保存树
import pickle
fw = open(fileName, 'w')
pickle.dump(tree, fw)
fw.close()
def grab_tree(fileName): #读取树
import pickle
fr = open(fileName)
return pickle.load(fr)
4.决策树可视化
使用字典的形式表示决策树对于人类来说还是有点抽象,假设能以图像的方式呈现就很方便了。很幸运,matplotlib中有模块能够使决策树可视化。这里就不解说了,直接“拿来使用”。将treePlotter.py复制到我们文件的根文件夹。直接导入treePlotter,然后调用treePlotter.createPlot()函数就可以:
import treePlotter
treePlotter.createPlot(tree)
如上面的决策树可视化后例如以下:
5.使用决策树预測隐形眼镜类型
隐形眼镜数据集包括患者的眼睛状况以及医生推荐的隐形眼镜类型。患者信息有4维,分别表示年龄,视力类型,是否散光,眼睛状况。隐形眼镜类型有3种,各自是软材质,硬材质和不适合带隐形眼镜。
想要把我们编写的脚本应用于别的数据集?没问题,仅仅要改动加载数据集的函数就可以,其它的函数不须要改变,详细例如以下:
#加载数据
def file2matrix():
file = open("lenses.data.txt")
allLines = file.readlines()
row = len(allLines)
dataSet = []
for line in allLines:
line = line.strip()
listFromLine = line.split()
dataSet.append(listFromLine)
labels = ['age', 'prescription', 'astigmatic', 'tear rate'] #年龄,视力类型,是否散光。眼睛状况
return dataSet, labels
生成的决策树可视化后例如以下:
事实上博主还尝试了其它的数据集,只是决策树实在是太复杂了。太大了。密密麻麻根本看不清楚。谁有兴趣能够尝试一下别的数据集。
6.总结
- 源代码在我的GitHub中。包括了可视化脚本以及数据集
MachineLearningAction
仓库里面有常见的机器学习算法处理常见数据集的各种实例。欢迎訪问- 决策树的长处
- 决策树易于理解和解释,尤其是可视化后的决策树很直观
- 决策树分类很快
- 决策树的缺点
- easy过拟合
- 对缺失数据的数据集处理困难
- 忽略数据集中特征的相互关联
- 常见的决策树有ID3,C4.5和CART决策树
- C4.5较之ID3更优。信息增益比能够解决信息增益选取取值较多的特征的问题
- C4.5决策树生成的过程中有剪枝。能够降低决策树的拟合度
- C4.5能够处理数值型数据,而ID3仅仅能处理标称型数据
- 决策树能够应用在贷款发放,约会见面等方面
手把手生成决策树(dicision tree)的更多相关文章
- 机器学习算法实践:决策树 (Decision Tree)(转载)
前言 最近打算系统学习下机器学习的基础算法,避免眼高手低,决定把常用的机器学习基础算法都实现一遍以便加深印象.本文为这系列博客的第一篇,关于决策树(Decision Tree)的算法实现,文中我将对决 ...
- 数据挖掘 决策树 Decision tree
数据挖掘-决策树 Decision tree 目录 数据挖掘-决策树 Decision tree 1. 决策树概述 1.1 决策树介绍 1.1.1 决策树定义 1.1.2 本质 1.1.3 决策树的组 ...
- 决策树 Decision Tree
决策树是一个类似于流程图的树结构:其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布.树的最顶层是根结点.  决策树的构建 想要构建一个决策树,那么咱们 ...
- 用于分类的决策树(Decision Tree)-ID3 C4.5
决策树(Decision Tree)是一种基本的分类与回归方法(ID3.C4.5和基于 Gini 的 CART 可用于分类,CART还可用于回归).决策树在分类过程中,表示的是基于特征对实例进行划分, ...
- (ZT)算法杂货铺——分类算法之决策树(Decision tree)
https://www.cnblogs.com/leoo2sk/archive/2010/09/19/decision-tree.html 3.1.摘要 在前面两篇文章中,分别介绍和讨论了朴素贝叶斯分 ...
- 决策树decision tree原理介绍_python sklearn建模_乳腺癌细胞分类器(推荐AAA)
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- 机器学习方法(四):决策树Decision Tree原理与实现技巧
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 前面三篇写了线性回归,lass ...
- 决策树Decision Tree 及实现
Decision Tree 及实现 标签: 决策树熵信息增益分类有监督 2014-03-17 12:12 15010人阅读 评论(41) 收藏 举报 分类: Data Mining(25) Pyt ...
- 【转载】决策树Decision Tree学习
本文转自:http://www.cnblogs.com/v-July-v/archive/2012/05/17/2539023.html 最近在研究规则引擎,需要学习决策树.决策表等算法.发现篇好文对 ...
随机推荐
- Linux 安装Nginx具体图解教程
系统:Centos6.6 64位 Nginx: http://nginx.org/en/download.html 眼下最新版本号1.9.4 我下载1.8.0 watermark/2/text/a ...
- SICP 习题 (1.39)解题总结
SICP 习题1.39沿着习题1.37, 1.38的方向继续前行,要求我们依据德国数学家J.H.Lambert的公式定义tan-cf过程,用于计算正切函数的近似值. J.H.Lambert的公式例如以 ...
- CSS布局篇——固宽、变宽、固宽+变宽
学了前端挺久了.近期写一个项目測试系统,布局时发现自己对变宽+固宽的布局还没有全然掌握,所以在这里总结一下,以后须要的时候回头看看. 1.最简单的当然是一列或多列固宽 比如两列固宽: <1> ...
- 初步使用RecyclerView实现瀑布流
先看效果 关于RecyclerView,真的是很强大. 个人觉得主要方便的地方是 1.直接可以设置条目布局,通过setLayoutManager LinearLayoutManager:线性布局,横向 ...
- 根据ID和parentID利用Java递归获取全路径名称
如下图所示,本文参考资源:https://jie-bosshr.iteye.com/blog/1996607 感谢大佬的无私奉献. 思路: 定义一个方法getParentName参数为int类型的c ...
- CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)
题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...
- STL中erase()的陷阱
最近在刷stl源码剖析这本书时,对于vector的erase()函数引起了我的注意 在删除单个元素时是这样定义的: iterator erase(iterator position){ !=end() ...
- 通过Ajax进行POST提交JSON类型的数据到SpringMVC Controller的方法
现在在做的项目用到了SpringMVC框架,需要从前端angular接收请求的JSON数据,为了测试方便,所以直接先用AJAX进行测试,不过刚开始用平时用的ajax方法,提交请求会出现415或者400 ...
- iOS界面生命周期过程具体解释
开发过Android的人都知道,每个Android界面就是一个Activity,而每个Activity都会有自己的生命周期, 有一系列方法会控制Activity的生命周期.如:onCreate(),o ...
- layout-maxWidth属性用法
对于maxWidth属性,相信大家都不陌生.不过,今天我遇到了一个问题,就是当我希望一个relayout的宽度有个最大值的时候,用maxWidth却没办法实现.这里总结下maxWidth 的用法 1. ...