1. 介绍

        决策树是一种依托决策而建立起来的一种树。在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象/分类,树中的每一个分叉路径代表某个可能的属性值,而每一个叶子节点则对应从根节点到该叶子节点所经历的路径所表示的对象的值

通过训练数据构建决策树,可以高效的对未知的数据进行分类。决策数有两大优点:

    1)决策树模型可以读性好,具有描述性,有助于人工分析;

    2)效率高,决策树只需要一次构建,反复使用,每一次预测的最大计算次数不超过决策树的深度。

决策树是一颗树形的数据结构,可以是多叉树也可以是二叉树,决策树实际上是一种基于贪心策略构造的,每次选择的都是最优的属性进行分裂。

决策树也是一种监督学习算法,它的样本是(x,y)形式的输入输出样例。

输入:一组对象属性

输出:对象值(分类算法中得到某个类别)

决策树中间计算过程:

  统计学习方法中根据下表贷款数据表生成的决策树如下,当给定一个人的特征属性之后就能判断能不能给他贷款。

由上面的示例可以看出决策树模型是一个 if(){}else if(){} else(){}模型,这里它具有一个十分重要的性质:互斥并且完备(每一个实例都被一条路径或者一条规则所覆盖,而且只被一条路径或一条规则所覆盖)

一般可以将决策树分为两种类型,一种是 分类决策树,也就是本篇所介绍的决策树类型。另一种决策树是 回归决策树(CART回归树),下一篇中再介绍。它们的主要区别是得到的结果是否是连续值还是一个类别(分类问题、回归问题)。


2. 分类决策树

看到上面的第一张决策树的图后,心中会产生几个疑问:

    1) 为什么将“有自己的房子”作为根节点?

    2) 为什么有自己的房子分类结果就是“是”?

    3) 如何选定下一个节点?…..

先介绍一下决策树中必须明白的几个概念:

2.1 熵与条件熵、经验熵与检验条件熵

熵H(X):表示随机变量不确定性的度量,如果一个变量的随机性越大(不确定性),则它的熵越大。

计算公式:

条件熵H(Y|X):表示在已知随机变量X的条件下随机变量Y的不确定性。例如“有自己房子”条件下“贷款”的熵。

当熵和条件熵中的概率是由数据估计(特别是极大似然估计)得到时,所对应的熵与条件熵分别称为经验熵和经验条件熵。

2.2 信息增益与信息增益比

信息增益:表示得知特征的信息使得类Y的信息的不确定性减少程度。

特征A对训练数据集D的信息增益g(D,A):集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差。

假设数据D可以分为K个类(对应介绍中 贷款“是”,“否”),特征A(“有自己的房子”)有n个不同的取值(“有”,“无”)。

H(D): 对数据集D进行分类的不确定性。

H(D|A): 在特定A给定条件下对数据集D进行分类的不确定性。

它们的计算公式如下(统计学习方法中的解析)

既然已经有了信息增益为什么还要引入“信息增益比”呢?

在以信息增益划分到底采用那个特征时,存在偏向于选取值较多的特征的问题,所以这里引入的增益比相当于归一化,使各个特曾的影响因子归一化。

其中:


3. 决策树算法——ID3 算法

当理解了上面信息熵和条件熵的概念后,ID3算法就很容易理解了。该算法解决的主要问题是:如何生成一个决策树?

输入:训练数据集D,特征集A,阈值e

输出: 决策树 T

3.1 决策树生成算法

ID3算法的核心是在决策树各个子节点上应用信息增益准则选择特征,递归的构建决策树,具体方法是:从根节点开始,对节点计算所有可能的特征的信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值建立子节点;再对子节点递归调用以上方法,构建决策树。直到所有特征的信息增益均很小或没有特征可以选择为止。最后得到一个决策树。

这其中会遇到一些问题:

  1、若D中所有的实例属于用一类C(k),则T为单节点数,并将类C(k)作为该节点的类标记

  2、若A = null,则T为单节点树,并将D中实例数最大的类C(k)作为该节点的类标记。

  3、如果A(g)的信息增益比小于阈值e,则置T为单节点树,并将D中实例数最大的类作为该节点的类标记。

  4、随着树的向下生长,特征集也会逐渐减少(A-A(g)),父节点中出现的特征将会排除在特征选取中。

与ID3算法类似的算法 C4.5算法,与ID3唯一的不同是 它选取信息增益比作为特征选择的标准,这样可以减少过拟合。而ID3采用信息增益作为特征选择的标准。

创建决策树的伪代码(createBranch函数):

  1 检测数据中的每个子项是否属于同一个分类
2 if so return 类标签
3 else
4 寻找划分数据集的最好特征
5 划分数据集
6 创建分支节点
7 for 每个划分的子集
8 调用 createBranch并增加返回结果到分支节点中
9 return 分支节点

3.2 决策树的减枝

通过决策树算法生成的决策树往往对训练数据的分类很精确,但对未知的测试数据的分类却没有那么准确,即出现过拟合现象。

在决策树学习中将已生成的树进行简化的过程称为剪枝。

决策树的剪枝往往通过极小化决策树整体的损失函数/代价函数来实现。 当剪枝后决策树的损失值小于剪枝前损失函数值,那么该分支将会被剪掉。(从叶节点自下而上遍历决策树的每个节点,确定是否需要进行剪枝)

3.3 决策树的损失函数:

《统计学习方法》中给出了损失函数的公式:


4. python 实现ID3决策树生成

决策树构建的组件图如下:

数据准备(只作为算法测试)

def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
#change to discrete values
return dataSet, labels

1. 计算信息熵的函数:

注: 输入数据的最后一列为 数据标签。

def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet: #the the number of unique elements and their occurance
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) #log base 2
return shannonEnt

2. 划分数据集

该函数的目的是筛选出 某一列值等于某个只的所有数据,放到一个新的矩阵中:

# dataSet: 原始测试数据
# axis : 测试数据的某一列
# value: 需要筛选的值
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis] #chop out axis used for splitting
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet

3. 计算最佳的数据划分方式

计算信息增益选取最佳的数据划分方式. (分别计算每个特征值的信息增益值,返回信息增益最大的特征值序号)

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]
# 存放第i列,数据值的set
uniqueVals = set(featList) #get a set of unique values
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 #calculate the info gain; ie reduction in entropy
if (infoGain > bestInfoGain): #compare this to the best gain so far
bestInfoGain = infoGain #if better than current best, set to best
bestFeature = i
return bestFeature #returns an integer

注: 这里运用了信息增益,而并没有使用信息增益比。

4.递归构建决策树

有了前面的函数工具基础,构建一颗决策树也就不那么复杂了。

def createTree(dataSet,labels):
classList = [example[-1] for example in dataSet]
if classList.count(classList[0]) == len(classList):
return classList[0]#stop splitting when all of the classes are equal
#stop splitting when there are no more features in dataSet
if len(dataSet[0]) == 1:
return majorityCnt(classList)
bestFeat = chooseBestFeatureToSplit(dataSet)
bestFeatLabel = labels[bestFeat]
myTree = {bestFeatLabel:{}}
del(labels[bestFeat])
featValues = [example[bestFeat] for example in dataSet]
uniqueVals = set(featValues)
for value in uniqueVals:
subLabels = labels[:] #copy all of labels, so trees don't mess up existing labels
#递归调用,createTree函数
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
return myTree

参考:

《统计学习方法》

《机器学习实战》

http://blog.csdn.net/jialeheyeshu/article/details/51832165

https://www.cnblogs.com/starfire86/p/5749328.html

https://blog.csdn.net/u011067360/article/details/24871801

监督学习——决策树理论与实践(上):分类决策树的更多相关文章

  1. 监督学习——决策树理论与实践(下):回归决策树(CART)

    介绍 决策树分为分类决策树和回归决策树: 上一篇介绍了分类决策树以及Python实现分类决策树: 监督学习——决策树理论与实践(上):分类决策树          决策树是一种依托决策而建立起来的一种 ...

  2. SKlearn中分类决策树的重要参数详解

    学习机器学习童鞋们应该都知道决策树是一个非常好用的算法,因为它的运算速度快,准确性高,方便理解,可以处理连续或种类的字段,并且适合高维的数据而被人们喜爱,而Sklearn也是学习Python实现机器学 ...

  3. 吴裕雄 python 机器学习——分类决策树模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_s ...

  4. 计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践

    计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践 2018年06月13日 16:38:11 轻春 阅读数 6004更多 分类专栏: 机器学习 机器学习荐货情报局   版 ...

  5. 高翔《视觉SLAM十四讲》从理论到实践

    目录 第1讲 前言:本书讲什么:如何使用本书: 第2讲 初始SLAM:引子-小萝卜的例子:经典视觉SLAM框架:SLAM问题的数学表述:实践-编程基础: 第3讲 三维空间刚体运动 旋转矩阵:实践-Ei ...

  6. 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法

    若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...

  7. Java 理论与实践: 处理 InterruptedException

    捕捉到它,然后怎么处理它? 很多 Java™ 语言方法,例如 Thread.sleep() 和 Object.wait(),都可以抛出InterruptedException.您不能忽略这个异常,因为 ...

  8. Java 理论与实践: 非阻塞算法简介——看吧,没有锁定!(转载)

    简介: Java™ 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能.非阻塞算法属于并发算法,它们可以安全地派生它们的线程, ...

  9. Java 理论与实践: 流行的原子——新原子类是 java.util.concurrent 的隐藏精华(转载)

    简介: 在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待.无锁定的算法.在 java.util.concurrent 中添加原子变量类之后,这种情况发生了变化.请跟随并 ...

随机推荐

  1. Netty学习第一节Netty的总体概况

    一.Netty简介 什么是Netty? 1.高性能事件驱动,异步非阻塞的IO加载开源框架. 它是由JBoss提供,用于建立TCP等底层链接.基于Netty可以建立高性能的HTTP服务器,快速开发高性能 ...

  2. python编码(三)

    python 有str object 和 unicode object 两种字符串,都可以存放字符的字节编码,但是他们是不同的type,这一点很重要,也是为什么会有encode(编码)和decode( ...

  3. 关于RabbitMQ一点

    RabbitMQ是AMQP(高级消息队列协议)的标准实现,理论上可以保证消息发送的准确性 RabbitMQ是用Erlang语言编写的,而Erlang语言具有以下特点: 并发性--Erlang支持超大量 ...

  4. 3D indoor map positioning with a smartphone image

    menu 1. 基于Tango的三维建模技术(SLAM)(视觉SLAM,RGBD单目深度摄像机+罗盘仪)导出或不导出->Android 三维游戏开发技术(普通Android手机) 2. 基于An ...

  5. ZOJ2481 Unique Ascending Array 2017-04-18 23:08 33人阅读 评论(0) 收藏

    Unique Ascending Array Time Limit: 2 Seconds      Memory Limit: 65536 KB Given an array of integers ...

  6. IDEA14添加SVN

    今天升级IDEA14,发现SVN变了,折腾了好一会才搞好.记录一下,希望其他人能少走弯路.主要是IDEA14的svn是用命令行工具进行操作,这样对以后SVN的兼容性也会好很多,这个在他们官方的博客上也 ...

  7. fully delete project in Eclipse

    选择你的项目(test)右击,选择delete——弹出框中勾选删除全部,如下如所示: 正常情况下,这样就能删除干净了,有时候你项目在运行,这时候你点击删除,那就会报下面的错误提示,虽然不会影响你其它项 ...

  8. pl/sql 语言设置

    1.select * from v$nls_parameters 查询nls的参数,获得数据库服务器端的字符编码 NLS_LANGUAGE NLS_CHARACTERSET 2.修改本地环境变量 NL ...

  9. delphi 动态加载dll

    引入文件 DLL比较复杂时,可以为它的声明专门创建一个引入单元,这会使该DLL变得更加容易维护和查看.引入单元的格式如下: unit MyDllImport; {Import unit for MyD ...

  10. Android DalivkVM与JVM的比较

    JVM 与 DalivkVM的区别 Android 为什么还有搞一个Dalivk虚拟机,不是已经就有Java虚拟机了吗,为什么还要专门搞一个Dalivk虚拟机呢? 答: 1.以前Java是Sun公司的 ...