机器学习笔记:ID3算法建立决策树(二)

在《机器学习笔记:ID3算法建立决策树(一)》中记录了ID3算法的计算公式和步骤,现在用例子记录一下ID3构建决策树的过程。
对以下数据进行分类:

-是否能飞?是否有羽毛?是小鸟?
1
2
3
4
5

是否能飞用0,1表示,0不能飞,1能飞;
是否有羽毛用0,1表示,0没有羽毛,1有羽毛;
也就是用是否能飞,是否有羽毛去判断一个东西是不是小鸟
用矩阵表达如下:

def createDataSet():
    dataSet = [[1,1,'是'],
               [1,1,'是'],
               [1,0,'否'],
               [0,1,'否'],
               [0,1,'否']]
    labels = ['能飞的','有羽毛的']
    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 * math.log(prob,2)
    return shannonEnt

对整个样本数据按类别划分子集:

def splitDataSet(dataSet,axis,value):
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            #featVec 是一维数组,下标为axis元素之前的值加入到reducedFeatVec
            reducedFeatVec = featVec[:axis]    
            #下一行的内容axis+1之后的元素加入到reducedFeatVec
            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
        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]
    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

调用

myDat,labels = createDataSet()
print(createTree(myDat, labels))

结果

{'能飞的': {0: '否', 1: {'有羽毛的': {0: '否', 1: '是'}}}}

接下来继续学习图形化显示决策树,更直观。

总结

计算各属性的信息增益,找出最大者为根节点
先验熵:样板数据中,先求出各种值出现的概率P(ui),再利用公式求熵
后验熵:对其他列,先求出各种值出现的概率P(vi),再求出先验列中各种值对本列取值为vi时的概率P(u|vi),再根据公式求熵H(U|vi),把u为各种值的情况下的H(U|vi) 算出来
条件熵:对后验熵在输出符号集V中求期望,接收到全部符号后对信源的不确定性,根据后验熵得到的P(vi)乘以H(U|vi)之和
信息增益:先验熵与条件熵的差,即先验熵中求得的P(ui)减去条件熵
拆分子集:对作为根节点的属性的数据根据不同的值分成子集。
对剩余属性重复上述步骤。

这是个人理解,如果有不到位的地方,或者有理解偏差,希望有人能指出扶正,交流学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值