决策树 机器学习实战

'''
    需要文件联系我
    决策树
    优点: 计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关特征数据
    缺点:可能会产生过度匹配问题
    适用数据类型:数值型,标称型

    一般流程:
        收集数据
        准备数据:数构造算法只适合用于标称型数据,因此数值型数据必须离散化
        分析数据
        训练算法
        测试算法
        使用算法

    划分数据集:
        检测数据集中的每个子项是否属于同一分类
        If so return 类标签
        Else
            寻找划分数据集的最好特征
            划分数据集
            创建分支节点
                For 每个划分的子集
                    调用函数createBranch并增加返回结果到分支点中
            Return 分支节点
    信息增益——————
        原则:将无序数据变为有序数据
        集合信息的度量方式成为香浓熵或者简称熵(ShannonEnt)
        熵定义为信息的期望
        l(xi) = -log2p(xi)   p(xi)表示选择该分类的概率
    计算所有类别所有可能值包含的信息期望
        H = -Σp(xi)log2p(xi)   1->n 

    熵越高混合的数据越高
    得到熵之后可以按照获取最大信息增益的方法划分数据集
    另一个方法基尼不纯度 
    
'''
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', 'fippers']
    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 #创建一个新的标签键值 并且设置为0
        labelCounts[currentLabel] += 1 #当前标签+1
    ShannonEnt = 0.0 #计算香农熵
    for key in labelCounts: # 对于每个标签
        prob = float(labelCounts[key])/numEntries #计算当前标签的概率
        ShannonEnt -= prob*log(prob, 2) #计算log
    return ShannonEnt #返回香农熵
'''
myDat, labels = createDataSet()
shannon = calcShannonEnt(myDat)
print(shannon)
myDat[0][-1] = 'maybe'
shannon = calcShannonEnt(myDat)
print(shannon)
'''

def splitDataSet(dataSet, axis, value):
    # 划分数据集
    # 带划分的数据集,划分数据集的特征, 需要返回的特征值
    retDataSet = [] #存值
    for featVec in dataSet: # 对于每一个数据
        if featVec[axis] == value: #如果是需要返回的数据
            reducedFeatVec = featVec[:axis] # 复制
            reducedFeatVec.extend(featVec[axis+1:]) #复制  extend 在list 后 一次性追加多个值
            retDataSet.append(reducedFeatVec)
    return retDataSet
        
def chooseBestFeatureToSplit(dataSet):#选择最好的数据集划分方式
    numFeatures = len(dataSet[0]) - 1 #计算数据形状 最后一列’yes‘ ’no‘ 不计算
    baseEntropy = calcShannonEnt(dataSet) #计算香农熵
    bestInfoGain = 0.0 # 最好的信息增益
    bestFeature = -1   # 最好的特征值
    for i in range(numFeatures): #对于每一个特征值
        featList = [example[i] for example in dataSet] #每一列的值
        uniqueVals = set(featList) #创建唯一的分类标签
        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
        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]
   # print('go')
    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

'''' 
myDat, labels = createDataSet()
myTree = createTree(myDat, labels)
print(myTree)

'''

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值