机器学习——决策树

本文详细介绍了决策树中的ID3(信息增益)和CART(基尼指数)算法,包括如何构建决策树、特征选择过程以及在Python中的实现示例。ID3更倾向于信息增益,而CART使用基尼系数来评估纯度。
摘要由CSDN通过智能技术生成

1.概述    

        决策树(Decision Tree)是一种基本的分类与回归方法,决策树模型呈树形结构,在分类问题中,表示基于特征对数据进行分类的过程。它可以认为是if-then规则的集合。每个内部节点表示在属性上的一个测试,每个分支代表一个测试输出,每个叶节点代表一种类别。

2.如何构建决策树

        决策树构建的基本步骤如下:

                1. 开始,所有记录看作一个节点

                2. 遍历每个特征的每一种分裂方式,找到最好的分裂特征(分裂点)

                3. 分裂成两个或多个节点

                4. 对分裂后的节点分别继续执行2-3步,直到每个节点足够“纯”为止

        具体实践中,到底选择哪个特征作为当前分裂特征,常用的有下面三种算法:

               信息增益(ID3)

                        假设训练数据集D和特征A,根据如下步骤计算信息增益:

                        第一步:计算数据集D的经验熵:

                                

                        其中,|{C_k}|为第k类样本的数目,|D|为数据集D的数目。

                        第二步:计算特征A对数据集D的经验条件熵H(D|A):

                        

                        第三步:计算信息增益:

                        

       一般而言,信息增益越大,则意味着使用属性A来进行划分所获得的“纯度提升” 越大。因此,我们可使用信息增益来进行决策树的划分属性选择。ID3决策树学习算法就是以信息增益为准则来选择划分属性的。

                信息增益率(C4.5)

                        特征A对于数据集D的信息增益比定义为:

                        

                        其中,称为数据集D关于A的取值熵。增益率准则就可取值数目较少的属性有所偏好,因此,C4.5算法并不是直接选择增益率最大的候选划分属性,而是使用了一个启发式:先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。

                基尼指数(CART)

                        分类问题中,假设有K个类,样本点属于k的概率{p_k},则概率分布的基尼指数:

                        

                        二分类问题:

                        对给定的样本集合D,基尼指数:

                        

                        CART决策树使用“基尼指数”来选择划分属性。数据集D的纯度可用基尼值来度量,Gini(D)越小,则数据集的纯度越高。CART生成的是二叉树,计算量相对来说不是很大,可以处理连续和离散变量,能够对缺失值进行处理。

3.python实现

        3.1 数据集

        

        有四个特征:

        年龄:青年0,中年1,老年2

        工作:否0,是1

        有自己的房子:否0,是1

        信贷情况:一般0,好1,非常好2

        

# 创建测试数据集
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 = ['年龄', '有工作', '有自己的房子', '信贷情况']  # 分类属性

        3.2 构建决策树

                3.2.1 ID3算法

                        

# 计算给定数据集的熵
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)  # 以2为底求对数
    return shannonEnt  # 返回经验熵


# 按照给定特征划分数据集
def splitDataSet(dataSet, axis, value):  # dataSet:带划分数据集   axis:划分数据集的特征   value:需要返回的特征的值
    retDataSet = []  # 创建新的list对象
    for featVec in dataSet:  # 遍历元素
        if featVec[axis] == value:  # 符合条件的,抽取出来
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis + 1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet


# 选择最好的数据集划分方式 ID3算法——信息增益
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]  # 获取dataSet的第i个所有特征
        uniqueVals = set(featList)  # 创建set集合{},元素不可重复
        newEntropy = 0.0  # 信息熵
        for value in uniqueVals:  # 循环特征的值
            subDataSet = splitDataSet(dataSet, i, value)  # subDataSet划分后的子集
            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 majorityCnt(classList):
    classCount = {}  # 统计classList中每个类标签出现的次数
    for vote in classList:
        if vote not in classCount.keys():
            classCount[vote] = 0
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.iteritems(), 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

        结果测试:

{'有自己的房子': {0: {'有工作': {0: 'no', 1: {'年龄': {0: {'信贷情况': {'no': 'no', 'yes': 'yes'}}, 2: 'yes'}}}}, 1: {'年龄': {0: {'信贷情况': {'no': 'no', 'yes': 'yes'}}, 1: 'yes', 2: 'yes'}}}}

        3.2.2 CART算法

​
# 计算概率
def calcProbabilityEnt(dataSet):
    numEntries = len(dataSet)                # 数据集大小
    feaCounts = 0                            # 特征数量
    feature = dataSet[0][len(dataSet[0]) - 1]
    for feaVec in dataSet:
        if feaVec[-1] == feature:
            feaCounts += 1
    probabilityEnt = float(feaCounts) / numEntries    #概率= 特征数量/数据集大小
    return probabilityEnt
 
# 选择最好的数据集划分方式 CAR算法——基尼指数
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1                     #特征数量
    if numFeatures == 1:
        return 0
    bestGini = 1                                          #最佳基尼指数
    bestFeature = -1                                      #最优的划分特征,初始化为-1
    for i in range(numFeatures):  # 遍历所有的特征
        featList = [example[i] for example in dataSet]
        feaGini = 0  # 定义特征的值的基尼系数
        uniqueVals = set(featList)                        #获取该特征下的所有不同的值
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)  #划分数据集
            prob = len(subDataSet) / float(len(dataSet))
            probabilityEnt = calcProbabilityEnt(subDataSet)
            feaGini += prob * (2 * probabilityEnt * (1 - probabilityEnt))
        if (feaGini < bestGini):
            bestGini = feaGini                            #基尼指数
            bestFeature = i                               #记录基尼指数最小的索引值
    return bestFeature

​

        结果测试:

{'有自己的房子': {0: {'有工作': {0: 'no', 1: {'年龄': {0: {'信贷情况': {1: 'yes'}}, 2: 'yes'}}}}, 1: {'年龄': {0: {'有工作': {1: {'信贷情况': {0: 'yes'}}}}, 1: 'yes', 2: 'yes'}}}}

        

4.总结

                ID3算法:ID3算法核心就是“最大信息熵增益” 原则选择划分当前数据集的最好特征。而且对于连续型特征,比如长度,密度都是连续值,无法在ID3运用,利用信息熵划分属性,会对倾向于可取值数目较多的属性。没有考虑过拟合的问题。

                CART算法:CART算法使用基尼系数来代替信息增益比,基尼系数代表了模型的不纯度,基尼系数越小,则不纯度越低,特征越好。这和信息增益及信息增益率是相反的。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
决策树算法是一种广泛应用于分类和回归的机器学习算法,它基于树形结构对样本进行分类或预测。决策树算法的主要思想是通过一系列的判断来对样本进行分类或预测。在决策树中,每个节点表示一个属性或特征,每个分支代表该属性或特征的一个取值,而每个叶子节点代表一个分类或预测结果。 决策树算法的训练过程主要包括以下步骤: 1. 特征选择:根据某种指标(如信息增益或基尼系数)选择最优的特征作为当前节点的分裂属性。 2. 决策树生成:根据选择的特征将数据集分成若干个子集,并递归地生成决策树。 3. 剪枝:通过剪枝操作来提高决策树的泛化性能。 决策树算法的优点包括易于理解和解释、计算复杂度较低、对缺失值不敏感等。但是,决策树算法也存在一些缺点,如容易出现过拟合、对离散数据敏感等。 下面是一个决策树算法的案例:假设我们要根据一个人的年龄、性别、教育程度和职业预测其收入水平(高于或低于50K)。首先,我们需要将这些特征进行编码,将其转换为数值型数据。然后,我们可以使用决策树算法对这些数据进行训练,并生成一个决策树模型。最后,我们可以使用该模型对新的数据进行分类或预测。例如,根据一个人的年龄、性别、教育程度和职业,我们可以使用决策树模型预测该人的收入水平。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值