• 决策树python实现小样例


    我们经常使用决策树处理分类问题,近年来的调查表明决策树也是经常使用的数据挖掘算法
    K-NN可以完成多分类任务,但是它最大的缺点是无法给出数据的内在含义,决策树的主要优势在于数据形式非常容易理解
    决策树的优缺点:
    优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据
    缺点:可能会产生过度匹配问题
    适用数据类型:数值型和标称型
    在构造决策树时,我们需要解决的第一个问题是,当前数据集上哪个特征在划分数据分类时起决定性作用。
    为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据集就被划
    分为几个数据子集。这些数据子集会分布在第一个决策点的所有分支上,如果某个分支下的数据属于同一
    类型,则当前无需阅读的垃圾邮件已经正确地划分数据分类,无需进一步对数据集进行分割。如果数据子
    集内的数据不属于同一类型,则需要重复划分数据子集的过程。如何划分数据子集的算法和划分原始数据集
    的方法相同,直到所有具有相同类型的数据均在一个数据子集内
    决策树的一般流程
    (1)收集数据:可以使用任何方法
    (2)准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
    (3)分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期

    (4)训练算法:构造树的数据结构

    (5)测试算法:使用经验树计算错误率
    (6)使用算法:此步骤可以适用于任何监督学习算法,而适用决策树可以更好地理解数据的内在含义

    从数据集构造决策树算法所需要的子功能模块,其工作原理如下:得到原始数据集,然后基于
    最好的属性值划分数据集,由于特征值可能多余两个,因此可能存在大于两个分支的数据集划
    分,第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再
    次划分数据。

      1 计算给定数据集的香农熵
      2 from math import log
      3 import operator
      4 import treePlotter
      5 
      6 
      7 def calcShannonEnt(dataSet):
      8     #计算数据集的实例总数
      9     numEntries = len(dataSet)
     10     labelCounts = {}
     11     #创建一个字典,他的键值是最后一列的数值,如果当前键值不存在,则扩展字典并将当前键值加入字典。
     12     # 每个键值都记录了当前类别出现的次数。最后,使用所有类标签的发生频率计算类别出现的概率。我们
     13     # 将用这个概率计算香农熵,统计所有类标签发生的次数。
     14     for featVec in dataSet:  # the the number of unique elements and their occurance
     15         #为所有可能分类创建字典
     16         currentLabel = featVec[-1]
     17         if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0
     18         labelCounts[currentLabel] += 1
     19     shannonEnt = 0.0
     20     for key in labelCounts:
     21         prob = float(labelCounts[key]) / numEntries
     22         #以2为底求对数,香农定理
     23         shannonEnt -= prob * log(prob, 2)  # log base 2
     24     return shannonEnt
     25 def createDataSet():
     26     dataSet = [[1, 1, 'yes'],
     27                [1, 1, 'yes'],
     28                [1, 0, 'no'],
     29                [0, 1, 'no'],
     30                [0, 1, 'no']]
     31     labels = ['no surfacing','flippers']
     32     #change to discrete values
     33     return dataSet, labels
     34 
     35 #按照给定特征划分数据集
     36 #三个输入参数:待划分的数据集、划分数据集的特征、特征的返回值。
     37 #注:python不考虑内存分配的问题
     38 def splitDataSet(dataSet, axis, value):
     39     #创建新的list对象
     40     retDataSet = []
     41     for featVec in dataSet:
     42         if featVec[axis] == value:
     43             #抽取
     44             reducedFeatVec = featVec[:axis]     #chop out axis used for splitting
     45             reducedFeatVec.extend(featVec[axis+1:])
     46             retDataSet.append(reducedFeatVec)
     47     return retDataSet
     48 
     49 #选择最好的数据集划分方式
     50 def chooseBestFeatureToSplit(dataSet):
     51     numFeatures = len(dataSet[0]) - 1      #the last column is used for the labels
     52     # 计算了整个数据集的香农熵
     53     baseEntropy = calcShannonEnt(dataSet)
     54     bestInfoGain = 0.0; bestFeature = -1
     55     for i in range(numFeatures):        #iterate over all the features
     56         #创建唯一的分类标签列表
     57         featList = [example[i] for example in dataSet]#create a list of all the examples of this feature
     58         uniqueVals = set(featList)       #get a set of unique values
     59         newEntropy = 0.0
     60         for value in uniqueVals:
     61             #计算每种划分方式的信息熵
     62             subDataSet = splitDataSet(dataSet, i, value)
     63             prob = len(subDataSet)/float(len(dataSet))
     64             newEntropy += prob * calcShannonEnt(subDataSet)
     65         infoGain = baseEntropy - newEntropy     #calculate the info gain; ie reduction in entropy
     66         if (infoGain > bestInfoGain):
     67             #计算最好的增益compare this to the best gain so far
     68             bestInfoGain = infoGain         #if better than current best, set to best
     69             bestFeature = i
     70     return bestFeature
     71 
     72 #这与投票代码非常类似,该函数使用分类名称的列表,然后创建键值为classList中唯一值的数据字典,字典对象
     73 # 存储了classList中每个类标签出现的频率,最后利用operator操作键值排序字典,并返回出现次数最多的分类名称。
     74 def majorityCnt(classList):
     75     classCount={}
     76     for vote in classList:
     77         if vote not in classCount.keys(): classCount[vote] = 0
     78         classCount[vote] += 1
     79     sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
     80     return sortedClassCount[0][0]
     81 
     82 #创建树的函数代码
     83 '''
     84 两个输入参数:数据集和标签列表 
     85 '''
     86 def createTree(dataSet,labels):
     87     classList = [example[-1] for example in dataSet]
     88     #类别完全相同则停止继续划分
     89     if classList.count(classList[0]) == len(classList):
     90         return classList[0]#stop splitting when all of the classes are equal
     91     #遍历完所有特征时,返回出现次数最多的
     92     if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet
     93         return majorityCnt(classList)
     94     bestFeat = chooseBestFeatureToSplit(dataSet)
     95     bestFeatLabel = labels[bestFeat]
     96     myTree = {bestFeatLabel:{}}
     97     del(labels[bestFeat])
     98     #得到列表包含的所有属性值
     99     featValues = [example[bestFeat] for example in dataSet]
    100     uniqueVals = set(featValues)
    101     for value in uniqueVals:
    102         subLabels = labels[:]       #copy all of labels, so trees don't mess up existing labels
    103         myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
    104     return myTree
    105 
    106 #使用决策树分类函数
    107 def classify(inputTree,featLabels,testVec):
    108     firstStr = list(inputTree.keys())[0]
    109     secondDict = inputTree[firstStr]
    110     featIndex = featLabels.index(firstStr)
    111     key = testVec[featIndex]
    112     valueOfFeat = secondDict[key]
    113     if isinstance(valueOfFeat, dict):
    114         classLabel = classify(valueOfFeat, featLabels, testVec)
    115     else: classLabel = valueOfFeat
    116     return classLabel
    117 
    118 
    119 myDat,label=createDataSet()
    120 
    121 print('数据集'+ str(myDat))
    122 print('labels'+ str(label))
    123 # A=calcShannonEnt(myDat)
    124 # print('香农熵'+str(A))
    125 # B=splitDataSet(myDat,0,1)
    126 # print('按给定特征划分数据集'+str(B))
    127 # C=chooseBestFeatureToSplit(myDat)
    128 # print('最好的增益'+str(C))
    129 '''
    130 # 结果告诉我们,第0个特征是最好的用于划分数据集的特征。
    131 # 如果我们按照第一个特征属性划分数据,也就是说第一个特征是1的放在一组,
    132 # 第一个特征是0的放在另一组
    133 # '''
    134 mytree=treePlotter.retrieveTree(0)
    135 D=classify(mytree,label,[1,0])
    136 print(D)
  • 相关阅读:
    java基础之条件运算符
    java基础之x++与++x
    java基础之三种注释及API帮助文档的生成
    java基础之类型转换及常量的应用
    java基础之数据类型
    java基础之标识符
    生活小插曲(长篇连载,持续更新ing)^_^
    记录那个刚毕业,还不太富裕的那个人的生活
    记录两次小组会议总结
    这是大娃笔记里的一首散文诗
  • 原文地址:https://www.cnblogs.com/zhibei/p/9351171.html
Copyright © 2020-2023  润新知