数据分析方法-决策树

大家好,这篇文章我们探讨下,决策树算法的相关的知识,决策树是一种分类算法,现在也可以应用与回归,决策树算法的实现有很多种,你可以写Python 代码,也可以调用现成的sklearn包实现!
本文,主要包括三个部分:
1.第一部分,通过图文的方式介绍决策树算法的基本原理
2.第二部分,通过简单的例子,用Python 代码实现一个分类的问题
3.第三部分,调用sklearn包实现决策树算法

Part1: 决策树算法
决策数据算法是通过一系列,精心构建的问题来,通过是或和否的方式,直到找到记录所属的类。现在假设我们发现一个新物种,我们如何如何确定它的科属了,可以通过下面的例子进行说明。


决策树示例.png

决策构建的基本思路是,根据属性不断的对集合进行划分,直到集合中所有的元素都属于同一中类型或者达到指定的样本数量

决策树构建算法1-Hunt:
基本思路:1.如果集合Ct中的的元素所属类型一致,则节点t为叶节点,用yt进行标记
2.如果Dt中包含多个类的记录,则选择一个属性测试条件(体温,胎生),
把记录划分为较小的集合,然后对集合递归的调用这个算法(见上图)。
需要解决的问题:
1.如何确定合适的属性进行划分(体温or胎生)?
2.什么时候停止分裂(一直分裂会导致树变得很复杂)?
1.哪个属性更好
确定属性的常用方法有三种,详见下图


划分的度量标准.png

具体应用示例.png

2.什么时候停止分裂
(待续……)
决策树计算的伪代码

检测数据集中的每个子项是否属于同一分类:
    If so return 类标签
    Else
        寻找划分数据集的最好特征
        划分数据集
        创建分支节点
            for 每个划分的子集
                调用函数createBranch并增加返回结果到分支节点中
        return 分支节点

决策树构建算法2: ID3,C4.5,CART

image.png

Part2:python 代码的实现

from math import log
import   operator
#预定义数据集合
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


#定义函数返回集合的熵
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)   #❷ 以2为底求对数
    return shannonEnt

#数据集划分函数
def splitDataSet(dataSet, axis, value): #待划分的数据集合,划分数据集合的特征,需要返回的特征值
    #创建新的list对象
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            #(以下三行)抽取
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

#选取数据集合的最佳划分方式
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):
        #❶ (以下两行)创建唯一的分类标签列表
        featList = [example[i] for example in dataSet]
        # print(1,featList)
        uniqueVals = set(featList)  #对取值去重
        # print(2,uniqueVals)
        newEntropy = 0.0
        #❷ (以下五行)计算每种划分方式的信息熵
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)
            prob = 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
        else:
            classCount[vote] += 1 # 存在就+1
    sortedClassCount=sorted(classCount.items(),  key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0] #返回出现次数最多的类标签
print("majorityCnt",majorityCnt([1,2,2,3,1,1,3]))
#生成决策树
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) #返回最佳特征
    bestFeatLabel = labels[bestFeat]
    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)
    return myTree
3
#读取数据
myDat,labels2=createDataSet()
print(1,myDat,labels2)
#计算集合的熵
# print("计算集合的熵:\n",calcShannonEnt(myDat))
#返回划分后的数据集合
# print(splitDataSet(myDat,0,0)) #集合,特征,特征取值
# print(splitDataSet(myDat,0,1))
#选择最佳划分特征
# print(chooseBestFeatureToSplit(myDat))
#生成决策树
myTree = createTree(myDat,labels2)
print(myTree)

#利用决策树,对新的数据进行预测
def classify(inputTree,featLabels,testVec): #树,可划分的属性列表
    firstStr = list(inputTree.keys())[0]
    secondDict = inputTree[firstStr]
    #将标签字符串转换为索引
    print(featLabels)
    featIndex = featLabels.index(str(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
#对测试数据进行划分
print(2,myDat,labels2)
print("划分结果\n",classify(myTree,['no surfacing', 'flippers'],[1,1])) #有问题
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容