[机器学习]决策树模型及实验

目录

一、算法概述

1.1决策树模型简介

1.2决策树的构造

二、信息熵

2.1信息熵的介绍

2.2信息熵的计算

三、划分选择

3..1 信息增益(ID3算法)

3.2信息增益率(C4.5算法)

3.3基尼系数(CART算法)

四、对决策树的剪枝

4.1剪枝

4.2预剪枝处理

4.3后剪枝处理

五、算法实现(ID3)

5.1准备数据集,并进行属性标注

5.2 计算信息熵

5.3按照给定的特征划分数据集

5.4选择最好的数据集划分方式

5.5 统计classList中出现次数最多的元素(类标签)

5.6创建决策树

5.7整体代码

六、以C4.5实现构建决策树

七、实验小结

7.1实验结果截图

7.2实验总结

7.3参考书籍


一、算法概述
1.1决策树模型简介

决策树(Decision Tree):一种分类和回归方法,即基于各种情况发生的所需条件构成决策树,以实现期望最大化的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。它的运行机制非常通俗易懂,因此被誉为机器学习中,最“友好”的算法。在分类问题中,表示基于特征对实例进行分类的过程,可以认为是if-then的集合,也可以认为是定义在特征空间与类空间上的条件概率分布。例如下图是对于西瓜问题的一个决策树:

一般,一棵决策树包含一个根结点、若干个内部结点和若干个叶结点;叶结点对应于决策结果,其他每个结点则对应于一个属性测试;每个结点包含的样本集合根据集合测试的结果被划分到子结点中;根结点包含样本全集。决策树学习的目的是为了产生一棵泛化能力强,即处理未见示例能力强的决策树,其基本流程遵循“分而治之”策略。

1.2决策树的构造

构造决策树通常有三个步骤:特征选择、决策树的生成、决策树的修剪。

决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得各个子数据集有一个最好的分类的过程。这一过程对应着对特征空间的划分,也对应着决策树的构建。

1) 开始:构建根节点,将所有训练数据都放在根节点,选择一个最优特征,按着这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。

2) 若这些子集已经能够被基本正确分类,则构建叶节点,并将这些子集分到所对应的叶节点去。

3)若还有子集不能够被正确的分类,那么就对这些子集选择新的最优特征,继续对其进行分割,构建相应的节点,如果递归进行,直至所有训练数据子集被基本正确的分类,或者没有合适的特征为止。

4)每个子集都被分到叶节点上,即都有了明确的类,这样就生成了一棵决策树。

决策树的生成是一个递归过程。在决策树算法中,有三种情形会导致递归返回:(1)当前结点包含的样本全属于同一类别,无需划分;(2)当前属性集为空,或所有样本在属性值上取值相同,无法划分;(3)当前结点包含的样本集合为空,不能划分。

过程:

首先,确定当前数据集上的决定性特征,为了得到该决定性特征,必须评估每个特征,完成测试之后,原始数据集就被划分为几个数据子集,这些数据子集会分布在第一个决策点的所有分支上,如果某个分支下的数据属于同一类型,则当前无序阅读的垃圾邮件已经正确的划分数据分类,无需进一步对数据集进行分割,如果不属于同一类,则要重复划分数据子集,直到所有相同类型的数据均在一个数据子集内。

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

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

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

信息熵(Information Entropy)是表示随机变量不确定性的度量,即物体内部的混乱程度。

2.2信息熵的计算

假设当前样本集合D中第k个样本所占的比例为p_{k}(k=1,2,...,|y|),则D的信息熵定义为

   Ent(D)=-\sum_{k=1}^{|y|}p_{k}log_{2}p_{k}

Ent(D)的值越小,则D的纯度越高。

三、划分选择
3..1 信息增益(ID3算法)

假定离散属性a有V个可能的取值{a^{1},a^{2},...,a^{V}},若使用a来对样本集D进行划分,则会产生V个分支结点,其中第v个分支结点包含了D中所有在a上取值为a^{V}的样本,记为D^{V}。根据信息熵公式可以计算出D^{V}的信息熵,再考虑到不同的分支结点所包含的样本数不同,给分支结点赋予权重|D^{V}|/|D|,即样本数越多的分支结点的影响越大,于是可以计算出用属性a对样本集D进行划分所获得的“信息增益”

Gain(D,a)=Ent(D)-\sum_{v=1}^{V}\frac{|D^{v}|}{|D|}Ent(D^{v})

一般而言,信息增益越大,意味着使用属性a来进行划分所获得的“纯度提升”越大。著名的ID3决策树学习算法[Quinlan,1986]就是以信息增益作为准则来选择划分属性。但是ID3 仅仅适用于二分类问题。

3.2信息增益率(C4.5算法)

C4.5 克服了 ID3 仅仅能够处理离散属性的问题,以及信息增益偏向选择取值较多特征的问题。信息增益准则对可取数目较多的属性有所偏好,为减少这种偏好可能带来的不利影响,C4.5决策树算法[Quinlan,1993]使用“增益率”来选择最优划分属性。增益率定义为

Gain ratio(D,a)=\frac{Gain(D,a)}{IV(a)}

其中         IV(a)=-\sum_{v=1}^{V}\frac{|D^{v}|}{|D|}log_{2}\frac{|D^{v}|}{|D|}

IV(a)称为属性a的“固有值”。属性a的可能取值数目越多(即V越大),则IV(a)的值通常会越大。

但是,增益率准则对可取值数目较少的属性有所偏好。

3.3基尼系数(CART算法)

CART决策树使用“基尼指数”来选择划分属性,数据集D的纯度可用基尼值来度量:

Gini(D)=\sum_{k=1}^{|y|}\sum_{k^{'}\neq k}^{}p_{k}p^{k^{'}}=1-\sum_{k=1}^{|y|}p_{k}^{2}

CART 与 ID3,C4.5 不同之处在于 CART 生成的树必须是二叉树。直观来说,Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率。因此,Gini(D)越小,则数据集D的纯度越高。基尼指数越大,集合不确定性越高,不纯度也越大。属性a的基尼指数定义为

Gini index(D,a)=\sum_{v=1}^{V}\frac{|D^{v}|}{|D|}Gini(D^{v})

于是,在候选属性集合A中,选择那个使得划分后基尼指数最小的属性作为最优划分属性,即a_{*}=arg min_{a\epsilon A}Gini index(D,a)

四、对决策树的剪枝
4.1剪枝

剪枝(pruning):从已经生成的树上裁掉一些子树或叶节点,并将其根节点或父节点作为新的叶子节点,从而简化分类树模型。

实现方式:极小化决策树整体的损失函数或代价函数来实现

决策树学习的损失函数定义为:

C_{\alpha }(T)=\sum_{t=1}^{|T|}N_{t}H_{t}(T)+\alpha |T|

其中,T表示这棵子树的叶子结点,H_{t}(T)表示第t 个叶子的熵,N_{t}表示该叶子所含的训练样例的个数,|T|表示子树的叶子结点的个数,α表示惩罚系数。

剪枝就是当α 确定时,选择损失函数最小的模型,即损失函数最小的子树。

当α值确定时,子树越大,往往与训练数据的拟合越好,但是模型的复杂度越高;子树越小,模型的复杂度就越低,但是往往与训练数据的拟合不好
损失函数正好表示了对两者的平衡。

决策树算法很容易过拟合(overfitting),剪枝算法就是用来防止决策树过拟合,提高泛化性能的方法。

4.2预剪枝处理

预剪枝是在决策树生成过程中,对每个结点在划分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划分并将当前结点标记为叶结点。

4.3后剪枝处理

后剪枝是从训练集生成一棵完整的决策树,然后自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化性能提升,则将该子树替换为叶结点。

五、算法实现(ID3)
5.1准备数据集,并进行属性标注
表一  贷款申请样本数据表

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

  • 年龄:0代表青年,1代表中年,2代表老年;
  • 有工作:0代表否,1代表是;
  • 有自己的房子:0代表否,1代表是;
  • 信贷情况:0代表一般,1代表好,2代表非常好;
  • 类别(是否给贷款):no代表否,yes代表是。
5.2 计算信息熵

首先计算数据集中实例的总数。接着创建数据字典,它的键值是最后一列的数值。若当前键值不存在,则拓展字典并将当前键值加入字典。每个键值记录了当前类别出现的次数。最后,使用所有类标签的发生频率计算类别出现的概率。用这个概率计算出熵。

def calcShannonEnt(dataSet):
    #返回数据集行数
    numEntries=len(dataSet)
    #保存每个标签(label)出现次数的字典
    labelCounts={}
    #对每组特征向量进行统计
    for featVec in dataSet:
        currentLabel=featVec[-1]                     #提取标签信息
        if currentLabel not in labelCounts.keys():   #如果标签没有放入统计次数的字典,添加进去
            labelCounts[currentLabel]=0
        labelCounts[currentLabel]+=1                 #label计数

    shannonEnt=0.0                                   #经验熵
    #计算经验熵
    for key in labelCounts:
        prob=float(labelCounts[key])/numEntries      #选择该标签的概率
        shannonEnt-=prob*log(prob,2)                 #利用公式计算
    return shannonEnt                                #返回经验熵
5.3按照给定的特征划分数据集

分类算法除了需要测量信息熵,还需要划分数据集,度量划分数据集的熵,以便判断当前是否正确地划分了数据集。我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的划分方式。

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
5.4选择最好的数据集划分方式

计算整个数据集的原始信息熵,保存最初的无序度量值,用于与划分完之后的数据集计算的熵值进行比较。遍历当前特征的所有唯一属性值,对每个唯一属性值划分一次数据集,然后计算数据集的新熵值,并对所有唯一特征值得到的熵求和。最后比较所有特征中的信息增益,返回最好特征划分的索引值。

#选择信息增益最大特征的索引值
def chooseBestFeatureToSplit(dataSet):
    #特征数量
    numFeatures = len(dataSet[0]) - 1
    #计数数据集的香农熵
    baseEntropy = calcShannonEnt(dataSet)
    #信息增益
    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划分后的子集
            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
5.5 统计classList中出现次数最多的元素(类标签)

通过分类名称的列表,创建键值为classList中唯一值的数据字典,字典对象存储了classList中每个类标签出现的频率,利用operator操作键值排序字典,并返回出现次数最多的分类名称。

def majorityCnt(classList):
    classCount={}
    #统计classList中每个元素出现的次数
    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]
5.6创建决策树

递归函数的第一个停止条件是当所有的类标签完全相同,则直接返回该类标签。第二个停止条件是使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。代码中字典变量myTree存储了树的所有信息,当前数据集选取的最好特征存储在变量bestFeat中,得到列表包含的所有属性值。

def createTree(dataSet,labels,featLabels):
    #取分类标签(是否放贷:yes or no)
    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
5.7整体代码
from math import log
import operator

#创建测试数据集(dataSet:数据集;labels:分类属性)
def createDataSet():
    # 数据集
    dataSet=[[0, 0, 0, 0, 'no'],
            [0, 0, 0, 1, 'no'],
            [0, 1, 0, 1, 'yes'],
            [0, 1, 1, 0, 'yes'],
            [0, 0, 0, 0, 'no'],
            [1, 0, 0, 0, 'no'],
            [1, 0, 0, 1, 'no'],
            [1, 1, 1, 1, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [2, 0, 1, 2, 'yes'],
            [2, 0, 1, 1, 'yes'],
            [2, 1, 0, 1, 'yes'],
            [2, 1, 0, 2, 'yes'],
            [2, 0, 0, 0, 'no']]
    #分类属性
    labels=['年龄','有工作','有自己的房子','信贷情况']
    #返回数据集和分类属性
    return dataSet,labels

#计算数据集的经验熵
def calcShannonEnt(dataSet):
    #返回数据集行数
    numEntries=len(dataSet)
    #保存每个标签(label)出现次数的字典
    labelCounts={}
    #对每组特征向量进行统计
    for featVec in dataSet:
        currentLabel=featVec[-1]                     #提取标签信息
        if currentLabel not in labelCounts.keys():   #如果标签没有放入统计次数的字典,添加进去
            labelCounts[currentLabel]=0
        labelCounts[currentLabel]+=1                 #label计数
    shannonEnt=0.0                                   #经验熵
    #计算经验熵
    for key in labelCounts:
        prob=float(labelCounts[key])/numEntries      #选择该标签的概率
        shannonEnt-=prob*log(prob,2)                 #利用公式计算
    return shannonEnt                                #返回经验熵

#根据给定特征划分数据集
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

#选择信息增益最大特征的索引值
def chooseBestFeatureToSplit(dataSet):
    #特征数量
    numFeatures = len(dataSet[0]) - 1
    #计数数据集的香农熵
    baseEntropy = calcShannonEnt(dataSet)
    #信息增益
    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划分后的子集
            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

#统计classList中出现次数最多的元素(类标签)
def majorityCnt(classList):
    classCount={}
    #统计classList中每个元素出现的次数
    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):
    #取分类标签(是否放贷:yes or no)
    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

"""
使用决策树进行分类
Parameters:
    inputTree;已经生成的决策树
    featLabels:存储选择的最优特征标签
    testVec:测试数据列表,顺序对应最优特征标签
Returns:
    classLabel:分类结果
"""
def classify(inputTree,featLabels,testVec):
    #获取决策树节点
    firstStr=next(iter(inputTree))
    #下一个字典
    secondDict=inputTree[firstStr]
    featIndex=featLabels.index(firstStr)

    for key in secondDict.keys():
        if testVec[featIndex]==key:
            if type(secondDict[key]).__name__=='dict':
                classLabel=classify(secondDict[key],featLabels,testVec)
            else: classLabel=secondDict[key]
    return classLabel

if __name__=='__main__':
    print('使用ID3算法')
    dataSet,labels=createDataSet()
    featLabels=[]
    myTree=createTree(dataSet,labels,featLabels)
    print(myTree)
    #测试数据
    testVec=[0,1]
    result=classify(myTree,featLabels,testVec)

    if result=='yes':
        print('测试数据的预测结果:放贷')
    if result=='no':
        print('测试数据的预测结果:不放贷')
六、以C4.5实现构建决策树

与ID3类似,只不过此时需要将信息增益改为信息增益率,修改calcShannonEnt函数以计算信息增益率,其余过程与ID3一致。

from math import log
import operator

def createDataSet():
    dataSet = [[0, 0, 0, 0, 'no'],
               [0, 0, 0, 1, 'no'],
               [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],
               [0, 0, 0, 0, 'no'],
               [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'],
               [1, 1, 1, 1, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [2, 0, 1, 2, 'yes'],
               [2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],
               [2, 1, 0, 2, 'yes'],
               [2, 0, 0, 0, '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

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

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGainRatio = 0.0
    bestFeature = -1
    for i in range(numFeatures):
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        newEntropy = 0.0
        IV = 0.0
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)
            prob = len(subDataSet) / float(len(dataSet))
            newEntropy += prob * calcShannonEnt(subDataSet)
            IV -= prob * log(prob, 2)
        infoGain = baseEntropy - newEntropy
        if (IV == 0):  # 防止除数为0的情况
            IV = 1
        infoGainRatio = infoGain / IV
        print("第%d个特征的增益率为%.3f" % (i, infoGainRatio))
        if (infoGainRatio > bestInfoGainRatio):
            bestInfoGainRatio = infoGainRatio
            bestFeature = i
    return bestFeature

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

def classify(inputTree, featLabels, testVec):
    firstStr = next(iter(inputTree))
    secondDict = inputTree[firstStr]
    featIndex = featLabels.index(firstStr)
    for key in secondDict.keys():
        if testVec[featIndex] == key:
            if type(secondDict[key]).__name__ == 'dict':
                classLabel = classify(secondDict[key], featLabels, testVec)
            else:
                classLabel = secondDict[key]
    return classLabel

if __name__ == '__main__':
    print('使用C4.5算法')
    dataSet, labels = createDataSet()
    featLabels = []
    myTree = createTree(dataSet, labels, featLabels)
    print(myTree)
    #测试数据
    testVec=[0,1]
    result=classify(myTree,featLabels,testVec)

    if result=='yes':
        print('测试数据的预测结果:放贷')
    if result=='no':
        print('测试数据的预测结果:不放贷')
七、实验小结
7.1实验结果截图

以ID3实现的结果为:

根据计算,选择信息增益最大的A2作为节点的特征,由于其有两个取值可能,所以引出两个子节点:

①对应“是”(有工作),包含三个样本,属于同一类,所以是一个叶子节点,类标记为“是”

②对应“否”(无工作),包含六个样本,输入同一类,所以是一个叶子节点,类标记为“否”

这样就生成一个决策树,该树只用了两个特征(有两个内部节点),生成的决策树如下图所示:

以C4.5实现的结果为:

7.2实验总结

  通过本次实验学习了对决策树的创建,决策树算法主要包括三个部分:特征选择、树的生成、树的剪枝。常用算法有 ID3、C4.5、CART。其中,特征选择的关键是准则:信息增益、信息增益比、Gini 指数;决策树的生成通常是利用信息增益最大、信息增益比最大、Gini 指数最小作为特征选择的准则。从根节点开始,递归的生成决策树。相当于是不断选取局部最优特征,或将训练集分割为基本能够正确分类的子集;决策树的剪枝是为了防止树的过拟合,增强其泛化能力。包括预剪枝和后剪枝。

7.3参考书籍

《机器学习》 周志华

《机器学习实战》     Peter Harrington

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值