第三章 决策树(一)

1.预备知识

1.信息增益

在信息论与概率统计中,熵(entropy)是表示随机变量的不确定性的度量,熵值越大表明越不确定,设X是随机变量,则熵定义如下
     
计算信息增益如下:

2代码解析

#coding:gbk
'''
Created on 2014年11月4日

@author: dell
'''
from numpy import log2
import operator
'''
    总的信息增益是依据分类来算的,即line[-1],统计出每个占多少总数
    len(y1)/total_num然后再用D1/D(p*log(P)) D1表示占分类中标签占多少个
  @function 计算熵
'''
def calcShannonEnt(dataSet):
    labels={}
    total_num = len(dataSet)
    for line in dataSet:
        key=line[-1]
        if key not in labels.keys():
            labels[key]=1
        else:
            labels[key]+=1
    shannon=0.0
    for key in labels.keys():
        p = float(labels[key])/total_num
        shannon-= p *log2(p)
    return shannon


'''
@function 创建一个数据矩阵
'''
def creatDataSet():
    dataset = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
    labels = ['no surfacing','flippers']
    return dataset,labels

'''
 @function 划分数据集,将数据集在axis列中是value的值删除
 @param  dataSet是要划分的数据集,axis是要特征的具体位置,vlaue是具体的值,
'''
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
'''
 @function 选择最好的特征划分数据集
 @param dataSet是要划分的数据集
 @return 返回的最优特征的下标
'''
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)) #这个就是Di在D中的比例
            newEntropy += prob*calcShannonEnt(subdataSet) #先算出来某一个特征在总特征集的比例,然后再将这个特征值删除,计算删除特征值后的数据集的熵
        infoGain = baseEntropy -newEntropy #信息增益是拿总分类的熵-特征的熵,信息增益最大即为最优特征
        if infoGain > bestInfoGain:
            bestInfoGain = infoGain
            bestFeature = i 
    return bestFeature 
'''
 @function  包含类标签的列表
 #对具有相同特征值的类别排序,采用投票的方法。也就是类别多的 即为输出类别
'''     
def majorityCnt(classList):
    classCount={}  #用字典存储一个类别列表,然后用sorted函数输出一个数目最多的,sortedClassCount好像是一个元组
    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)  #sorted是排序函数,按照key值排序从大到小, b=operator.itemgetter(1)      //定义函数b,获取对象的第1个域的值
    return sortedClassCount[0][0]  #返回频率最高的分类
'''
    @param dataSet:数据集,labels:类标签 
    @function 创建决策树,先选定最佳特征值,然后子树就是在删除最佳特征的子数据集上递归进行构建决策树
    
'''
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:{}} #已经构建了好了一个关于myTree的字典,只需递归构建即可,key是设置的是最优路径的分类标签值,value是下一个
    del(labels[bestFeat]) #删除这个最佳特征,方便为下一步递归的建立决策树
    featValues = [example[bestFeat] for example in dataSet] #得到列表包含的所有属性值
    uniqueVals = set(featValues)
    for value in uniqueVals:
        subLabels = labels[:]       #copy all of labels, so trees don't mess up existing labels,因为bestLabel已经被删除了
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)  #递归的建立决策树
    return myTree



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值