在生活中我们经常会用到决策树算法,最简单的就是二叉树了;相信大家也会又同样的困扰,手机经常收到各种短信,其中不乏很多垃圾短信、此时只要设置这类短信为垃圾短信手机就会自动进行屏蔽、减少被骚扰的次数,同时正常短信又不会被阻拦。类似这种就是决策树的工作原理,决策树的一个重要任务是为了理解数据中所含的信息,可以使用决策树不熟悉的数据集合,并从中体取一系列规则,这些机器根据数据集创建规则的过程,就是机器学习的过程。

决策树优缺点:

优点:计算复杂度不高,输出结果易于理解、即对模型的输出结果的可解释性要高;对中间值的缺失不敏感,可以处理不相关数据;

缺点:可能会产生过拟合现象;

决策树的构建:

输入:数据集

输出:构建好的决策树(训练集)

def 创建决策树:

if(数据集中所有样本分类一致):

创建携带类标签的叶子节点

else:

寻找划分数据集最好的特征

根据最好特征划分数据集

for每个划分的数据集:

创建决策子树(递归完成)

决策树的关键在于当前数据集上选择哪个特征属性作为划分的条件(能够将本来无序的数据集最大程度的划分为有序的子集),度量最佳分类属性特征的“最佳性”可用非纯度进行衡量;如果一个数据集只有一种分类结果,则该数据集一致性好、能够提供的信息也最少:只有一种情况;如果数据集有很多分类,则该数据集的一致性不好,能够提供的信息也较多:至少确定不只一种。组织杂乱数据的一种方法就是使用信息论度量信息,在划分数据前后信息发生的变化称为信息增益、这里描述集合信息的度量方式称为香农熵或者简称熵。(该名字来源于克劳德.香农、二十实际最聪明的人之一)。熵定义为信息的期望值,为了计算熵、我们需要计算所有类别的可能值所包含的信息期望。

熵计算公式:

明确决策树分类选择特征的依据后,先梳理下决策树的流程都有哪些:

1、收集数据:一切可以使用的方法、只要不违法;

2、准备数据:树构造算法只适用于标准型数据,因此数据值必须离散化;

3、分析数据:可以使用任何方法,数据构建完成后,需看下是否达到了我们的预期;

4、训练算法:构建树的数据结构;

5、测试算法:使用构建好的树计算正确率,越高当然越好(也可能过拟合、不能过份高了);

6、使用算法。

为了后面更好的理解决策树,利用如下数据我们先套用下公式,直观的计算一下什么是信息熵、什么是信息增益,以及如何选择一个特征作为当前数据的划分条件;以便后面更好的撸代码。

经典的样例数据:

Day

天气

温度

湿度

决定

1

N

2

N

3

Y

4

Y

5

正常

Y

6

正常

N

7

正常

Y

8

N

9

正常

Y

10

正常

Y

11

正常

Y

12

Y

13

正常

Y

14

N

根据信息熵的公式,此数据比较简单、我们可以手工计算一下各个特征的信息增益,从而知道ID3算法具体选择哪个特征作为分类的依据和算法的一个计算过程。

先列一下公式、参照公式带入计算,减小手工计算误差:

计算数据集(D)的经验熵:

一个特征(A)对数据集(D)的经验条件熵:

那么相对特征(A)此时的信息增益计算公式为:

以上4个特征中:天气(晴、阴雨)/温度(热、适中、凉)/湿度(高、正常)/风(强弱),推算过程中我们选择湿度或风、这两个特征值分布均只含两个值,计算过程的时候相对要简单一点。

第一步:计算该数据集的经验熵,该数据集共有14条数据:9条决定为Y、5条决定为N;则p(Y)=9/14、p(N)=5/14。此时代入公式:

第二步:选择风这个特征计算该特征相对数据集的经验熵,从数据可以看出风共有两个值:强和弱。

其中为强风的数据分布如下、共有6条数据,其中决定为Y和N的分别是3条,此时p(Y)=3/6、p(N)=3/6。

Day

天气

温度

湿度

决定

2

N

6

正常

N

7

正常

Y

11

正常

Y

12

Y

14

N

代入公式:

其中为若风的数据分布如下、共有8条数据,其中决定为Y有6条、N有2条,此时p(Y)=6/8、p(N)=2/8。

Day

天气

温度

湿度

决定

1

N

3

Y

4

Y

5

正常

Y

8

N

9

正常

Y

10

正常

Y

13

正常

Y

代入公式:

风这个特征的经验熵计算就完成了,强风和弱风在整个数据集中的占比分别为:

p(强)=6/14、p(弱)=8/14;代入公式则风这个特征的条件熵为:

风这个特征的信息增益为:

以此类推:

从中可以看出天气的新增增益为0.246、高于其他三个特征的增益,这也是为什么天气作为第一个分类依据的特征、在树的根节点上。

参照《机器学习实践》构建一颗决策树、python代码如下:

from math import logimport operatordef calcShannonEnt(dataSet):  # 计算数据的熵(entropy)    numEntries = len(dataSet)  # 数据条数    labelCounts = {}    for featVec in dataSet:        currentLabel = featVec[-1]  # 每行数据的最后一个字(类别)        if currentLabel not in labelCounts.keys():            labelCounts[currentLabel] = 0        labelCounts[currentLabel] += 1  # 统计有多少个类以及每个类的数量    shannonEnt = 0    for key in labelCounts:        prob = float(labelCounts[key]) / numEntries  # 计算单个类的熵值        shannonEnt -= prob * log(prob, 2)  # 累加每个类的熵值    return shannonEntdef createDataSet1():  # 创造示例数据    dataSet = [['黑', '是', '男'], ['白', '否', '男'], ['黑', '是', '男'],               ['白', '否', '女'], ['黑', '是', '女'], ['黑', '否', '女'],               ['白', '否', '女'], ['白', '否', '女']]    labels = ['a', 'b']    return dataSet, labels#待划分的数据集、划分数据集的特征、需要返回的特征值def splitDataSet(dataSet, axis,value):  # 按某个特征分类后的数据,例如value = 长,axis为头发axis = 0    retDataSet = []  # retDataSet返回的是数据中,所有头发为长的记录    for featVec in dataSet:        if featVec[axis] == value:            # 每次会将这个feature删除掉            reducedFeatVec = featVec[:axis]            reducedFeatVec.extend(featVec[axis + 1:])            retDataSet.append(reducedFeatVec)    return retDataSetdef chooseBestFeatureToSplit(dataSet):  # 选择最优的分类特征    numFeatures = len(dataSet[0]) - 1    baseEntropy = calcShannonEnt(dataSet)  # 原始的熵    bestInfoGain = 0    bestFeature = -1    # (1)遍历每个特征    for i in range(numFeatures):        featList = [example[i] for example in dataSet]        uniqueVals = set(featList)        newEntropy = 0        # (2)对单个特征中每个唯一值都进行子树的切分,然后计算这个的信息增益,然后累加每个分裂条件的信息增益,为newEntropy        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 bestFeaturedef majorityCnt(classList):  #按分类后类别数量排序,比如:最后分类为2男1女,则判定为男;    classCount = {}    for vote in classList:        if vote not in classCount.keys():            classCount[vote] = 0        classCount[vote] += 1    sortedClassCount = sorted(classCount.items(),                              key=operator.itemgetter(1),                              reverse=True)    return sortedClassCount[0][0]# 决策树核心逻辑:递归,深度优先遍历创建子树def createTree(dataSet, labels):    #print(dataSet)    classList = [example[-1] for example in dataSet]  # 类别:男或女    if classList.count(classList[0]) == len(classList):        return classList[0]    if len(dataSet[0]) == 1:  # 当只剩最优一个feature时,因为每次分裂会删除一个特征        return majorityCnt(classList)    # (1) 选择最优分裂特征    bestFeat = chooseBestFeatureToSplit(dataSet)  #选择最优特征    bestFeatLabel = labels[bestFeat]    myTree = {bestFeatLabel: {}}  #分类结果以字典形式保存    del (labels[bestFeat])    featValues = [example[bestFeat] for example in dataSet]    uniqueVals = set(featValues)    # (2) 遍历分裂特征的每个唯一值,分裂产生子树    for value in uniqueVals:        # 将每个label都往子树传递,labels一直可能会被选用        subLabels = labels[:]        # 对基于best feature这个feature内每个唯一值切分为不同的子树,然后返回子树的结果。每个子树切分能多个分支        # 递归调用,每层的切分为每个特征的唯一值        # (3) 对最佳分裂特征的每个值,分别创建子树        myTree[bestFeatLabel][value] = createTree(            splitDataSet(dataSet, bestFeat, value), subLabels)    return myTreeif __name__ == '__main__':    dataSet, labels = createDataSet1()  # 创造示列数据    print(createTree(dataSet, labels))  # 输出决策树模型结果

为了更直观展示决策树及各节点的信息熵,用sklearn工具基于鸢尾花数据集展示一颗完整的决策树结构。

from sklearn.datasets import load_irisfrom sklearn import treeimport osimport pydot  # need installprint(os.getcwd())clf = tree.DecisionTreeClassifier(criterion="entropy", max_features="log2",max_depth = 10)  #giniiris = load_iris()clf = clf.fit(iris.data, iris.target)tree.export_graphviz(clf, out_file='tree.dot')(graph, ) = pydot.graph_from_dot_file('tree.dot')graph.write_png('tree.png')

对应的决策树结构如下:

ID3是基于信息增益作为分类依据的监督学习算法,它有一个明显的缺点是该算法会倾向选择有较多属性值的特征作为分类依据,鉴于ID3算法缺点后面又衍生出来C4.5和CART算法、具体后面再详细介绍和分享总结。

python机器学习算法.mobi_机器学习之ID3算法详解及python代码实现相关推荐

  1. python随机数程序源码_Python 实现随机数详解及实例代码

    Python3实现随机数 random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串. random.seed(x)改变随机数生成器的种子seed. 一般不必特别去设定seed,Pyth ...

  2. 机器学习最易懂之贝叶斯模型详解与python实现

    文章目录 0.预备知识 0.1 先验概率.条件概率.后验概率 0.2 贝叶斯公式 0.3 极大似然估计 0.4 生成模型与判别模型 1.朴素贝叶斯模型 1.1 朴素贝叶斯的符号说明 1.2 朴素贝叶斯 ...

  3. python【数据结构与算法】最长公共子串详解(附代码)

    文章目录 1 定义 1 定义 和最长公共子序列一样,使用动态规划的算法. 下一步就要找到状态之间的转换方程. 和LCS问题唯一不同的地方在于当A[i] != B[j]时,res[i][j]就直接等于0 ...

  4. python编程8g的内存够么_详解解决Python memory error的问题(四种解决方案)

    昨天在用用Pycharm读取一个200+M的CSV的过程中,竟然出现了Memory Error!简直让我怀疑自己买了个假电脑,毕竟是8G内存i7处理器,一度怀疑自己装了假的内存条....下面说一下几个 ...

  5. python两张图片无缝合成一张_详解基于python的多张不同宽高图片拼接成大图

    #!/usr/bin/env python # -*- coding:utf-8 -*- import PIL.Image as Image import os IMAGES_PATH = 'D:Ma ...

  6. python中rstrip是什么意思_【详解】python中字符串的strip(),lstrip(),rstrip()的含义...

    [解答] 主要是: string. lstrip ( s[, chars] ) Return a copy of the string with leading characters removed. ...

  7. python分析每月销售数据_时间序列ARIMA模型详解:python实现店铺一周销售量预测...

    顾名思义,时间序列是时间间隔不变的情况下收集的时间点集合.这些集合被分析用来了解长期发展趋势,为了预测未来或者表现分析的其他形式.但是是什么令时间序列与常见的回归问题的不同? 有两个原因: 1.时间序 ...

  8. python的shutil模块是内置的_Python之shutil模块11个常用函数详解,python内置函数是什么...

    Python之shutil模块11个常用函数详解,python内置函数是什么 shutil 是 Python 中的高级文件操作模块,与os模块形成互补的关系,os主要提供了文件或文件夹的新建.删除.查 ...

  9. AdaBoost算法详解与python实现

    AdaBoost算法详解与python实现 https://tangshusen.me/2018/11/18/adaboost/

  10. RRT(Rapidly-Exploring Random Trees)算法详解及python实现

    RRT(Rapidly-Exploring Random Trees)算法详解及python实现 前言 一.原理 二.伪代码 三.代码详解 总结 前言 快速探索随机树(RRT):作为一种随机数据结构, ...

最新文章

  1. Hyperic 脚本服务(Script service)配置
  2. JAVA基础:JDK、JRE、JVM的概念
  3. testNg自动化,读取excel的数据
  4. 调用其他文件的define_C与C++的互相调用!就像大学宿舍一样,我用你的,你用我的!...
  5. hdu--4028--dp
  6. python设计编程体验中心_试学了风变编程的Python小课体验课,觉得课程模式很有趣,报名正式课程应该注意什么?...
  7. C语言 strcat函数实现
  8. php mysql.dll 下载_php_mysql.dll下载|
  9. VS2012 ffmpeg 没有定义的lrint
  10. sqlserver2008秘钥
  11. Spring、SpringMVC、SpringBoot、SpringCloud概述
  12. IPSec Over GRE和GRE Over IPSec技术
  13. 用AOP思想改造一个服务器的数据存储
  14. C语言 用矩形法计算定积分∫(0—1)sinxdx、∫(-1—1)cosxdx、∫(0—2)e^xdx
  15. 献给2012——易水寒的心声
  16. 小白操作Win10扩充C盘(把D盘内存分给C盘)亲测多次有效
  17. 执行shellcode一直提示illegal instruction
  18. EasyCVR平台通过国标GB28181接入柯达NVR显示注册失败,该如何解决?
  19. python怎么重复画圆_重画圆Python
  20. 计算机网络协议分析 第三课 PAP,CHAP,PPPoE

热门文章

  1. 三款新功能发布,助力阿里云表格存储再次升级
  2. 新功能:在负载均衡SLB控制台上查看DDoS安全防护阈值
  3. Veeam 发布 2022 年数据保护趋势报告,开发者需关注哪些点?
  4. 防水耐脏,超大容量双肩包,限时拼团仅需49元
  5. 反转了!“只问了1个框架,就给了35K的Python岗”
  6. 强封锁之后,华为正寻求10亿美元贷款;苹果发布iOS 12.3.1正式版,出击垃圾短信;联想CFO为“联想搬出中国”言论道歉;...
  7. shell安装mysql5.7_一键部署----shell脚本安装MySQL5.7
  8. html5 烟雾,jQuery烟雾背景发生器(HTML5 Canvas插件waterpipe.js
  9. 正则表达式中的开头和结尾
  10. (需求实战_进阶_02)SSM集成RabbitMQ 关键代码讲解、开发、测试