机器学习实战--chapter3 决策树

1 大话决策树

决策树就是一颗树,每个父节点就是基于特征的一种表示,子节点就是对数据集的再次细分,通过层层细分,得到数据集中每个样本的类别。主要涉及到每层树根的特征的选取策略与递归结束时的处理。当然这里防止层数太多,可以人为限制层数。

2 决策树的一般流程

  1. 收集数据
  2. 准备数据:标称型数据。
  3. 分析数据:
  4. 训练算法:构造树的数据结构。
  5. 测试算法
  6. 应用

:标称型数据:取值有限,适合分类;数值型数据:无限,适合回归。

3 信息熵

百度百科
博客1
博客2

3.1 不确定性

概率表示某事件发生的可能性,概率越大,也就说明不确定性越小;反之,概率越小,不确定性越大。所以,不确定性可以通过概率来衡量。怎么理解呢?比如综合天气的一些数据,天气预报得出明天90%下雨,那么明天基本会下雨,这事也就基本确定了,从而不确定性就非常小。
不确定性函数

l(xi)=log2p(xI)

3.2 信息熵

熵形容系统的混乱程度,定义为信息的期望值,信息就是上面描述的不确定性。

H=i=1np(xi)log2p(x2)

3.2 信息增益

信息增益就是系统原先的熵减去某事件发生后剩余的熵,就是该事件发生后,系统不确定性降低了多少,降低越大,说明不确定消除越多,获得的信息量越大。

4 决策树算法

4.1 递归构建

结束条件:
1. 所有特征已经过滤完,此时如果剩余样本还是类别不清楚,则选择其中的众数作为该子集的类别;
2. 剩余样本已经属于某一类,即已确定。

4.2 每个树的树根的选取

采用第三节的方法,每选的一个特征,使得系统的信息增益最大化。

5 代码

5.1 计算熵

#创建数据集,列表的形式,yes, no是tag.
def createDataSet():
    dataSet = [[1, 1, 'yes'],
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
    labels = ['no surfacing','flippers']  #起显示作用,对算法没作用
    #change to discrete values
    return dataSet, labels

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) #根据熵公式计算,对信息的加权平均,即信息的均值。
    return shannonEnt

5.2 选择特征

#根据特征筛选数据集,作为一个分支
def splitDataSet(dataSet, axis, value):
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]     #slice操作,提取特征axis==value的样本,同时删去该特征,举例样本exp1 = [1, 2, 'yes'], 则exp1[0]特征为1的,组装一个新的列表,即[2, 'yes']
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

#特征选取的依据,信息增益最大  
def chooseBestFeatureToSplit(dataSet): #选择某个特征使得的信息增益最大
    numFeatures = len(dataSet[0]) - 1      #取得特征数,数据集最后一列是tag.
    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                      #returns an integer

5.3 递归构建树

结束条件:
1. 所有特征已经过滤完,此时如果剩余样本还是类别不清楚,则选择其中的众数作为该子集的类别;
2. 剩余样本已经属于某一类,即已确定。

def majorityCnt(classList): #条件一,返回剩余数据集众数的tag.
    classCount={}
    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] #数据集tag列表
    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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值