zoukankan      html  css  js  c++  java
  • 【机器学习】决策树-01

    心得体会:

      1决策树是在 香农熵 和 信息增益 的基础上构建的

      2筛选决策标签,当筛去该标签时得到香农熵最优结构时,选择该决策标签,不断筛选直到选完所有标签(或余下结果都一样)

      3取余下结果中最多的结果作为该叶节点的返回结果

      4数据结构是字典树

    #3-1构造决策树
    
    #计算香农熵
    from math import log
    def calcShannonEnt(dataSet):
        numEntries=len(dataSet)
        labelCounts={}
        for featVec in dataSet:
            currentLabel=featVec[-1]
            if currentLabel not in labelCounts.keys():
                labelCounts[currentLabel]=0
            labelCounts[currentLabel]+=1
        shannonEnt=0.0
        for key in labelCounts:
            prob=float(labelCounts[key]/numEntries)#该种数据的占比
            shannonEnt-=prob*log(prob,2)#香农熵公式
        return shannonEnt
    
    #自定义数据
    def createDataSet():
        dataSet=[
            [1, 1, 'yes'],
            [1, 1, 'yes'],
            [1, 0, 'no'],
            [0, 1, 'no'],
            [0, 1, 'no'],
        ]
        labels=['no surfacing','flippers']
        return dataSet,labels
    
    # myDat,labels=createDataSet()
    # print(calcShannonEnt(myDat))
    
    #按照给定特征划分数据集
    def splitDataSet(dataSet,axis,value):#选择axis位是value的数据
        retDataSet=[]
        for featVec in dataSet:
            if featVec[axis]==value:#选择数据集中符合条件的数据
                reducedFeatVec=featVec[:axis]#axis之前的数据
                reducedFeatVec.extend(featVec[axis+1:])#axis之后的数据
                retDataSet.append(reducedFeatVec)#新数据集(已经筛选过axis位)
        return retDataSet
    
    # myDat,labels=createDataSet()
    # print(myDat)
    # print(splitDataSet(myDat,0,1))
    # print(splitDataSet(myDat,0,0))
    
    # 选择最好的数据集划分方式
    def chooseBestFeatureToSplit(dataSet):
        numFeatures=len(dataSet[0])-1   #最后一个数据是结果
        baseEntropy=calcShannonEnt(dataSet) #计算基础香农熵
        bestInfoGain=0.0 #信息增益
        bestFeature=-1  #初始特征位是-1
        for i in range(numFeatures):
            featList=[example[i] for example in dataSet] # 复制dataset
            uniqueVals=set(featList) # 数据去重,得到i位置的域
            newEntropy=0.0  #i位置的总信息期望
            for value in uniqueVals:
                subDataSet=splitDataSet(dataSet,i,value)    #筛选i位置为value的数据
                prob=len(subDataSet)/float(len(dataSet))    #这些数据的占比
                newEntropy+=prob*calcShannonEnt(subDataSet) #筛选i位置为value的数据 的信息期望
            inoGain=baseEntropy-newEntropy #筛选i位置后剩下的信息期望
            if(inoGain>bestInfoGain):#选择筛去i后余下香农熵最小的,筛去i数据最整齐
                bestInfoGain=inoGain
                bestFeature=i
        return bestFeature
    
    # myDat,labels=createDataSet()
    # print(chooseBestFeatureToSplit(myDat))
    
    #递归构建决策树
    import operator
    #返回出现次数最多的分类名称
    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)#按字典(k,v)第一个域v排序
        return sortedClassCount[0][0]   #返回classList中val最大的key
    
    #创建决策树
    def createTree(dataSet,labels):#输入数据和位置含义
        classList=[example[-1] for example in dataSet] #返回所有结果
        if classList.count(classList[0])==len(classList):   #如果(第0位数据出现的次数和长度一样)剩下结果都一样
            return classList[0] #返回第0位的结果,因为都一样
        if len(dataSet[0])==1:  #如果数据只剩下最后一位(最后一位是结果 )
            return majorityCnt(classList)   #返回最多的结果
        bestFeat=chooseBestFeatureToSplit(dataSet)  #选择最优的位置
        bestFeatLabel=labels[bestFeat]  #最优位置的结果
        myTree={bestFeatLabel:{}} #字典树 bestFeatLabel:{}中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) #创建该分支下的子树
        return myTree
    
    # myDat,labels=createDataSet()
    # mytree=createTree(myDat,labels)
    # cur=mytree
    # while True:
    #     if(type(cur)==dict):
    #         label=list(cur.keys())[0]   #因为字典树只有一个根节点
    #         print("%s ?"%label)
    #         key=int(input("input_1/0(yes/no):"))#key要强制转换成int不然默认是string
    #         cur=cur[label][key] #选择分支
    #     else:
    #         print(cur)
    #         break
  • 相关阅读:
    做一个项目,平时都用到哪些工具提高效率(上)
    做项目时,如何做比较美观大方的数据输入窗体
    做一个项目,平时都用到哪些工具提高效率(中)
    类型的初试化器的调用时机
    数据加密小工具
    ASP.NET 开发知识小结
    做一个项目,平时都用到哪些工具提高效率(下)
    两道面试题目 关于new和override的
    js技巧,js找到html中的注释,js让客户端另存一段文本
    在适当的场合使用FlagsAttribute修饰枚举
  • 原文地址:https://www.cnblogs.com/LPworld/p/13268298.html
Copyright © 2011-2022 走看看