决策树是经常使用的数据挖掘算法之一,概念非常简单。
优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配的问题
适用数据类型:数值型和标称型

3.1 决策树的构造

机器学习实战(二)决策树 python3

3.1.1 信息增益的计算

香农熵(熵):集合信息的度量方式
计算公式:
机器学习实战(二)决策树 python3
p是选择该分类的概率,n是分类的数目。
信息增益:划分数据集前后信息发生的变化 E(信息增益) = S0(初始信息熵) - S1(当前信息熵)
举个栗子:
机器学习实战(二)决策树 python3
feature1:根据不浮出水面是否可以生存这一特征分类的信息增益
feature2:根据是否有脚蹼这一特征分类的信息增益
哪一个信息增益大就先依据该特征划分
机器学习实战(二)决策树 python3
代码实现:

from math import log
def calcShannonEnt(dataSet):
    # 返回数据集的行数
    numEntires = len(dataSet)
    # 保存每个标签(Label)出现次数的“字典”
    labelCounts = {}
    # 对每组特征向量进行统计
    for featVec in dataSet: #为所有可能的分类创造字典
        #print(featVec)
        # 提取标签(Label)信息
        currentLabel = featVec[-1]
        #print(currentLabel)
        # 如果标签(Label)没有放入统计次数的字典,添加进去
        if currentLabel not in labelCounts.keys():
            # 创建一个新的键值对,键为currentLabel值为0
            labelCounts[currentLabel] = 0
        # Label计数
        labelCounts[currentLabel] += 1
        #print(labelCounts)
    # 经验熵(香农熵)
    shannonEnt = 0.0
    # 计算香农熵
    for key in labelCounts:
        # 选择该标签(Label)的概率
        prob = float(labelCounts[key]) / numEntires
        # 利用公式计算
        shannonEnt -= prob*log(prob, 2)
        #print(shannonEnt)
    # 返回经验熵(香农熵)
    return shannonEnt

创建数据集,其中前四列是特征,最后一列是标签

def createDataSet():
    # 数据集
    dataSet = [[0, 0, 0, 0, 'no'],
               [0, 0, 0, 1, 'no'],
               [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],
               [0, 0, 0, 0, 'no'],
               [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'],
               [1, 1, 1, 1, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [2, 0, 1, 2, 'yes'],
               [2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],
               [2, 1, 0, 2, 'yes'],
               [2, 0, 0, 0, 'no']]
    # 分类属性
    labels = ['年龄', '有工作', '有自己的房子', '信贷情况']
    # 返回数据集和分类属性
    return dataSet, labels
>>> myDat, labels = createDataSet()
>>> Shannon = calcShannonEnt(myDat)
>>> shannon
> 0.9709505944546686

3.1.2 划分数据集

划分数据集

对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最佳选择。

def splitDataSet(dataSet, axis, value): #dataSet - 待划分的数据集,axis - 划分数据集的特征,values - 需要返回的特征的值,
    # 创建返回的数据集列表
    retDataSet = []
    # 遍历数据集的每一行
    for featVec in dataSet:
        if featVec[axis] == value:
            # 去掉axis特征
            reducedFeatVec = featVec[:axis]
            # 将符合条件的添加到返回的数据集
            # extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)。
            reducedFeatVec.extend(featVec[axis+1:])
            # 列表中嵌套列表
            retDataSet.append(reducedFeatVec) 
    # 返回划分后的数据集
    return retDataSet
  
>>> splitDataSet(myDat,1,1)
>[[0, 0, 1, 'yes'],
 [0, 1, 0, 'yes'],
 [1, 1, 1, 'yes'],
 [2, 0, 1, 'yes'],
 [2, 0, 2, 'yes']]

Python语言在函数中传递的是列表的引用,在函数内部对列表对象的修改,将会影响该列表对象的整个生存周期。为了消除这个不良影响,我们需要在函数的开始声明一个新列表对象。因为该函数代码在同一数据集上被调用多次,为了不修改原始数据集,创建一个新的列表对象。

选择最优特征

选取特征,划分数据集,计算最佳选择

def chooseBestFeatureToSplit(dataSet):
    # 特征数量
    numFeatures = len(dataSet[0]) - 1
    # 计算数据集的香农熵
    baseEntropy = calcShannonEnt(dataSet)
    # 信息增益
    bestInfoGain = 0.0
    # 最优特征的索引值
    bestFeature = -1
    # 遍历所有特征
    for i in range(numFeatures):
        # 获取dataSet的第i个所有特征存在featList这个列表中(列表生成式)
        featList = [example[i] for example in dataSet]
        # 创建set集合{},元素不可重复,重复的元素均被删掉
        # 从列表中创建集合是python语言得到列表中唯一元素值得最快方法
        uniqueVals = set(featList)
        # 经验条件熵
        newEntropy = 0.0
        # 计算信息增益
        for value in uniqueVals:
            # subDataSet划分后的子集
            subDataSet = splitDataSet(dataSet, i, value)
            # 计算子集的概率
            prob = len(subDataSet) / float(len(dataSet))
            # 根据公式计算经验条件熵
            newEntropy += prob * calcShannonEnt(subDataSet)
        # 信息增益
        infoGain = baseEntropy - newEntropy
        # 打印每个特征的信息增益
        print("第%d个特征的增益为%.3f" % (i, infoGain))
        # 计算信息增益
        if(infoGain > bestInfoGain):
            # 更新信息增益,找到最大的信息增益
            bestInfoGain = infoGain
            # 记录信息增益最大的特征的索引值
            bestFeature = i
    # 返回信息增益最大的特征的索引值
    return bestFeature

3.1.3 递归构建决策树

3.2 略

3.3 测试和存储分类器

3.3.1 测试算法:使用决策树执行分类

3.3.2 使用算法:决策树的存储

相关文章: