【ML实战】决策树ID3

相关知识

  1. 决策树是一种分类方法,通过不断的选取最优特征来进行树的建立
  2. 香农熵:度量数据集的无序(混乱)程度
    H ( x ) = − p ∗ l o g ( p ) H(x) = -p*log(p) H(x)=plog(p),其中p表示选择该分类的概率
  3. 信息增益(information gain): g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A) = H(D) - H(D|A) g(D,A)=H(D)H(DA);暨表示在给定A类别下,数据集合不确定性(混乱性)减小的程度。

思想

  • 对于给定数据集,决策树算法从所有特征中选择当前情况下最好的特征(暨信息增益最大,对该特征划分会使数据集合的不确定性大大降低),然后对数据集依照该特征的所有属性值进行此次划分。划分后将该特征去除,在剩余数据集中做如上相同的操作来递归的建立决策树,直到所有的特征均被划分或每个分支下的实例都属于相同的分类。
  • 若数据集已经处理了所有特征但类标签依然不唯一,则采用多数投票的方式进行归类。

代码实现

  • 引入所需要的包
import operator
from math import log
  • 随便创建的数据集
def createData():
    dataset = [
        [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']
    ]
    labels = ['no surfacing', 'flippers']
    return dataset, labels
  • 计算数据集的熵
def calcShannonEnt(dataset):
    numEntries = len(dataset)
    labelsCount = {}  # 创建标签字典
    for featureVec in dataset:  # 统计各标签数量
        currentLabel = featureVec[-1]
        if currentLabel not in labelsCount.keys():
            labelsCount[currentLabel] = 0
        labelsCount[currentLabel] += 1
    Entropy = 0.0
    for key in labelsCount.keys():  # 计算熵
        p = float(labelsCount[key]) / numEntries
        Entropy -= p * log(p,2)
    return Entropy
  • 对给定特征划分数据集
def spiltDataset(dataset, axis, value):  # 划分数据集
    extractData = []
    for featureVec in dataset:
        if featureVec[axis] == value:  # 去除当前划分的特征列
            reducedFeatVec = featureVec[:axis]
            reducedFeatVec.extend(featureVec[axis+1:])
            extractData.append(reducedFeatVec)
    return extractData
  • 对当前数据集计算每个特征的信息增益来找出最好的划分特征
def chooseBestFeatureToSpilt(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]  # 取第i列所有取值
        uniqueFeature = set(featList)   # 对第i列的属性值去重
        newEntropy = 0.0
        for value in uniqueFeature: # 计算使用第i个特征划分后的新熵值,即条件熵
            subDataset = spiltDataset(dataset, i, value)
            p = len(subDataset) / float(len(dataset))
            newEntropy += p * calcShannonEnt(subDataset)
        infoGain = baseEntropy - newEntropy  # 计算信息增益
        if infoGain > bestInfoGain:  # 选择最大信息增益的特征作为当前应划分的特征
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature
  • 如果出现类标签划分不唯一的情况,考虑多数投票
def majority(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, label):
    classList = [example[-1] for example in dataset]
    if classList.count(classList[0]) == len(classList):  # 若列表中第一个值的数目等于列表长度
        return classList[0]  # 暨所有数据类别相同,直接返回
    if len(dataset[0]) == 1:  # 若无法划分成仅包含一个类别的分组,则采取多数投票
        return majority(classList)
    bestFeature = chooseBestFeatureToSpilt(dataset)  # 获取最好的划分特征
    bestFeatLabel = labels[bestFeature]
    theTree = {bestFeatLabel:{}}
    del(labels[bestFeature])  # 删除当前最好特征的标签
    featValues = [example[bestFeature] for example in dataset]
    uniqueFeatValues = set(featValues)  # 获取最好特征的所有属性值
    for value in uniqueFeatValues:  # 根据每一个属性值递归建树
        sublabels = labels[:]
        theTree[bestFeatLabel][value] = createTree(spiltDataset(dataset, bestFeature, value), sublabels)
    return theTree
  • 主函数,调用上述函数实现算法并输出结果
if __name__ == '__main__':
    datasets, labels = createData()
    tree = createTree(datasets, labels)
    print(tree)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值