机器学习之决策树(一)

1、算法介绍
决策树是一种基本的分类和回归方法,决策树模型呈树形结构,在分类问题中,表示基于特征对实例进行分类的过程。决策树学习通常包括三个步骤:特征选择、决策树的生成和决策树的修剪。决策树的本质是从训练数据集中归纳出一组分类规则。本文主要是对决策树的ID3算法的介绍,后文会介绍C4.5和CART算法。


2、算法优缺点
优点:计算复杂度不高,结果易于理解,对于中间值的缺失不敏感,可以处理不相关特征。
缺点:可能会产生过拟合问题。
适用于标称型(ID3和C4.5)和数值型(CART算法)


3、特征选择
熵:
设X是一个取有限个值的离散随机变量,其概率分布为:

则随机变量X的熵定义为:

条件熵:
条件熵H(Y|X):表示在己知随机变量X的条件下随机变量Y的不确定性,定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

信息增益:
信息增益:特征A对训练数据集D的信息增益,g(D,A), 定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即g(D,A)=H(D)-H(D|A)
因此,选择信息增益最优,也即是信息增益最大的特征作为节点,然后再循环构建决策树。


4、数学例子

首先计算熵:
样本总共有15条记录,其中不买的有5条记录,买的有10条记录。
所以H(D) = -5/15log2(5/15)-10/15log2(10/15) = 0.92
再计算条件熵:
年龄:青年有5条记录,其中不买的为3条,买的记录为2条
   中年有4条记录,其中不买的为0条,买的记录为4条
   老年有6条记录,其中不买的为2条,买的记录为4条
   则条件熵为5/15*(-3/5*log(3/5,2)-2/5*log(2/5,2)) + 4/15*(0 - 4/4*log(4/4,2))    + 6/15*(-2/6*log(2/6,2)-4/6*log(4/6,2)) = 0.69
   所以年龄的信息增益为0.23
当特征值取收入,学生,信誉时,信息增益分别为:0.03,0.17,0.03
故选择年龄为第一次迭代的节点,然后再重复上述步骤,最后完成树的构建。


5、ID3代码实现

from sklearn.model_selection import train_test_split
import math

def getData():
    #获取数据集,数据来自uci的mushroom.data
    data_x = [];data_y = [];train = []
    with open(‘mushroom.data‘) as f:
        for line in f:
            line = line.strip().split(‘,‘)
            data_x.append(line[1:])
            data_y.append(line[0])
    train_x,test_x,train_y,test_y = train_test_split(data_x,data_y,test_size=0.8,random_state=0)
    for x,y in zip(train_x,train_y):
        x.append(y)
        train.append(x)
    return train,test_x,test_y

def calI(prob):
    ‘‘‘封装对数计算公式‘‘‘
    I = 0.0
    for p in prob:
        if p != 0:  # p=0时不能计算log
            I += -p * math.log(p, 2)
    return I

def calInfo(dataSet):
    ‘‘‘计算信息熵‘‘‘
    values = [value[-1] for value in dataSet]
    uniqueVal = set(values)
    prob = []
    for val in uniqueVal:
        #计算p
        prob.append(values.count(val) / float(len(values)))
    return calI(prob)

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)#把符合返回的值那些返回(axis那一列不添加)
    return retDataSet

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1      #计算特征的数目
    baseEntropy = calInfo(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 * calInfo(subDataSet)
        infoGain = baseEntropy - newEntropy     #计算信息增益
        if (infoGain > bestInfoGain):       #选择最好的信息增益
            bestInfoGain = infoGain
            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=lambda x:x[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

def classify(inputTree,featLabels,testVec):
    firstStr = list(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

def correct_rate(test_y,predict_y):
    #返回测试集的正确率
    length = len(test_y)
    score = 0
    for num in range(length):
        if test_y[num] == predict_y[num]:
            score += 1
    rate = str((score/float(length)) *100) + ‘%‘
    return rate

if __name__ == ‘__main__‘:
    train,test_x,test_y = getData()
    labels = [‘cap-shape‘,‘cap-surface‘,‘cap-color‘,‘bruises‘,‘odor‘,‘gill-attachment‘,‘gill-spacing‘,‘gill-size‘,‘gill-color‘,‘stalk-shape‘,‘stalk-root‘,‘stalk-surface-above-ring‘,‘stalk-surface-below-ring‘,‘stalk-color-above-ring‘,‘stalk-color-below-ring‘,‘veil-type‘,‘veil-color‘,‘ring-number‘,‘ring-type‘,‘spore-print-color‘,‘population‘,‘habitat‘]
    label = labels[:]
    mytree = createTree(train, labels)
    predict_y = []
    for x in test_x:
        y = classify(mytree,label,x)
        predict_y.append(y)
    print(‘正确率:‘,correct_rate(test_y,predict_y))

博主在做交叉验证时出了问题,探索了很久,发现原因在于一开始选的数据集太过单一,导致树的构建不完整,在验证模型正确率时出现错误,因此改用了mushroom.data,此数据集在uci网站可以下载,共有8124个记录。


参考书籍:
《统计学习方法》--李航
《机器学习实战》--Peter

原文地址:http://blog.51cto.com/14065757/2342082

时间: 2024-07-30 12:08:10

机器学习之决策树(一)的相关文章

[转载]简单易学的机器学习算法-决策树之ID3算的

一.决策树分类算法概述 决策树算法是从数据的属性(或者特征)出发,以属性作为基础,划分不同的类.例如对于如下数据集 (数据集) 其中,第一列和第二列为属性(特征),最后一列为类别标签,1表示是,0表示否.决策树算法的思想是基于属性对数据分类,对于以上的数据我们可以得到以下的决策树模型 (决策树模型) 先是根据第一个属性将一部份数据区分开,再根据第二个属性将剩余的区分开. 实现决策树的算法有很多种,有ID3.C4.5和CART等算法.下面我们介绍ID3算法. 二.ID3算法的概述 ID3算法是由Q

【火炉炼AI】机器学习006-用决策树回归器构建房价评估模型

[火炉炼AI]机器学习006-用决策树回归器构建房价评估模型 (本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 ) 最近几十年,房价一直是中国老百姓心中永远的痛,有人说,中国房价就像女人的无肩带文胸,一半人在疑惑:是什么支撑了它?另一半人在等待:什么时候掉下去? 而女人,永不可能让它掉下来.就算快掉下来了,提一提还是又上去了..... 虽然我们不能预测中国房价什么时候崩盘,但是却可以用机器学

[机器学习&数据挖掘]机器学习实战决策树plotTree函数完全解析

在看机器学习实战时候,到第三章的对决策树画图的时候,有一段递归函数怎么都看不懂,因为以后想选这个方向为自己的职业导向,抱着精看的态度,对这本树进行地毯式扫描,所以就没跳过,一直卡了一天多,才差不多搞懂,才对那个函数中的plotTree.xOff的取值,以及计算cntrPt的方法搞懂,相信也有人和我一样,希望能够相互交流. 先把代码贴在这里: import matplotlib.pyplot as plt #这里是对绘制是图形属性的一些定义,可以不用管,主要是后面的算法 decisionNode

机器学习二 -- 决策树学习

决策树学习 从今天开始,坚持每天学习一个机器学习的新知识,加油! 决策树学习是应用最广的归纳推理算法之一,是一种逼近离散值目标函数的方法,在这种方法中学习到的函数被表示为一颗决策树. 决策树表示法 决策树通过把实例从根结点排列到某个叶子结点来分类实例,叶子结点即为实例所属的分类.树上的每一个结点指定了对实例的某个属性的测试,并且该结点的每一个后继分支对应于该属性的一个可能值.分类实例的方法是从这棵树的根节点开始,册数这个结点指定的属性,然后按照给定实例的该属性对应的树枝向下移动,然后这个过程再以

机器学习---算法---决策树

转自:https://blog.csdn.net/qq_43208303/article/details/84837412 决策树是一种机器学习的方法.决策树的生成算法有ID3, C4.5和CART等.决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果.决策树是一种十分常用的分类方法,需要监管学习(有教师的Supervised Learning),监管学习就是给出一堆样本,每个样本都有一组属性和一个分类结果,也就是分类结果已

机器学习_02_决策树

决策树也是一种基础的机器学习模型 比如预测今天小明是否出去打球, 那么我们知道一些特征, 通过对特征的划分,我们可以做出一颗树, 就是决策树, 其实决策树在管理学也用的很多, 主要是对每种情况给出一个概率,然后判断情况的优劣, 这样我们可以通过这棵树来判断当前的情况 如何判断哪个特征进行划分呢, 我们用熵来划分,通过信息增益我们可以选出最优的特征来进行划分. 熵是不确定性的度量, 熵越大, 不确定性越大, 否则越小 ID3算法 对当前的样本集合, 计算所有的信息增益 选择信息增益最大的属性作为测

机器学习笔记-决策树

决策树(Decision Tree) 决策树学习,建立一颗树结构的模型.此模型由一系列逻辑决策构成.在此结构中决策点代表某个属性上的决策,分支表示决策选择项,树的叶子节点是一系列联合决策的结论. 决策树通过分而治之(Divide and conquer)方式-递归划分(recurisive partitioning)来建立.在这个建立过程中,我们从代表所有数据的根节点出发,选择通向目标分类的特性把样本拆分成不同的组,如此直至触及停止标准.有几类停止标准, 节点上的所有或几乎所有的样本都是属于同一

机器学习技法-决策树和CART分类回归树构建算法

课程地址:https://class.coursera.org/ntumltwo-002/lecture 重要!重要!重要~ 一.决策树(Decision Tree).口袋(Bagging),自适应增强(AdaBoost) Bagging和AdaBoost算法再分类的时候,是让所有的弱分类器同时发挥作用.它们之间的区别每个弱分离器是否对后来的blending生成G有相同的权重. Decision Tree是一种有条件的融合算法,每次只能根据条件让某个分类器发挥作用. 二.基本决策树算法 1.用递

机器学习实战——决策树

from math import log #以决策为标准计算信息熵 def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} for featVec in dataSet: currentLabel = featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentL