机器学习02-决策树ID3算法

决策树

概述:通过分析每个数据特征项在分类过程中所起到的所用比重,将数据划分为几个数据子集,如果某个数据子集数据同一类型,则无需再继续划分数据分类,如果不属于同一分类,则需要在对数据子集进行分割。
优点:计算复杂度不高。
缺点:可能会出现由于样本特征值对应的样本数量不统一导致结果偏向于数量多的样本对应的分类。

具体分类算法 ID3算法

在每次划分数据集时我们会取一个特征属性来进行划分,那么这里有一个问题,例如训练样本里面有20个特征值,我们如何从这些特征中选择当前用于划分的最适合的特征项呢?我们需要找到一个有效的量化方法来划分数据。

信息熵

样本id是否需要浮出水面是否有脚蹼属于鱼
1
2
3
4
5

我们划分数据的原则是将无须的数据变得更加有序,这里有一个信息增益的概念:即数据在划分前后的信息发生的变化成为信息增益。因此我们需要计算每个特征值的数据划分之后的信息增益值,选取最大的信息增益特征值作为当前数据划分特征。集合信息的度量方式成为熵,我们需要计算我们的信息集合熵值。
熵的计算公式: H=log2p(xi) 对于集合的熵计算公式: H=ni=1p(xi)log2p(xi)
计算信息熵算法

#-*- coding=utf-8 -*-
from numpy import *
from math import log
import operator

def calcShannonEnt(dataSet):
    labelCounts = {} #统计每个标签的次数
    for line in dataSet:
        label = line[-1]
        labelCounts[label] = labelCounts.get(label, 0) + 1
    shannonEnt = 0.0
    #统计信息熵
    for key in labelCounts:
        prob = float(labelCounts[key])/len(dataSet)
        shannonEnt -= prob * log(prob, 2)
    return shannonEnt

数据划分code

由于是决策树因此我们需要将集合划分为不同的子集

#例如上面的通过是否浮出水面划分数据就能得到两个子集
#子集1
#是否有脚蹼|属于鱼类
#是 | 是
#是 | 是
#否 | 是
#子集2
#是 | 否
#是 | 否
#axis表示特征项,value表示需要匹配的特征值
def splitDataSet(dataSet, axis, value):
    resultDataSet = []
    for line in dataSet:
        if line[axis] == value:
            reduceValue = line[:axis]
            reduceValue.extend(line[axis+1 : ])
            resultDataSet.append(reduceValue)

    return resultDataSet

选择最优的划分属性

由于有上面两个方法作为基础,我们可以通过下面的代码来寻找最适合划分的特征值

def chooseBestSplitFeature(dataSet):
    featureCount = len(dataSet[0]) - 1
    #计算当前的熵值
    currentShannonEnt = calcShannonEnt(dataSet)
    #定义信息增益
    bestInfoGain = 0.0
    #定义返回值
    bestAxis = -1
    #遍历每个特征项
    for i in range(featureCount):
        featureValues = set([value[i] for value in dataSet])
        subShannonEnt = 0.0
        for featureValue in featureValues:
            subDataSet = splitDataSet(dataSet, i, featureValues)
            subDataSetProb = float(subDataSet)/len(dataSet)
            subShannonEnt += subDataSetProb * calcShannonEnt(subDataSet)

        subInfoGain = currentShannonEnt - subShannonEnt
        #判断当先最优的划分特征
        if subInfoGain > bestInfoGain :
            bestInfoGain = subInfoGain
            bestAxis = i

    return bestAxis

构建决策树

我们可以通过一个map来表示我们的决策树

def createTree(dataSet):
    classList = [value[-1] for value in dataSet]
    #如果所有的classList一致则直接返回
    if classList.count(classList[0]) == len(classList):
        return classList[0]

    if len(dataSet[0]) == 1:
        ##这里的case场景是,已经没有可用的特征项时,针对剩余的分类如何决定目标分类
        #return dataSet[0]
        #这里采用取占比最多的值
        return major(dataSet)
    #选择分类属性
    axis = chooseBestSplitFeature(dataSet)
    #定义tree树 属性 index->Map
    myTree = {axis:{}}  
    featureList = set([value[axis] for value in dataSet])
    for feature in featureList :
        mytree[axis][feature] = createTree(splitDateSet(dataSet, axis, feature))

    return mytree

#去占比最多的分类值
def major(dataSet):
    labelCount={}
    for line in dataSet:
        labelCount[line[-1] = labelCount.get(line[-1], 0) + 1

    #排序
    return sorted(labelCount.iteritems(), key = operator.itemgetter(1), reverse=True)[0][0]

关于python的序列化

决策树构建完成之后,我们可以将决策树序列化到一个文件中,以便以后直接使用,这里就涉及到python的序列化模块pickle

import pickle
def storeTree(myTree, fileName):
    fw = open(fileName, 'w')
    pickle.dumps(myTree, fw)
    fw.close()

def readTree(fileName):
    fr = open(fileName)
    return pickle.load(fr)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值