机器学习-决策树(一)

一、决策树概述

1.决策树的概念:

        分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型:内部结点和叶节点。内部结点表示一个特征或属性,叶节点表示一个类。如:

上图中长方形代表判断模块,椭圆形代表终止模块,表示已经得出结论,可以终止运行。从判断模块中引出的箭头是分支,它可以到达另一个模块。

 2.决策树的优缺点及适用范围:

优点:计算复杂度不高,数据形式容易理解,对中间值的缺失不敏感,可以处理一些不相关的特征数据。

缺点:可能会产生过度匹配的问题。

适用数据类型:数值型和标称型。

二、决策树的构造

1.流程:

(1)评估每个特征,找到在当前数据集上划分数据分类时起决定作用的特征。并以此决定性的特征将原始数据集划分为几个数据子集,使得这些数据子集有一个当前条件下最好的分类。

(2)将这些数据子集分到第一个决策点的所有分支上。

(3)如果某分支下的数据属于同一个类型,则无需进一步对数据集进行划分。

(4)如果某分支下的数据不属于同一个类型,则重复划分数据子集的过程。方法与划分原始数据集类似,直到所有具有相同数据类型的数据都处于一个数据子集内。

(5)这样就生成了一颗决策树。

2.创建分支的伪代码 createBranch() 如下所示:

检测数据集中每个子项是否属于同一类:

If so return 类标签:
Else
     寻找划分数据集的最好特征
     划分数据集
     创建分支节点
         for 每个划分的子集
             调用函数createBranch()并增加返回结果到分支节点中
     return 分支节点

3.划分选择:

        决策树学习的关键在于如何选择最优划分属性,本节使用ID3算法来划分数据集,该算法处理如何划分数据集,何时停止划分数据集。

4.信息增益:

        信息增益,即在划分数据集之前之后信息发生的变化。知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。

        熵定义为信息的期望值,如果待分类的事物可能划分在多个类之中,则符号 x_{i}的信息定义为:

l(x_{i})= -{log_{2}{p(x_{i})} }

​其中,p(x_{i})是选择该分类的概率,即p(x_{i}) = P(X=x_{i} )。  

        为了计算熵,我们需要计算所有类别所有可能值所包含的信息期望值,通过下式得到:

H= {-\textstyle \sum_{i=1}^{n}p(x_{i})\log_{2}{p(x_{i})} }

其中,n为分类数目。随机变量的不确定性就越大,熵越大。
 

5.数据集的准备:

数据集如下图:

 对数据集进行属性标注:

  • 家庭收入:0代表一般,1代表较差,2代表很差;
  • 是否努力:0代表否,1代表是;
  • 平时生活状况:0代表良好,1代表一般;
  • 类别(是否通过):yes代表是,no代表否。

6.编写代码:

(1)计算数据集的信息熵

from math import log

def creatDataSet():
    # 数据集
    dataSet=[[0, 1, 0, 'no'],
             [0, 0, 0, 'no'],
             [0, 0, 1, 'no'],
             [0, 0, 0, 'no'],
             [0, 1, 1, 'yes'],
             [1, 1, 0, 'yes'],
             [1, 1, 1, 'yes'],
             [1, 0, 0, 'no'],
             [1, 1, 0, 'yes'],
             [1, 0, 1, 'no'],
             [1, 1, 1, 'yes'],
             [2, 1, 0, 'yes'],
             [2, 1, 0, 'yes'],
             [2, 1, 1, 'yes'],
             [2, 0, 1, 'no']]
    # 分类属性
    labels=['家庭收入','是否努力','平时生活状况']
    # 返回数据集和分类属性
    return dataSet,labels


# 计算给定数据集的香农熵
def calcShannonEnt(dataSet):
    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.0  
    for key in labelCounts:  
        prob=float(labelCounts[key])/numEntries      
        shannonEnt-=prob*log(prob,2) 
    return shannonEnt   

(2)编写代码划分数据集

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
        print("第%d个特征的增益为%.3f" % (i, infoGain))  
        if (infoGain > bestInfoGain):
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature


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

(3)递归构建决策树

def majorityCnt(classList):
    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,featLabels):
    classList=[example[-1] for example in dataSet]
    if classList.count(classList[0])==len(classList):
        return classList[0]
    if len(dataSet[0])==1:
        return majorityCnt(classList)
    bestFeat=chooseBestFeatureToSplit(dataSet)
    bestFeatLabel=labels[bestFeat]
    featLabels.append(bestFeatLabel)
    myTree={bestFeatLabel:{}}
    del(labels[bestFeat])
    featValues=[example[bestFeat] for example in dataSet]
    uniqueVls=set(featValues)
    for value in uniqueVls:
        myTree[bestFeatLabel][value]=createTree(splitDataSet(dataSet,bestFeat,value),
                                               labels,featLabels)
    return myTree

(4)测试运行

if __name__=='__main__':
    dataSet,labels=creatDataSet()
    featLabels=[]
    myTree=createTree(dataSet,labels,featLabels)
    print(myTree)

(5)运行结果

7.决策树的图形表示:

8.实验总结:

        通过比较数据集中的数据,可以看出数据集中的所有数据都能代入决策树。通过该决策树,将复杂的数据集变得易于理解。

9.参考教材:

机器学习实战

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值