[Python源码解析]机器学习-决策树

在学习机器学习的源码,记录下对该代码的理解。

1.1 计算数据集的熵

待分析的数据集列表如下,首先根据表3-1构建数据集。

源码如下:

def createDataSet():
    dataSet = [[1, 1, 'yes'], #index=0,就是“不浮出水面是否可以生存”,index=1,就是“是否有脚蹼”,最后一个是"是否鱼类"
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
    labels = ['no surfacing','flippers']
    #change to discrete values
    return dataSet, labels

这个比较简单。

计算该数据集熵的源码:

def calcShannonEnt(dataSet):
    numEntries = len(dataSet)#该数据集长度,即有多少个数据,这里等于5
    labelCounts = {}#特征结果字典,比如以index=2,对数据集进行分类,则labelCounts就是yes和no的个数统计,YES:2, no:3;这样的字典。
    for featVec in dataSet: #the the number of unique elements and their occurance,逐行遍历
        currentLabel = featVec[-1]#取每个元素的倒数第一个值,也就是index=2这一列
        if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0#如果字典中,不包含当前特征值,则字典中加入该特征。
        labelCounts[currentLabel] += 1#该特征计数
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key])/numEntries#分别计算YES和NO 出现的概率,这里分别为0.6,和0.4
        shannonEnt -= prob * log(prob,2) #log base 2#根据计数公式,计算熵
    return shannonEnt

1.2 根据特征,划分数据集

dataSet就是数据集,axis就是选择的特征,value,就是对应特征的值。

这个方法比较简单,以上面的dataSet为例,如果axis=0,就是选择第一列特征,即:"不浮出水面是否可以生存";这个特征有两个值,就是1和0,所以对应的value就是1和0;

def splitDataSet(dataSet, axis, value):
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]     #chop out axis used for splitting
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet
    

如果分别执行执行以下代码:

subDataSet1 = splitDataSet(dataSet, 0, 1)
subDataSet2= splitDataSet(dataSet, 0, 0)

分别得到结果是:

subDataSet1 =     subDataSet2 = 

可见,这个方法就是根据特征值的不同把数据集划分子数据集。在这里,就是根据特征“不浮出水面是否可以生存”的值1和0,分成了两个上图两个子集。


1.3 选择最佳分类特征

当我们拿到一个数据集,需要用决策树进行分类是,我们如何从众多特征中选择一个特征,作为决策树的第一个分类点呢?比如上述“不浮出水面是否可以生存” 和“是否有脚蹼”这两个特征,我们应该先选哪个特征进行分类呢?

这就需要用到1.1和1.2的分类方法。

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1      #the last column is used for the labels 计算特征个数,这个例子中等于2
    baseEntropy = calcShannonEnt(dataSet)#计算原始数据集的熵
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):        #iterate over all the features,根据特征进行迭代,从index=0,到1;
        #获取index=0的特征对应的所有值,即取dataSet矩阵每列的所有值。     
        featList = [example[i] for example in dataSet]#create a list of all the examples of this feature,
        uniqueVals = set(featList)       #get a set of unique values,统计每个特征对应的值有多少可能,比如这里index=0的特征,只有两个值0,1
        newEntropy = 0.0
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)#针对每个特征,划分子集
            #比如对index=0的特征进行子集划分,特征值为0的有2个,为1的有3个;权重分别为2/5,  3/5
            prob = len(subDataSet)/float(len(dataSet))#计算每个子集的权重,
            newEntropy += prob * calcShannonEnt(subDataSet)#计算总熵值,权重*子熵     
        infoGain = baseEntropy - newEntropy     #calculate the info gain; ie reduction in entropy,计算分类后熵和原来熵的差值
        if (infoGain > bestInfoGain):       #compare this to the best gain so far,差值越大,(也就是子集熵越小),分类越合理。
            bestInfoGain = infoGain         #if better than current best, set to best
            bestFeature = i
    return bestFeature                      #returns an integer

综合来说,就是根据特征值,进行分类,计算每个分类之后熵值的大小,然后进行排序,熵值越小,分类越合理。

就优先以该特征值进行划分。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值