2021-10-24 决策树构建

本文介绍了如何使用Python的sklearn库构建一个决策树模型,以帮助用户选择合适的隐形眼镜。通过创建数据集,计算信息熵和信息增益,选择最佳特征进行划分,最终构建出一棵决策树,用于预测用户是否需要隐形眼镜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# sklearn之构建决策树,为自己配一个隐形眼镜
# 决策树
import operator
from math import log


# 创建数据集
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  # 返回数据集和分类属性


# 计算给定数据集的经验熵
def calcEnt(dataSet):
    # 返回数据集的行数
    numEntires = len(dataSet)
    # 保存每个标签出现次数的字典
    labelCounts = {}
    # 遍历每一个特征向量
    for eigenVec in dataSet:
        # 提取当前特征向量的标签
        currentlabel = eigenVec[-1]
        # 如果标签没有存在字典中,添加进去
        if (currentlabel not in labelCounts.keys()):
            labelCounts[currentlabel] = 0
        # 标签计数
        labelCounts[currentlabel] += 1
    # 定义香农熵
    Ent = 0.0
    # 遍历标签
    for key in labelCounts:
        # 计算标签的概率
        prob = float(labelCounts[key]) / numEntires
        # 计算此标签的信息熵,并累加
        # Ent = -Σ(1~k)pklog2(pk)
        Ent -= prob * log(prob, 2)
    return Ent


# 计算各个特征的信息增益,信息增益可由信息熵减去条件熵推出
def splitDataSet(dataSet, axis, value):
    """
    :param dataSet: 待划分数据集
    :param axis: 划分数据集的特征值
    :param value:需要返回特征的值
    :return: 无
    """
    retDataSet = []
    for eigenVec in dataSet:
        if (eigenVec[axis] == value):
            reducedFeatVec = eigenVec[:axis]
            reducedFeatVec.extend(eigenVec[axis + 1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet


def chooseBeatFeatureToSplit(dataSet):
    """
    :param dataSet:数据集
    :return: 返回最大特征的索引值
    """
    numFeatures = len(dataSet[0]) - 1
    # 计算数据集的信息熵
    baseEntropy = calcEnt(dataSet)
    # 定义信息增益
    beatGain = 0.0
    # 最优特征的索引值
    beatFeatureIndex = -1
    # 遍历所有特征
    for i in range(numFeatures):
        # 获取dataSet的第i个特征
        featList = [example[i] for example in dataSet]
        # 创建set集合,元素不可重复
        uniqueVals = set(featList)
        # 定义条件经验熵
        newEntropy = 0.0
        # 遍历标签
        for value in uniqueVals:
            # 依照特征,划分子集
            subDataSet = splitDataSet(dataSet, i, value)
            print(subDataSet)
            # 求出子集的概率
            prob = len(subDataSet) / float(len(dataSet))
            # 计算条件熵
            newEntropy += prob * calcEnt(subDataSet)
            # 计算此特征下的信息增益
        infoGain = baseEntropy - newEntropy
        print("第%d个特征的增益为%.3f" % (i, infoGain))
        if (infoGain > beatGain):
            beatGain = infoGain
            beatFeatureIndex = i
    return beatFeatureIndex


# 返回classList中出现次数最多的元素
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, featLabels):
    """
    :param dataSet:训练数据集
    :param labels:分类属性标签
    :param featLabels:存储选择的最优特征标签
    :return:决策树,一个嵌套字典,形如{'有自己的房子': {0: {'有工作': {0: 'no', 1: 'yes'}}, 1: 'yes'}}
    """
    # 类别向量
    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 = chooseBeatFeatureToSplit(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:
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), labels, featLabels)
    return myTree


if __name__ == '__main__':
    dataSet, labels = createDataSet()
    print("数据集:", dataSet)
    print("信息熵:", calcEnt(dataSet))
    print("最优特征索引值:" + str(chooseBeatFeatureToSplit(dataSet)))
    featLabels = []
    myTree = createTree(dataSet, labels, featLabels)
    print(myTree)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值