决策树

机器学习之决策树

决策树原理

可以将决策树看成一个if-then规则的集合。则决策树的根节点到叶节点的每一条路径构成一条规则。路径上的内部结点的特征对应着规则的条件,而叶节点的类,对应着规则的结论。

决策树的特征选择准则是信息增益或信息增益比。

熵(entropy):体系的混乱程度,在各领域都有运用。

信息熵:表示信息的混乱程度。信息越有序,信息熵越低。

信息增益:在划分数据集前后信息发生的变化。熵的减少或是数据无序度的减少。


如何构造一个决策树呢?

伪代码

检测数据中所有数据的分类标签是否相同:
    If so return 标签
        Else:
            寻找划分数据集最好的特征(划分后,信息熵最小,或者是信息增益最大的特征)
            划分数据集
            创建分支节点
                for 每个划分的子集
                    调用createBranch(创建分支的函数),并增加返回结果到分支节点中
            return 分支节点

Python代码实现

计算香农熵(或者直接称为熵entronpy)

def calcShannonEnt(dataSet):        
    numEntries = len(dataSet)  #求list的长度,表示参与训练的训练量         
    labelCounts = {}
    for featVec in dataSet: #the the number of unique elements and their occurance
        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) #log base 2
    return shannonEnt

根据给定的特征划分数据集

def splitDataSet(dataSet, axis, value):   # 括号里是数据集、划分数据集的特征、需要返回的特征的值
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]     #chop out axis used for splitting
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

选择最好的数据划分方式

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1      #the last column is used for the labels最后一个元素是标签
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):        #iterate over all the features 分别计算不同特征值的信息熵
        featList = [example[i] for example in dataSet] #create a list of all the examples of this feature
        #print(featList)
        uniqueVals = set(featList)       #get a set of unique values
        #print(uniqueVals)
        newEntropy = 0.0
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)
            prob = len(subDataSet)/float(len(dataSet))
            newEntropy += prob * calcShannonEnt(subDataSet)     
        infoGain = baseEntropy - newEntropy     #calculate the info gain; ie reduction in entropy
        if (infoGain > bestInfoGain):       #compare this to the best gain so far
            bestInfoGain = infoGain         #if better than current best, set to best
            bestFeature = i
    return bestFeature

创建决策树

def createTree(dataSet,labels): #数据集和标签列表
    classList = [example[-1] for example in dataSet] #将dataSet中的最后一列的类别标签存入classList当中
    if classList.count(classList[0]) == len(classList): 
        return classList[0]#stop splitting when all of the classes are equal
    if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet
        return majorityCnt(classList)
    #以上是递归停止条件

    bestFeat = chooseBestFeatureToSplit(dataSet)
    bestFeatLabel = labels[bestFeat]  #最优分类特征
    myTree = {bestFeatLabel:{}} #初始化myTree
    copylabels = labels.copy()
    del(copylabels[bestFeat]) #删除已经分类使用的特征值
    featValues = [example[bestFeat] for example in dataSet]
    uniqueVals = set(featValues)  #set函数基本功能包括关系测试和消除重复元素,返回是一个无序不重复元素集
    for value in uniqueVals:
        subLabels = copylabels[:]       #copy all of labels, so trees don't mess up existing labels
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
    return myTree 

项目案例1:判定鱼类和非鱼类

此处仅插入运行后的决策树

项目案例2:使用决策树预测隐形眼镜类型

此处仅插入运行后的决策树


PS :

《机器学习实战》这本书中使用的python2,因此在python3中使用是,有些小小的不同:
在这章中有:
firstStr = myTree.keys()[0] #找到输入的第一个元素
在python3运行会报错:’dict_keys’ object does not support indexing
这是因为python3中改变了dict.keys,返回的是dict_keys对象,支持iterable 但不支持indexable
因此我们需要将其转化成list,即更改为:

firstStr = list(myTree.keys())[0]   

更多详细的讲解和代码,请访问 ApacheCN

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页