本篇文章将从决策树模型的原理开始讲起,通过解决如何在夏日中挑选西瓜这一问题来全面掌握。

本文目录:

一:问题导向

二:ID3算法预备知识:

  • 2.1:熵
  • 2.2 : 信息增益

三:代码实现及结果分析

  • 3.1:标注数据:
  • 3.2:计算信息熵(经验熵:
  • 3.3:计算信息增益:

四:决策树生成和修剪

一:问题导向

夏日炎炎,我们如何使用过去的经验来判断一个西瓜是不是好瓜呢?

我们一般会根据它的 色泽,根蒂,敲声,纹理,触感等等来判断它是不是一个好瓜。

以下是去年父亲买瓜时的信息:

色泽,根蒂,敲声,纹理,脐部,触感,好坏

青绿,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
乌黑,蜷缩,沉闷,清晰,凹陷,硬滑,好瓜
乌黑,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
青绿,蜷缩,沉闷,清晰,凹陷,硬滑,好瓜
浅白,蜷缩,浊响,清晰,凹陷,硬滑,好瓜
青绿,稍蜷,浊响,清晰,稍凹,软粘,好瓜
乌黑,稍蜷,浊响,稍糊,稍凹,软粘,好瓜
乌黑,稍蜷,浊响,清晰,稍凹,硬滑,好瓜
乌黑,稍蜷,沉闷,稍糊,稍凹,硬滑,坏瓜
青绿,硬挺,清脆,清晰,平坦,软粘,坏瓜
浅白,硬挺,清脆,模糊,平坦,硬滑,坏瓜
浅白,蜷缩,浊响,模糊,平坦,软粘,坏瓜
青绿,稍蜷,浊响,稍糊,凹陷,硬滑,坏瓜
浅白,稍蜷,沉闷,稍糊,凹陷,硬滑,坏瓜
乌黑,稍蜷,浊响,清晰,稍凹,软粘,坏瓜
浅白,蜷缩,浊响,模糊,平坦,硬滑,坏瓜
青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,坏瓜

但我们会对这些判断条件有一个优先级,先要挑最重要的那个因素考虑,可能对西瓜而言没有这么明显,但当我们去看医生时,如果我们的症状是腹泻,头疼,脱水,昏厥,那么医生会按照 昏厥 这个 权重最大 的症状先判断生命特征,再按照 *脱水 *去开点滴,再按照 腹泻 判断可能是肠胃炎等等。

树结构大家应该都熟知了,通过根节点开始,通过判断节点信息的是或否决定分支,逐次向下,最后在叶子节点生成最终的决策。

决策树的过程和这个类似,就是先挑“权重”最大的那个考虑,然后再往下细分。

那么我们用一个什么标准来 衡量某个特征是权重最大的呢

这里有信息增益和基尼系数两个。我们使用ID3算法

ID3算法采用的是信息增益这个量。

二:ID3算法的预备知识

(理论熟练的同学可以跳过这一部分)

2.1 熵

在物理中: 熵是混乱的度量指标。

对于一个数据集而言,它的类别越多,越混乱.

我们引入 “信息熵” 来作为度量样本集合混乱度(纯度)的指标,采用信息增益这个量来作为纯度的度量,选取信息增益最大的特征进行分裂(即作为结点)。

信息熵的计算公式是:
E(x)=−∑i=1Np(xi)log2 p(xi)E(x)= -\sum_{i=1}^N p(x_i)log_2 \, p(x_i)E(x)=−i=1∑N​p(xi​)log2​p(xi​)

2.2 . 信息增益

构造树的基本想法是随着树深度的增加,节点的熵迅速地降低。熵降低的速度越快越好,这样我们有望得到一棵高度最矮的决策树。

在没有给定西瓜信息时,根据去年数据,我们只知道新的一个瓜好瓜的概率为8/17,坏瓜的概率为9/17.此时的熵为:

En(x)=−817log2 817−917log2 917=0.511+0.486=0.997E_n(x)= - \frac{8}{17}log_2 \, \frac{8}{17}-\frac{9}{17}log_2\,\frac{9}{17}=0.511+0.486=0.997En​(x)=−178​log2​178​−179​log2​179​=0.511+0.486=0.997

属性有六个:色泽,根蒂,敲声,纹理,脐部,触感。我们首先要决定哪个属性作树的根节点。

对每项指标分别统计:在不同的取值下好瓜和坏瓜的个数。

色泽 根蒂 敲声 纹理 脐部 触感
好/坏:
青绿:3/3 蜷缩:5/3 浊响 :6/4
乌黑:4/2 稍蜷 :3/4 沉闷:2/3
浅白:1/4 硬挺 :0/2 清脆:0/2

对每个属性计算信息熵:

我们以色泽为例:

Ent(青绿)=−36log2 36−36log2 36=1E_{nt}(青绿)= - \frac{3}{6}log_2 \, \frac{3}{6}-\frac{3}{6}log_2\,\frac{3}{6}=1Ent​(青绿)=−63​log2​63​−63​log2​63​=1
Ent(乌黑)=−46log2 46−26log2 26=0.918E_{nt}(乌黑)= - \frac{4}{6}log_2 \, \frac{4}{6}-\frac{2}{6}log_2\,\frac{2}{6}=0.918Ent​(乌黑)=−64​log2​64​−62​log2​62​=0.918
Ent(浅白)=−15log2 15−45log2 45=0.722E_{nt}(浅白)= - \frac{1}{5}log_2 \, \frac{1}{5}-\frac{4}{5}log_2\,\frac{4}{5}=0.722Ent​(浅白)=−51​log2​51​−54​log2​54​=0.722

由此我们可以计算出色泽属性的信息增益是:

Gain(X,色泽)=Ent−∑i=13SvSEnt(Sv)=0.997−(617×1.000+617×0.918+517×0.722)=0.108G_{ain}(X,色泽) = E_{nt}- \sum_{i=1}^3 \frac{S_v}{S}E_{nt}(S_v) \\\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\qquad\qquad =0.997-(\frac{6}{17}\times 1.000+\frac{6}{17}\times 0.918+\frac{5}{17}\times0.722) \\=0.108Gain​(X,色泽)=Ent​−i=1∑3​SSv​​Ent​(Sv​)=0.997−(176​×1.000+176​×0.918+175​×0.722)=0.108

同理,按照其他方法构造出其他属性的信息增益,分别如下:
,
Gain(X,根蒂)=0.043Gain(X,敲声,)=0.141G_{ain}(X,根蒂) = 0.043 \qquad G_{ain}(X,敲声,) = 0.141Gain​(X,根蒂)=0.043Gain​(X,敲声,)=0.141
Gain(X,纹理)=0.337Gain(X,脐部,)=0.289G_{ain}(X,纹理) = 0.337 \qquad G_{ain}(X,脐部,) = 0.289 Gain​(X,纹理)=0.337Gain​(X,脐部,)=0.289
Gain(X,触感)=0.006G_{ain}(X,触感) = 0.006 \qquad \qquad\qquad\qquad Gain​(X,触感)=0.006

经过比较,我们得出信息增益最大的属性为纹理 于是我们得到第一个划分属性结点(纹理)。

到现在可得出如下初步构建的决策树:

再次根据节点的标签划分三个子结点的集合,这里的3个子集合相当于一个类似总集合X一样的地位。

重复上面找的纹理结点的方法进行递归。
利用信息增益最大的方法来进行特征选择。

不断递归构建整个决策树。

注意:我们这里使用了比较好的数据,但实际应用中我们还需要对决策树进行剪枝来应对参差不齐的数据(剪枝:可以理解为根据测试集消除影响不大的节点)

这样产生的树往往对训练数据的分类很准确,但对未知的测试数据的分类却没有那么准确,即出现过拟合现象

过拟合的原因在于学习时过多地考虑如何提高对训练数据的正确分类,从而构建出过于复杂的决策树。解决这个问题的办法是考虑决策树的复杂度,对已生成的决策树进行简化。

大家可以下思考一下,我们在下一节详细论述并解决上述问题

三:代码实现及结果分析

3.1标注数据:

在编写代码之前,我们先对数据集进行属性标注。

  • 色泽:0代表青绿,1代表乌黑,2代表浅白;

  • 根蒂:0代表蜷缩,1代表稍蜷,2代表硬挺;

  • 敲声:0代表清脆,1代表浊响,2代表沉闷;

  • 脐部:0代表凹陷,1代表稍凹,2代表平坦;

  • 纹理:0代表稍糊,1代表清晰

  • 触感:0代表硬滑,1代表软粘

  • 好坏:no代表坏瓜,yes代表好瓜。

3.2 计算信息熵(经验熵)

确定这些之后,我们就可以创建数据集,并计算经验熵了,代码编写如下:

from math import log#训练数据集
def createDataSet():dataSet = [[0,0,1,1,0,0,'yes'],[1,0,2,1,0,0,'yes'],[1,0,1,1,0,0,'yes'],[0,0,2,1,0,0,'yes'],[2,0,1,1,0,0,'yes'],[0,1,1,1,1,1,'yes'],[1,1,1,0,1,1,'yes'],[1,1,1,1,1,0,'yes'],[1,1,2,0,1,0,'no'],[0,2,0,1,2,1,'no'],[2,2,0,0,2,0,'no'],[2,0,1,0,2,1,'no'],[0,1,1,0,0,0,'no'],[2,1,2,0,0,0,'no'],[1,1,1,1,1,1,'no'],[2,0,1,0,2,0,'no'],[0,0,2,0,1,0,'no']]labels = ['色泽','根蒂','敲声','纹理','脐部','触感','好坏']#分类属性return dataSet, labels                #返回数据集和分类属性

计算给定数据集的经验熵(信息熵)

def calMessageEnt(dataSet):numEntires = len(dataSet) #返回数据集的行数labelCounts = {}        #保存每个标签出现次数的次数#对每组特征向量就进行统计for featVec in dataSet:currentLabel = featVec[-1]  #提取标签的信息#如果标签不在统计里面if (currentLabel not in labelCounts.keys()):labelCounts[currentLabel] = 0#如果在,计数labelCounts[currentLabel]+=1#信息熵MessageEnt = 0.0#计算信息熵for key in  labelCounts:#选择该标签(Label)的概率prob = float(labelCounts[key])/numEntires#利用公式计算MessageEnt -= prob*log(prob,2)#返回信息熵return MessageEntif __name__ =='__main__':dataSet,features =createDataSet()print(dataSet)print(calMessageEnt(dataSet))

结果如下:信息熵和我们上文算的一样

注意:在公式中,是把所有的事件代入公式求和得出信息熵 ,所以使用累加的形式

一般写+=习惯,但对于这个公式是-= ,一定要注意,否则只算以此,而不能循环

利用公式计算
MessageEnt -= prob*log(prob,2)

因为涉及到大量的公式,一定要多输出计算的数值和我们手动算的进行对比,确保无误在向下进行

3.3:计算信息增益

#按照给定特征划分 数据集#  dataSet - 待划分的数据集#  axis - 划分数据集的特征#  value - 需要返回的特征的值def splitDataSet(dataSet,axis,value):#创建返回的数据集列表retDataSet = [] #遍历数据集for featVec in dataSet:#如果划分的等于那个特征if featVec[axis] == value:#去掉axis特征reducedFeatVec = featVec[:axis]#将符合条件的添加到返回的数据集reducedFeatVec.extend(featVec[axis+1:])retDataSet.append(reducedFeatVec)#返回划分后的数据集return retDataSet#选择最优特征# dataSet - 数据集# bestFeature - 信息增益最大的(最优)特征的索引值# bestInFoGain 信息增益def chooseBestFeatureToSplit(dataSet):#特征的数量numFeatures = len(dataSet[0])-1#计算数据集的信息熵baseEntropy = calMessageEnt(dataSet)print('数据集的信息熵',baseEntropy)#信息增益bestInfoGain =0.0#最优特 征索引值bestFeature = -1#遍历所有特征for i in range(numFeatures):#获取dataSet的第i个所有特征featList = [example[i] for example in dataSet]#创建SET集合,元素不可重复uniqueVals =set(featList)newEntropy = 0.0 #经验条件熵#计算信息增益for value in uniqueVals:#划分子集subDataSet = splitDataSet(dataSet,i,value)#计算子集的概率prob = len(subDataSet)/float(len(dataSet))print('第',i,'个特征,第',value,'个子集的概率',prob)#根据公式计算经验条件熵newEntropy += prob*calMessageEnt(subDataSet)print('第',i,'特征子集信息熵',calMessageEnt(subDataSet))print('第',i,'个特征的经验条件熵',newEntropy)#信息增益infoGain = baseEntropy - newEntropy#打印每个特征的信息增益print("第%d个特征的增益为%.3f" % (i, infoGain))#计算最优特征的信息增益if (infoGain > bestInfoGain): #更新信息增益,找到最大的信息增益bestInfoGain = infoGain#记录信息增益最大的特征的索引值bestFeature = i#返回信息增益最大的特征的索引值return bestFeatureif __name__ == '__main__':dataSet, features = createDataSet()print("最优特征索引值:" + str(chooseBestFeatureToSplit(dataSet)))

由下图可知,色泽特征的信息熵与信息增益,计算过程无误

且由结果获知:最优特征为 纹理

四:决策树生成和修剪

刚才已经学习了从数据集构造决策树算法所需要的子功能模块,包括信息熵的计算和最优特征的选择,

简单回顾:

  • 标注原始数据集,然后基于最好的属性值划分数据集,
  • 第一次划分之后,数据集被向下传递到树的分支的下一个结点。
  • 在这个结点上,根据信息增益,我们可以再次划分数据。
  • 采用递归的原则处理数据,构建完整的树。

决策树生成算法递归地产生决策树,直到不能继续下去未为止。这样产生的树往往对训练数据的分类很准确,但对未知的测试数据的分类却没有那么准确,即出现过拟合现象

过拟合的原因在于学习时过多地考虑如何提高对训练数据的正确分类,从而构建出过于复杂的决策树。

解决这个问题的办法是考虑决策树的复杂度,对已生成的决策树进行简化。

我们在下一篇文章中着重论述这个问题~~

夏日炎炎,使用决策树去挑选西瓜(python实现)相关推荐

  1. 03-0004 CART决策树解决银行贷款问题(Python)

    CART决策树解决银行贷款问题-Python 1.问题描述 2.术语解释 2.1.CART 2.2.基尼系数 2.3.基尼指数 2.4.基尼系数增益 3.算法步骤 3.1语言描述 3.2举例说明 4. ...

  2. 机器学习-决策树之回归树python实战(预测泰坦尼克号幸存情况)(三)

    本文用通俗易懂的方式来讲解分类树中的回归树,并以"一维回归的图像绘制"和"泰坦尼克号幸存者预测"两个例子来说明该算法原理. 以下是本文大纲: 1 Decisio ...

  3. 决策树ID3代码(Python)

    决策树ID3代码(Python) 上一节介绍了决策树的递归算法框架(create),这一节将用Python语言实现一个小程序.代码和数据来源于<机器学习实战>Peter Harringto ...

  4. 面向对象程序设计课程设计:利用决策树方法判定西瓜质量

    目录 第一章课程设计的目的及要求 1.1课程设计目标 1.2课程设计实验环境 1.3课程设计的预备知识 1.4课程设计要求 第二章课程设计的内容 2.1c++语言程序设计--<利用决策树方法判定 ...

  5. 你会去挑选租赁手机吗?

    租赁手机你听过没?听过同享租房.同享租车.同享充电宝.同享雨伞......乃至同享租女友回家过年,能够说,在今日这样一个同享经济年代,除了老婆之外,其他的好像都能同享.但或许很多人没有听说过同享手机! ...

  6. 挑选西瓜(决策树实现)

    小鹿 一.决策树 二.相关概念 2.1 基尼指数 2.2 信息熵 三.ID3算法 3.1 概念 3.2 步骤 3.3 代码实现 四.C4.5算法 4.1 介绍 4.2 步骤 4.3 改动代码 五.CA ...

  7. 决策树案例:基于python的商品购买能力预测系统

    数据分析入门与实战  公众号: weic2c        http://www.cnblogs.com/baiboy/p/ml3.html 目录 1 决策树/判定树(decision tree) 2 ...

  8. 当女友让程序员去买西瓜...... | 每日趣闻

    女朋友对程序员说:"亲爱的,去超市买一个西瓜吧, 如果他们还有鸡蛋,再买20个." 结果程员带了21个西瓜回家. 女朋友愤怒地说:"为什么买21个西瓜回来"? ...

  9. 决策树入门【西瓜书】

    当一个有经验的老农看一个瓜是不是好瓜时,他可能会先看下瓜的颜色,一看是青绿的,心想有可能是好瓜:接着他又看了下根蒂,发现是蜷缩着的,老农微微点头,寻思着五成以上是好瓜:最后他又敲了下瓜,一听发出浑浊的 ...

最新文章

  1. 前有教授被骗千万,后有某重点高校青年教师晒出月薪900的工资条,大学老师工资待遇如何?...
  2. 【Python基础】Python 10 个习惯用法,看看你都知道不?
  3. X509Certificate2 本地正常,放到线上内部错误
  4. D. Bananas in a Microwave
  5. 检索有关计算机系统功能设计方面的文献,文献检索系统
  6. 报告称海归国内就业遇阻力 去年近三成海归实际年薪不足10万
  7. zabbix 脚本安装
  8. xcode模拟器不显示键盘解决方案
  9. WebSocket之JS发送二进制
  10. ios打开html页面关闭当前页面跳转,【已解决】怎么从iOS原生界面跳转回到html页面呢...
  11. 金士顿优盘突然出现写保护,无法删除更改数据也没有办法格式化
  12. 如何把打开方式换成计算机程序,文件的打开方式
  13. oracle rsm 进程,Oracle 10g 的后台进程
  14. 手机App开发行业前景怎么样?
  15. python tkinter手册_tkinter 中文文档
  16. c语言程序24转换12时间,C语言将24小时制转换为12小时制的方法
  17. 关于关于高博3d2d程序报错的改动
  18. TPMS胎压传感器烧录器
  19. 网络通信之传输层协议
  20. Leaflet中的L.geoJSON一个坑

热门文章

  1. 2014年注电考试心得
  2. Good Vegetable 4级算法题 分值: [320/3120] 问题: [8/78]
  3. 创建自定义类型转换器
  4. Springboot发送邮件教程
  5. 万向节死锁的个人理解
  6. Echarts——中国地图绘制
  7. ARM嵌入式开发总结
  8. Shell语言基本语法总结(4)正则表达式与文本处理之grep
  9. 联发科技与Orange合作加速物联网设备普及
  10. ds18b20温度转换指令_DS18B20温度传感器使用方法以及代码