决策树0531

tree.py

import operator
from math import log
def calcShannonEnt(dataSet):#计算给定数据集的香农熵
    numEntries=len(dataSet)#获取数据集的文件数目
    labelCounts={}#建立一个标签矩阵 存放对应的标签值
    for featVec in dataSet:
        currentLabel=featVec[-1]#依次取featVec里的最后一个元素 即标签元素
        if currentLabel not in labelCounts.keys():#如果得到的标签不在已有的标签集内
            labelCounts[currentLabel]=0#创建一个新的标签
        labelCounts[currentLabel]+=1#对对应的标签种类进行计数(已经存在的)
    shannonEnt=0.0#熵清0
    #对所有不同类别计算熵
    for key in labelCounts:
        prob=float(labelCounts[key])/numEntries
        shannonEnt-=prob*log(prob,2)
    return shannonEnt

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 splitDataSet(dataSet,axis,value):#待划分的数据集、划分数据集的特征、需要返回的特征的值
    retDataSet=[]
    for featVec in dataSet:
        if featVec[axis]==value:#特征与目标值一致
            reducedFestVec=featVec[:axis]#将axis之前的列附到reducedFestVec中
            reducedFestVec.extend(featVec[axis+1:])#将axis之后的列附到reducedFestVec中
            retDataSet.append(reducedFestVec)#将reducedFestVec的值放到retDataSet中
    return retDataSet

def chooseBestFeatureToSplit(dataSet):#选择最好的数据分割点
    numFeatures=len(dataSet[0])-1#对数据集第一行,第一个例子的行数(特征个数),减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
    sortedClassCount=sorted(classCount.iteritems(),key=operator.iteritems(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)#把重复的属性去掉 放到uniqueVals里面
    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)
    for key in secondDict.keys():
        if testVec[featIndex]==key:
            if typr(secondDict[key]).__name__=='dict':
                classLabel=classify(secondDict[key],featLabels,testVec)
            else:
                classLabel=secondDict[key]
        return classLabel

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值