ML基础-决策树-5-测试和存储分类器

博客有没保存,记性差到已经忘了写了什么。

python相关知识

pikcle:

通过序列号实现持久化,在计算的时候可以把树进行持久化。
相关文章:https://www.cnblogs.com/tkqasn/p/6005025.html

# pickle:暂时持久化的set 与 get
def storeTree(inputTree, filename):
    import pickle
    fw = open(filename, 'w')
    pickle.dump(inputTree, fw)
    fw.close()

def grabTree(filename):
    import pickle
    fr = open(filename)
    return pickle.load(fr)

测试

分类器

#
# inputTree  树
# featLabels  显示的种类
# testVec ,就是判断的依据
#
def classify(inputTree, featLabels, testVec):
    # 获取第一个标签字符串
    firstStr = list(inputTree.keys())[0]
    # 根据标签字符串取得该标签下的树的数据数据
    secondDict = inputTree[firstStr]
    # ❶将标签字符串转换为索引
    featIndex = featLabels.index(firstStr)
    # 遍历改标签下树的key
    for key in secondDict.keys():
        # 如果testVec[索引]==key的时候,说明得到判断的依据,例子为0,1
        if testVec[featIndex] == key:
            if type(secondDict[key]).__name__ == 'dict':
                classLabel = classify(secondDict[key], featLabels, testVec)
            else:
                classLabel = secondDict[key]
    # 最后的classLabel就是判断依据的key 得到的值
    return classLabel
#打开文件
fr=open('lenses.txt')
#获得lenses的矩阵,即之前使用的myDat
lenses=[inst.strip().split('\t') for inst in fr.readlines()]
print(lenses)
#获得lenses的矩阵,即之前使用的labels
lensesLabels = [ 'tearRate','age', 'prescript', 'astigmatic']
lensesTree =createTree(lenses, lensesLabels)
print(lensesTree)
#创建
createPlot(lensesTree)

运行后得到了错误的结果。这里写图片描述

关于这个错,如何定位就成了问题。
1,我先对比了lenses和tree在正确版本和我做的版本中的区别,结果发现原始数据的结果一样,tree出现了问题。
那只能回到createTree中去看看了,追踪一下错误

错误1:def calcShannonEnt(dataSet)
 for featVec in dataSet:
        # 创建一个数据字典,它的键值是最后一列的数
        currentLabel = featVec[-1]
        # 如果当前键值不存在,则扩展字典并将当前键值加入字典
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
            labelCounts[currentLabel] += 1
        shannonEnt = 0.0

正确的代码应该是,当前分类,也就是结果在labelCounts中不存在添加,如果存在将+1,
最后得到应该是这个分类和出现个数的键值,如下:
{‘no lenses’: 15, ‘soft’: 5, ‘hard’: 4}

    for featVec in dataSet:
        # 创建一个数据字典,它的键值是最后一列的数
        currentLabel = featVec[-1]
        # 如果当前键值不存在,则扩展字典并将当前键值加入字典
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    shannonEnt = 0.0
错误1:def hooseBestFeatureToSplit(dataSet):

根据数据集合选择组好的分类特征

 def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    # 计算了整个数据集的原始香农熵,保存最初的无序度量值,用于与划分完之后的数据集计算的熵值进行比较。
    baseEntropy = calcShannonEnt(dataSet)
    print(baseEntropy)
    bestInfoGain = 0.0;
    bestFeature = -1
    # 第一个for循环遍历了所有特征
    for i in range(numFeatures):
        # ❶ (以下两行)创建唯一的分类标签列表,
        # 创建新的列表,将数据集中所有第i个特征值写入这个新列表
        # 获得所有数据第i个特征组成给一个列表,在uniquevals进行去重
        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
            # 信息增益是熵的减少或者数据无须度的减少,所以infoGain越大说明新的enwEntropy越小,数据越好。
            if (infoGain > bestInfoGain):
                # ❸  计算最好的信息增益
                bestInfoGain = infoGain
                bestFeature = i
        return bestFeature

正确的代码应该是

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    # 计算了整个数据集的原始香农熵,保存最初的无序度量值,用于与划分完之后的数据集计算的熵值进行比较。
    baseEntropy = calcShannonEnt(dataSet)
    print(baseEntropy)
    bestInfoGain = 0.0;
    bestFeature = -1
    # 第一个for循环遍历了所有特征
    for i in range(numFeatures):
        # ❶ (以下两行)创建唯一的分类标签列表,
        # 创建新的列表,将数据集中所有第i个特征值写入这个新列表
        # 获得所有数据第i个特征组成给一个列表,在uniquevals进行去重
        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
            # 信息增益是熵的减少或者数据无须度的减少,所以infoGain越大说明新的enwEntropy越小,数据越好。
        if (infoGain > bestInfoGain):
            # ❸  计算最好的信息增益
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature

这个地方再次出现了缩进问题,通过这个特征(i是他的index),求出的各个子集的新的熵值,熵越小说明数据越整合,也就是说infoGain越大越好。这样我们抽出最好的特征来逐层级判断。
结果如下:
这里写图片描述

看起来这棵树好多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值