• 【转载】决策树


    理论部分从这里复习

    决策树(呆呆的猫)

    机器学习实战(三)——决策树(呆呆的猫)

     

    代码也摘自上面博客,可以通过这个代码结合上面理论学习

    from math import log
    import operator
    
    
    """
    函数说明:计算给定数据集的经验熵(香农熵)
    Parameters:
        dataSet - 数据集
    Returns:
        shannonEnt - 经验熵(香农熵)
    """
    def calcShannonEnt(dataSet):
        numEntires = len(dataSet)  # 返回数据集的行数
        labelCounts = {}  # 保存每个标签(Label)出现次数的字典
        for featVec in dataSet:  # 对每组特征向量进行统计
            currentLabel = featVec[-1]  # 提取标签(Label)信息
            if currentLabel not in labelCounts.keys():  # 如果标签(Label)没有放入统计次数的字典,添加进去
                labelCounts[currentLabel] = 0
            labelCounts[currentLabel] += 1  # Label计数
        shannonEnt = 0.0  # 经验熵(香农熵)
        for key in labelCounts:  # 计算香农熵
            prob = float(labelCounts[key]) / numEntires  # 选择该标签(Label)的概率
            shannonEnt -= prob * log(prob, 2)  # 利用公式计算
        return shannonEnt  # 返回经验熵(香农熵)
    
    
    """
    函数说明:创建测试数据集
    Parameters:
        无
    Returns:
        dataSet - 数据集
        labels - 特征标签
        
    年龄:0代表青年,1代表中年,2代表老年;
    有工作:0代表否,1代表是;
    有自己的房子:0代表否,1代表是;
    信贷情况:0代表一般,1代表好,2代表非常好;
    类别(是否给贷款):no代表否,yes代表是。
    """
    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  # 返回数据集和分类属性
    
    
    
    
    """
    函数说明:按照给定特征划分数据集
    Parameters:
        dataSet - 待划分的数据集
        axis - 划分数据集的特征, 去掉该列的特征
        value - 需要返回的特征的值
    Returns:
        无
    """
    def splitDataSet(dataSet, axis, value):
        retDataSet = []  # 创建返回的数据集列表
        for featVec in dataSet:  # 遍历数据集
            if featVec[axis] == value:
                reducedFeatVec = featVec[:axis]  # 去掉axis特征
                reducedFeatVec.extend(featVec[axis + 1:])  # 将符合条件的添加到返回的数据集
                retDataSet.append(reducedFeatVec)
        return retDataSet  # 返回划分后的数据集
    
    
    """
    函数说明:选择最优特征
    Parameters:
        dataSet - 数据集
    Returns:
        bestFeature - 信息增益最大的(最优)特征的索引值
    """
    def chooseBestFeatureToSplit(dataSet):
        numFeatures = len(dataSet[0]) - 1  # 特征数量
        baseEntropy = calcShannonEnt(dataSet)  # 计算数据集的香农熵
        bestInfoGain = 0.0  # 信息增益
        bestFeature = -1  # 最优特征的索引值
        for i in range(numFeatures):  # 遍历所有特征
            # 获取dataSet的第i个所有特征
            featList = [example[i] for example in dataSet]
            # print("featList:",type(featList),featList)
            uniqueVals = set(featList)  # 创建set集合{},元素不可重复
            # ("uniqueVals:",type(uniqueVals),uniqueVals)
            newEntropy = 0.0  # 经验条件熵
            for value in uniqueVals:  # 计算信息增益
                subDataSet = splitDataSet(dataSet, i, value)  # subDataSet划分后的子集
                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  # 返回信息增益最大的特征的索引值
    
    
    """
    函数说明:统计classList中出现此处最多的元素(类标签)
    Parameters:
        classList - 类标签列表
    Returns:
        sortedClassCount[0][0] - 出现此处最多的元素(类标签)
    """
    def majorityCnt(classList):
        classCount = {}
        for vote in classList:  # 统计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]  # 返回classList中出现次数最多的元素
    
    
    """
    函数说明:创建决策树
    Parameters:
        dataSet - 训练数据集
        labels - 分类属性标签
        featLabels - 存储选择的最优特征标签
    Returns:
        myTree - 决策树
    """
    
    
    def createTree(dataSet, labels, featLabels):
        classList = [example[-1] for example in dataSet]  # 取分类标签(是否放贷:yes or no)
        if classList.count(classList[0]) == len(classList):  # 如果类别完全相同则停止继续划分
            return classList[0]
        if len(dataSet[0]) == 1 or len(labels) == 0:  # 遍历完所有特征时返回出现次数最多的类标签
            return majorityCnt(classList)
        bestFeat = chooseBestFeatureToSplit(dataSet)  # 选择最优特征
        bestFeatLabel = labels[bestFeat]  # 最优特征的标签
        featLabels.append(bestFeatLabel)
        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, featLabels)
    
        return myTree
    
    
    """
    函数说明:使用决策树分类
    Parameters:
        inputTree - 已经生成的决策树
        featLabels - 存储选择的最优特征标签
        testVec - 测试数据列表,顺序对应最优特征标签
    Returns:
        classLabel - 分类结果
    """
    
    
    def classify(inputTree, featLabels, testVec):
        firstStr = next(iter(inputTree))  # 获取决策树结点
        secondDict = inputTree[firstStr]  # 下一个字典
        featIndex = featLabels.index(firstStr)
        for key in secondDict.keys():
            if testVec[featIndex] == key:
                if type(secondDict[key]).__name__ == 'dict':
                    classLabel = classify(secondDict[key], featLabels, testVec)
                else:
                    classLabel = secondDict[key]
        return classLabel
    
    
    
    
    if __name__ == '__main__':
        dataSet, labels = createDataSet()
        # print("最优特征索引值:" + str(chooseBestFeatureToSplit(dataSet)))
    
        featLabels = []
        myTree = createTree(dataSet, labels, featLabels)
        print(myTree)
        testVec = [1, 1]  # 测试数据
        result = classify(myTree, featLabels, testVec)
        if result == 'yes':
            print('放贷')
        if result == 'no':
            print('不放贷')

  • 相关阅读:
    由Highcharts加载提示想到的:我想要的别人已经做好了
    ajaxmin js压缩和VS(转1)
    ajaxmin js压缩和VS(转2)
    Silverlight客户端怎样获取外部参数
    SQL中的事务
    qt webkit 中文乱码问题 另辟蹊径
    密码学基础(1)
    使用jQuery的属性[attr]筛选
    Leetcode NO.19 Remove Nth Node From End Of List && 移除链表倒数第n个节点
    经典排序算法(一) —— Selection Sort 选择排序
  • 原文地址:https://www.cnblogs.com/dong973711/p/13792542.html
Copyright © 2020-2023  润新知