决策树⑤——Python代码实现决策树

系统 1705 0

决策树①——信息熵&信息增益&基尼系数
决策树②——决策树算法原理(ID3,C4.5,CART)
决策树③——决策树参数介绍(分类和回归)
决策树④——决策树Sklearn调参(GridSearchCV调参及过程做图)
决策树应用实例①——泰坦尼克号分类
决策树应用实例②——用户流失预测模型
决策树应用实例③——银行借贷模型

上一篇总结了Sklearn库用GridSearchCV调参的过程,今天用python依据现代女生的审美创建一颗简单的决策树,看下是否能代表大众的心声~~

            
              from math import log
import operator


def calcShannonEnt(dataset):
    numEntries = len(dataset)  # 输入样本个数
    labelCounts = {}  # 存类别及相应的数量
    for featVec in dataset:  # 一行即是一个特征向量
        currentLable = featVec[-1] # 取每个样本的类别
        if currentLable not in labelCounts.keys():# 如果变量已经有类别,则在数量上+1,如果没有,则先新建一个再+1
            labelCounts[currentLable] = 0
        labelCounts[currentLable] += 1
    shannoEnt = 0
    for key in labelCounts:
        prob = float(labelCounts[key])/float(numEntries)
        shannoEnt += -prob*log(prob, 2)  # 计算所有样本的信息熵
    return shannoEnt


def creaDataSet1():
    dataSet = [['高', '富', '帅','同意'],
               ['高', '富', '丑','同意'],
               ['高', '穷', '丑','同意'],
               ['高', '穷', '帅','同意'],
               ['矮', '穷', '帅','拒绝'],
               ['矮', '富', '帅', '同意'],
               ['矮', '穷', '丑', '拒绝'],
               ['矮', '富', '丑', '拒绝']]
    labels = ['身高', '财富', '外貌']
    return dataSet, labels


def splitDataSet(dataSet, axis, value):
    retDataset = []
    for feaVec in dataSet:  # 迭代每一个样本
        if feaVec[axis] == value:  # 如果样本的这个特征值=要求的值
            reducedFeatVec = feaVec[:axis] # 取这个样本的前N个特征,直到筛选的这个特征
            reducedFeatVec.extend(feaVec[axis+1:]) #拼接这个特征之后的所有特征值,相当于去掉这个特征
            retDataset.append(reducedFeatVec)  # 给出按这个特征值分类后的剩余特征
    return retDataset


def chooseBestFeatureToSplit(dataset):
    numFeatures = len(dataset[0]) - 1  #特征个数
    baseEntropy = calcShannonEnt(dataset) # 计算信息熵
    bestInfoGain = 0
    bestFeature = -1
    for i in range(numFeatures):# 迭代每一个特征
        featList = [example[i] for example in dataset]  # 找出这个特征的所有属性值
        uniqueVals = set(featList)  # 这个特征的唯一属性值
        newEntropy = 0
        for value in uniqueVals:
            subDataset = splitDataSet(dataset, i, value)  # 按这个特征这个属性值分类后的子集
            prob = float(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.items(), 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)  # 筛选最佳的特征
    print(labels) # 对应的特征名
    bestFeatLabel = labels[bestFeat] # 得到最佳的特征名
    myTree = {bestFeatLabel:{}}
    del (labels[bestFeat]) # 删除已经用于分裂的特征
    featValues = [example[bestFeat] for example in dataset]  # 按此特征的所有特征值
    uniqueVals = set(featValues)  # 特征值的唯一
    for value in uniqueVals:
        subLablels = labels[:] # 剩余可以用于分裂的特征
        print('sub"', subLablels)
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataset, bestFeat, value), subLablels)
# 先按最优特征值的某一个属性分裂,得到子集,对子集再找最优特征分裂,直到全部类别一样,或者已经没有特征可选时采用最大投票法得出分类结果;迭代的结果全部依次存入mytree字典中
    return myTree


if __name__ == '__main__':
    dataSet, labels = creaDataSet1()
    map = createTree(dataSet, labels)
    print(map)

            
          

在这里插入图片描述
从结果看出,女生在身高,财富和外貌中,最重视的还是身高,如果身高较高,不会在意其它2个条件,如果身高不高,则会再看财富,如果有钱且长得还行,能接受,如果有钱但长得不好则拒绝,如果没钱则直接拒绝。


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论