Python机器学习实战(二)--决策树

本文介绍了Python机器学习中的决策树算法,详细讲解了决策树的构造过程,包括如何选择最优划分特征,计算香农熵,以及构建决策树的函数实现。通过示例展示了如何使用构造的决策树进行数据分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python机器学习实战(二)--决策树

 

         决策树是处理分类问题的一个非常直观的算法,决策树是一个类似流程图的树结构,树中的每个内部节点是一个特征的测试,每个分支是一个特性输出,每一个叶子节点是数据所属的一个类型。如下图结构(图片来源网络,仅供学习参考)

 

 

图中橙色节点即为数据类型:见,不见。

绿色节点表示对数据的某一特征进行测试,即对年龄,长相,收入,公务员几个特征进行测试。

每一个分支即表示了特征的具体值,即年龄值<=30>30

 

 

年龄是否大于30

长相是否丑

收入(高:1,中:0,低:-1

是否公务员

选择见面还是不见面

1

1

1

0

1

0

2

1

0

1

0

0

3

0

1

-1

0

0

4

0

0

1

0

1

5

0

1

0

1

0

6

0

0

0

1

1

7

0

0

0

0

0

 

以上是一个训练集示例。可以对应创建一个简单数据集。

 

决策树算法通过训练集确定一个最优的决策树。

 

 

 

 

下面介绍如何构造决策树

决策树的构造流程如下面伪代码所示

CreateBranch():

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

         Ifture return 类标签

         Else

                   继续划分数据集

                   创造分支节点

                            For每个划分的子集

                                     调用函数CreateBranch并增加结果到分支节点

                   Return分支节点

 

即判断数据子集是否分类完成,否的话,对每个数据子集继续进行划分。

这里显然可以看到一个问题:对一个数据集分割时,应该选择哪一个特性进行划分?

 

 

下面介绍选择最优划分特性的方法:

依据信息论的理论基础,划分数据集的大原则是:将无序的数据变得更加有序。

那么如何度量是否有序,即通过计算数据信息的香农熵

熵定义为信息的期望值,对一个数据集的每一个类型x的信息定义为:

L(x) = - log p(x)

P(x)为特征值为x的概率。

熵值即为所有类别的信息期望值:

H = -sum( p(x)*log p(x) )

即对每一个特征值计算- p(x) * L(x) ,然后求和。

 

下面代码给出了计算一个数据集的香农熵

 

def calcShannonEnt(dataSet):            #计算香农熵 dataSet为数据集
    numEntries = len (dataSet)          #计算特征数
    labelCounts = {}                    #创建一个类型:类型值的字典
    for featVet in dataSet:
        currentlabel = featVet[-1]      #选取类型值
        labelCounts[currentlabel] = labelCounts.get(currentlabel,0)+1
    shannonEnt = 0.0                    #初始化香农熵
    for key in labelCounts:             #对每个类型计算
        prob = float(labelCounts[key])/numEntries
        shannonEnt -= prob*log(prob,2)
    return shannonEnt

 

 

知道了划分的标准,下面就可以给出选择最好划分集的方式:

先给出一个划分函数,该函数对输入的指定数据集,划分特征,特征值,返回对应的数据子集,同时返回的数据子集中已删除输入特征这一信息。

代码如下:

def splitDataSet(dataSet,axis,value):           #分割数据集dataSet,返回第axis个特征值为value,同时删除该特征的数据
    retDataSet = []
    for featVet in dataSet:
        if featVet[axis] == value:              #判断第axis个特征是否为value
            reducedFeatVec = featVet[:axis]
            reducedFeatVec.extend(featVet[axis+1:])         #删除第axis个特征
            retDataSet.append(reducedFeatVec)               #将选择处理过的数据加入结果
    return retDataSet

 

 

最好划分函数,该函数对输入数据集返回一个最好特征的索引值,基本思想即遍历每一个特征,比较划分后的香农熵,选出最小值即可。

代码如下:

 

def chooseBestFeatureToSplit(dataSet):          #从dataSet数据集中选择最优的特性,返回特征的索引
    numFeatures = len(dataSet[0])-1             #计算特征数
    baseEntropy = calcShannonEnt(dataSet)       #计算初始数据香农熵
    bestInfoGain = 0.0                          #熵能减小的最大值
    bestFeature = -1                            #初始化最优特征索引为-1
    for i in range(numFeatures):                #对每一个特征计算分割后的香农熵
        newEntropy = 0.0
        for example in dataSet:
            featList = [example[i]]             #第i个特征的所有值的列表
        uniqueVals = set(featList)              #用集合表示第i个特征值的集合
        for value in uniqueVals:    
            subDataSet = splitDataSet(dataSet,i,value)
            prob = float(len(subDataSet))/len(dataSet)
            newEntropy += prob * calcShannonEnt(subDataSet)
        infoGain = baseEntropy - newEntropy
        if (infoGain > bestInfoGain):
            bestInfoGain = infoGain
            bestFeature = i   
    return bestFeature

 

 

 

 

另外针对对所有特征进行划分完后,数据依然不是同一个类别时,我们可以选择返回类别数最多的类别,如下面的函数所示:

 

def majorityCnt(classList):
    classCount = collections.defaultdic(int)
    for vote in classList:
        classCount[vote] += 1
    sortedclassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=Ture)
    return sortedclassCount[0][0]
    

 

 

接下来给出构造树的函数,函数输入参数为数据集和标签列表,标签列表包括数据集中所有特征的标签。函数返回一个字典树。

代码如下:

 

def createTree(dataSet,labels):
    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)
    bestFeature = chooseBestFeatureToSplit(dataSet)
    bestFeatureLabel = labels[bestFeature]
    myTree = {bestFeatureLabel:{}}
    del(labels[bestFeature])
    featureValues = [example[bestFeature] for example in dataSet]
    uniqueValues = set(featureValues)
    for value in uniqueValues:
        subLabels = labels[:]
        myTree[bestFeatureLabel][value] = createTree(splitDataSet(dataSet,bestFeature,value),subLabels)
    return myTree

 

 

以上就是构建一个决策树的过程

 

下面给出一个简单的测试,利用该决策树对数据进行分类

输入参数为决策树,特征标签列表,待分类数据,返回类别

函数中由决策树确定每次划分特征,可以通过对特征标签列表用index方法返回索引,进行确定数据中该特征的值。

代码如下:

def classify(inputTree,featLabels,testVec):
    firstStr = inputTree.keys()[0]
    secondDict = inputTree[firstStr]
    featIndex = featLabels.index(firstStr)
    key = testVec[featIndex]
    valueOfFeat = secondDict[key]
    if isinstance(valueOfFeat, dict): 
        classLabel = classify(valueOfFeat, featLabels, testVec)
    else: classLabel = valueOfFeat
    return classLabel

以上为决策树的一些主要内容


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值