机器学习--决策树

一、算法简介

       决策树一般都是自上而下来生成的,每个决策后事件(即自然状态)都可能引出两个或多个事件,导致结果的不同,把这种结构分支画成形状很像一棵树的枝干,故称为决策树。

       决策树能够读取数据集合,并且决策树很多任务都是为了数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集合,并从中提取一系列规则,机器学习算法最终将使用这些机器从数据集中创造的规则。

       决策树就是将决策过程各个阶段之间的结构绘制成一张箭线图,我们可以用下图来表示:

               

 

二、构成要素

        决策树由节点和有向边组成,节点的类型有两种,分别为内部节点和叶子节点,其中,内部节点表示一个特征或属性的测试条件(用于分开具有不同特性的记录),叶子节点表示一个分类。


三、算法思想

(1)树以代表训练的样本的单个节点开始

(2)如果样本都在同一个类,则该节点成为树叶,并用该类标记

(3)否则,算法选择最有分类能力的属性作为决策树的当前节点

(4)根据当前节点属性取值的不同,将训练样本数据集分为若干子集,每个取值形成一个分支,有几个取值形成几个分支,一旦一个属性出现在一个节点上,就不必在该节点的任何衍生子集在考虑它。

(5)递归划分步骤仅当下列条件之一成立时停止:

  • 给定节点的所有样本属于同一类
没有剩余属性可以用来进一步划分样本,在这种情况下,使用多数表决,将给定的节点转换成树叶,并以样本中元组个数最多的类别作为类别标记,同时也可以存放该节点样本的类别分布
  • 如果某一分支没有满足该分支中已有分类的样本,则以样本的多数类创建一个树叶

     现在我们已经大致了解决策树可以完成哪些任务,接下来我们将学习如何从一堆原始数据中构造决策树。


四、信息论基础
(1)熵:熵度量了事物的不确定性,越不确定的事物,它的熵就越大。具体的,随机变量X的熵的表达式如下:
             
其中n代表X的n种不同的离散取值。而pi代表了X取值为i的概率,log为以2为底的对数。
举个例子,比如X有2个可能的取值,而这两个取值各为1/2时

             

(2)条件熵:它度量了我们的X在知道Y以后剩下的不确定性,表达式如下:

              
(3)特征增益:信息增益特征选择中的一个重要指标,它定义为一个特征能够为分类系统带来多少信息,带来的信息越多,该特征越重要,表达式如下:
             H(X) - H(X|Y)


五、代码详情
from math import log
import operator

def createDataSet():
    dataSet =[[1,1,'yes'],
              [1,1,'yes'],
              [1,0,'no'],
              [0,1,'no'],
              [0,1,'no']]
    labels = ['no surfacing','flippers']
    return dataSet,labels

def calcShannonEnt(dataSet):
    numEntries = len(dataSet)
    lableCounts = {}
    for featVec in dataSet:
        currentLable = featVec[-1]
        if currentLable not in lableCounts.keys():
            lableCounts[currentLable] = 0
        lableCounts[currentLable] += 1
    shannonEnt = 0
    for key in lableCounts:
        prob = float(lableCounts[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):
        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 * calcShannonEnt(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
    return max(classCount)


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 main():
    data,label = createDataSet()
    myTree = createTree(data,label)
    print myTree
   
if __name__=='__main__':
    main()

六、输出结果
{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

七、算法小结
       决策树分类器就像带有终止块的流程图,终止块表示分类结果。开始处理数据时,我们首先需要测量集合中数据的不一致性,也就是熵,然后寻找最优方案划分数据集,直到数据集中的所有数据属于同一分类。ID3算法可以用于划分标称型数据集。构建决策树时,我们通常采用递归的方法将数据集转化为决策树。
       有很多构建决策树的方法,包括ID3、C4.5、CART等,这里我用的是ID3算法。

猜你喜欢

转载自blog.csdn.net/sumflowers/article/details/75443610