机器学习之决策树介绍

简介

什么是决策树

        决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。决策树(Decision Tree)有以下特点:

  1. 决策树是在已知各种情况发生概率的基础上,通过构建决策树来进行分析的一种方式,是一种直观应用概率分析的一种图解法;
  2. 决策树是一种预测模型,代表的是对象属性与对象值之间的映射关系;
  3. 决策树是一种树形结构,其中每个内部节点表示一个属性的测试,每个分支表示一个测试输出,每个叶节点代表一种类别;
  4. 决策树是一种非常常用的有监督的分类算法。

决策过程

        决策树的决策过程就是从根节点开始,测试待分类项中对应的特征属性,并按照其值选择输出分支,直到叶子节点,将叶子节点的存放的类别作为决策结果。

决策树分类

类别分类:分类树和回归树

        分类树用于分类标签值,回归树用于预测连续值。常用算法有ID3、C4.5、CART等

特征属性分类:离散型和连续型

构建决策树步骤

  1. 将所有的特征看成一个一个的节点;
  2. 遍历每个特征的每一种分割方式,找到最好的分割点;将数据划分为不同的子节点,eg: N1、N2…Nm;计算划分之后所有子节点的’纯度’信息;
  3. 对第二步产生的分割,选择出最优的特征以及最优的划分方式;得出最终的子节点: N1、N2…Nm
  4. 对子节点N1、N2…Nm分别继续执行2-3步,直到每个最终的子节点都足够’纯’。

在这里插入图片描述

决策树算法效果评估

决策树的损失函数

在这里插入图片描述
        loss值越小,算法效果越好!

决策树生成算法以及比较

ID3算法

简介

        ID3算法是决策树的一个经典的构造算法,内部使用信息熵以及信息增益来进行构建;每次迭代选择信息增益最大的特征属性作为分割属性。
在这里插入图片描述H(D):信息熵
Gain:某特征的信息增益

优缺点

优点 缺点
1.决策树构建速度快;2.实现简单,易于理解 1.计算依赖于特征数目较多的特征,而属性值最多的属性并不一定最优;2.ID3算法不是递增算法;3.ID3算法是单变量决策树;4.抗噪性差;5.只适合小规模数据集

C4.5算法

简介

        C4.5算法使用信息增益率来取代ID3算法中的信息增益,在树的构造过程中会进行剪枝操作进行优化;能够自动完成对连续属性的离散化处理;
在这里插入图片描述H(D):信息熵
Gain:某特征的信息增益
Gain_ratio(A):某特征的信息增益率

优缺点

优点 缺点
1.易于理解;2.准确率较高;3.实现简单 1.效率较低;2.只适合小规模数据集

CART(Classification And Regression Tree)

简介

        CART(Classification And Regression Tree,分类回归树)算法是使用GINI增益作为分割属性选择的标准,选择GINI增益最大的作为当前数据集的分割属性;可用于分类和回归两类问题。CART构建是二叉树
在这里插入图片描述

ID3、C4.5、CART分类树算法总结

  1. ID3和C4.5算法均只适合在小规模数据集上使用
  2. ID3和C4.5算法都是单变量决策树
  3. 当属性值取值比较多的时候,最好考虑C4.5算法,ID3得出的效果会比较差
  4. 决策树分类一般情况只适合小数据量的情况(数据可以放内存)
  5. CART算法是三种算法中最常用的一种决策树构建算法。
  6. 三种算法的区别仅仅只是对于当前树的评价标准不同而已,ID3使用信息增益、
  7. C4.5使用信息增益率、CART使用基尼系数。
  8. CART算法构建的一定是二叉树,ID3和C4.5构建的不一定是二叉树

决策树案例

构造相关数据特征

在这里插入图片描述

扫描二维码关注公众号,回复: 6118915 查看本文章

代码实现

这里使用的是ID3算法

from math import log
import operator

def 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 shannonEnt

def createDataSet1():    # 创造示例数据
    dataSet = [['长', '粗', '男'],
               ['短', '粗', '男'],
               ['短', '粗', '男'],
               ['长', '细', '女'],
               ['短', '细', '女'],
               ['短', '粗', '女'],
               ['长', '粗', '女'],
               ['长', '粗', '女']]
    labels = ['头发','声音']  #两个特征
    return dataSet,labels

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
    bestFeature = -1
    for i in range(numFeatures):
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        newEntropy = 0
        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 bestFeature

def 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):
    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]
    myTree={bestFeatLabel:{}} #分类结果以字典形式保存
    del(labels[bestFeat])
    featValues=[example[bestFeat] for example in dataSet]
    uniqueVals=set(featValues)
    for value in uniqueVals:
        subLabels=labels[:]
        myTree[bestFeatLabel][value]=createTree(splitDataSet\
                            (dataSet,bestFeat,value),subLabels)
    return myTree


if __name__=='__main__':
    dataSet, labels=createDataSet1()  # 创造示列数据
    print(createTree(dataSet, labels))  # 输出决策树模型结果

输出结果

{'声音': {'细': '女', '粗': {'头发': {'短': '男', '长': '女'}}}}

结果说明:首先按声音分类,声音细为女生;然后再按头发分类:声音粗,头发短为男生;声音粗,头发长为女生。

猜你喜欢

转载自blog.csdn.net/weixin_44327656/article/details/89298244