我的机器学习之路-决策树

1.什么是决策树

决策树(DTS)是一种用于分类和回归的非参数监督学习方法。目标是创建一个模型,预测目标变量的值,通过学习简单的决策规则推断的数据特征。是一个类似于流程图的树结构:其中,每个内部结点表示在一个属性上的测试,每个分支代表一个属性输出,而每个树叶结点代表类或类分布。树的最顶层是根结点。
2.熵

1948年,香农提出了 ”信息熵(entropy)“的概念 一条信息的信息量大小和它的不确定性有直接的关系,要搞清楚一件非常非常不确定的事情,或者是我们一无所知的事情,需要了解大量信息==>信息量的度量就等于不确定性的多少。可以用下面的公式计算。
这里写图片描述

3 代码

# -*- coding: utf-8 -*-
"""
Created on Mon May  8 13:49:04 2017

@author: ThinkCentre
"""
from math import log
import operator
#==============================================================================
# 计算香浓熵
#==============================================================================
def calcshannonEnt(dataSet):
    #计算dataSet的列数
    numEntries=len(dataSet)
    #定义标签字典
    labelCounts ={}
    #遍历数据集dataSet的每一个列表featVec
    for featVec in dataSet:
        #取分类currentLabel(yes,no)
        currentLabel = featVec[-1]
        #计算每一个分类下yes,no的个数,用字典保存
        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 creatDataSet():
    dataSet = [[1,1,'yes'],
               [1,1,'yes'], 
               [1,0,'no'],
               [0,1,'no'],                            
               [0,1,'no']]
    labels = ['no surfacing','flippers']
    return dataSet,labels
#==============================================================================   
# 划分数据集    
#==============================================================================
def splitDataSet(dataSet,axis,value):
    retDataSet =[]
    for featVec in dataSet:
        #判断featVec的第axis值是否等于value
        if featVec[axis] == value:
            #reducedFeatVec的值为featVec除了第axis个值之外的值
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            #得到划分过的dataset
            retDataSet.append(reducedFeatVec)
    return retDataSet

#==============================================================================
# 计算最好的划分方式
#==============================================================================

def chooseBestFeatureToSplit(dataSet):
     #计算特征的数量
    numFeatures = len(dataSet[0])-1
    # calculate shannon  entropy
    baseEntropy = calcshannonEnt(dataSet)

    bestInfoGain = 0.0;bestFeature = -1
    for i in range(numFeatures):
        # 选择对应I的列
        featList = [example[i] for example in dataSet]
        # 取每一个featList 的集合uniqueVals
        uniqueVals = set(featList)
        newEntropy =0.0
        #遍历集合uniqueVals里的每一个元素value
        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 ={}
    #添加新特征到classCount
    for vote in classList:
        if vote not in classCount.keys:
            classCount[vote] += 1
        #排序
        sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reversed =True)
    return sortedClassCount[0][0]

#==============================================================================
# 建立决策树
#==============================================================================
def creatTree(dateSet,labels):
    #得到分类列表
    classList = [example[-1] for example in dateSet]
    #判断classList[0]即第一个标签的数量是否等于标签列表的长度,也就是说当类别相同时停止划分
    if classList.count(classList[0]) ==len(classList):
        return classList[0]
    #当数据集的每一行的长度为1时,返回出现次数最多的特征
    if len(dateSet[0]) == 1:
        return majorityCnt(classList)
    #得到使划分方式最优的特征
    bestFeat = chooseBestFeatureToSplit(dateSet)
    bestFeatLabel = labels[bestFeat]
    myTree = {bestFeatLabel:{}}
    #删除列表中最好的那个特征
    del(labels[bestFeat])
    #得到对应最好特征的值
    featValues = [example[bestFeat] for example in dateSet]
    uniqueVals = set(featValues)
    #向字典myTree插入相应的分类结果,并遍历
    for value in uniqueVals:
        subLabel = labels[:]
        myTree[bestFeatLabel][value] = creatTree(splitDataSet(dateSet,bestFeat,value),subLabel)
    return myTree        

4.测试
新建文件test.py

import DecisionTree
myDat, labels = DecisionTree.creatDataSet()
myTree = DecisionTree.creatTree(myDat,labels)
print(myTree)

保存运行,得到结果

 {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值