ML基础-决策树-2-获取最好的划分数据集合特征

数据源

不浮出水面可以生存是否有脚蹼是否属于鱼类
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
        #以2为底求对数log2(下)prob(上),计算香农熵
        shannonEnt-=prob* log(prob,2)

    return shannonEnt

在这复习一下信息增益和香农熵的概念

  • 熵:集合信息的度量方式。熵越高,混合的数据越多。
    下面的代码做一个验证:

myDat, labels = createDataSet()
print(calcShannonEnt(myDat))
print(11111111111111111111111111111111)
myDat[0][-1] = 'maybe'
print(calcShannonEnt(myDat))
print(22222222222222222222222222222222)

#
#0.9287712379549449
#11111111111111111111111111111111
#1.3931568569324173
#22222222222222222222222222222222
#

如果给myDat加一个不同的数据,熵的值更高。

划分数据及

#
# 按照指定特征划分数据集合
#  dataset 等待划分的数据集合
#  axis 划分数据集的特征
#  value 需要返回的的特征的值
#
#返回的是
#
def splitDataSet(dataSet, axis, value):
    # ❶ 创建新的list对象
    #创建这个list对象的原因是为了不修改原始数据集合,因为splitDataSet函数在同一数据上多次引用
    retDataSet=[];
    for featVec in dataSet:
        if featVec[axis] ==value:
            # ❷ (以下三行)抽取
            reducedFeatVec = featVec[:axis]
            #如果使用a.append(n),[1,2,3,[4,5,6,]];而a.extend(b)==[1,2,3,4,5,6]
            reducedFeatVec.extend(featVec[axis + 1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

我再做一个验证


myDat, labels = createDataSet()
print(myDat)
print(11111111111111111111111111111111)

r1=splitDataSet(myDat,0,1)
r2=splitDataSet(myDat,0,0)
print(r1)
print(r2)
print(33333333333333333333333333333333333333333333333333333)
#
#[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
#11111111111111111111111111111111
#[[1, 'yes'], [1, 'yes'], [0, 'no']]
#[[1, 'no'], [1, 'no']]
#33333333333333333333333333333333333333333333333333333
#

可以先理解为将数据源的第一项进行了区分,将1,0的值进行了返回。

获取最佳的数据划分方式

#
# 选取特征,划分数据集合,计算出最好的划分数据集特征
#要求:
# 1,数据必须是一种由列表元素组成的列表,而且所有列表元素都具有相同的数据长度
# 2,数据的最后一列,或者每个实例最后一个元祖是当前实例的类别的标签
#
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    #计算了整个数据集的原始香农熵,保存最初的无序度量值,用于与划分完之后的数据集计算的熵值进行比较。
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0; bestFeature = -1
    #第一个for循环遍历了所有特征
    for i in range(numFeatures):
        #❶ (以下两行)创建唯一的分类标签列表,
        #创建新的列表,将数据集中所有第i个特征值写入这个新列表
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        newEntropy = 0.0
        #❷ (以下五行)计算每种划分方式的信息熵
        #遍历当前特征中的唯一属性值,对每一个特征划分一次数据集2
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)
            #len计算元素个数
            prob = len(subDataSet)/float(len(dataSet))
            newEntropy += prob * calcShannonEnt(subDataSet)
            infoGain = baseEntropy - newEntropy
            #信息增益是熵的减少或者数据无须度的减少
            if (infoGain > bestInfoGain):
                #❸  计算最好的信息增益
                 bestInfoGain = infoGain
                 bestFeature = i
        return bestFeature

## set 是集合数据类型,从列表中从创建集合是python语言中得到列表中唯一元素值的最快方法

遍历当前特征中的唯一属性值,对每个特征划分一次数据集合,计算这个集合的熵,比较信息增益(即熵的减少),返回最好的索引值。

myDat, labels = trees.createDataSet()
print(chooseBestFeatureToSplit(myDat))

上述代码返回的是0,也就是说明这是最好用于划分数据集合的特征。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值