决策树的构建

本文按照《机器学习实战》书中ID3算法构建决策树,构建步骤即为代码的先后顺序

def calcShannonEnt(dataSet):  # 计算 熵 H
    numEntries = len(dataSet)
    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   shannonEnt = shannoEnt - prob * log(prob,2)
    return shannonEnt

计算熵值

def createDataSet():   # 获取数据
    dataSet = [[1, 1, 'yes'],
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
    # dataSet = [[1, 1, 'maybe'],
    #            [1, 1, 'yes'],
    #            [1, 0, 'no'],
    #            [0, 1, 'no'],
    #            [0, 1, 'no']]
    labels = ['no surfacing','flippers']
    #change to discrete values
    return dataSet, labels

获取数据

'''
splitdataset函数 按照 axis参数对应的特征进行数据集的划分,返回划分后该特征等于value的值的子集
'''
def splitDataSet(dataSet, axis, value):   #  按照给定特征划分数据集 参数为   待划分的数据集  划分数据集的特征  需要返回的特征的值   表示取出第axis列中值为value的数据集,并去除掉第axis列的数据。
    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   取出每一条数据的各个特征
        uniqueVals = set(featList)       #get a set of unique values    获取每一个特征有哪些取值
        newEntropy = 0.0
        for value in uniqueVals:    # 该循环执行 完成。 则 一个特征 完成所有子集的 计算
            subDataSet = splitDataSet(dataSet, i, value)  # 按照 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.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]



def createTree(dataSet,labels):
    classList = [example[-1] for example in dataSet]      # ['yes','yes','no','no','no']
    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

createTree函数递归创建树

mydat,labels=createDataSet()
print(mydat,labels)
mytree=createTree(mydat,labels)
print(mytree)

测试代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值