机器学习day5 机器学习实战决策树的实现预测隐形眼镜类型

今天中午开始实现决策树ID3的实现,KNN的缺点是不能体现数据的意义,全部数据全部归一化,决策树能体现数据的意义,根据数据分类。

先用一个一般的数据测试一下,隐形眼镜类型只不过是增加了一步从文件中提取数据这一步,其他步骤一模一样。

用matplotlib图形化展示效果特别好,但是特别费劲,没有一些特别麻烦的函数,所以这里不再给出,时间问题没能整明白,参考《机器学习实战》。

将在以后的学习里加入CART这一流行的决策树。

step1:

创建一个可以测试的数据,dataset和lavels

#创建数据集
def createDataSet():
    dataset = ([[1, 1, 'yes'],
            [1, 1, 'yes'], 
            [1, 0, 'no'], 
            [0, 1, 'no'], 
            [0, 1, 'no']])
    lavels = ['no surfacing', 'flippers']
    return dataset, lavels

有2个特性,2种标签。

step2:

计算数据集的香农熵,公式不再赘述。这里先把函数写在ID3.py,留待下面用。

#计算数据集的香农熵
def countShannonEnt(dataset):
    datalen = len(dataset)
    diclavels = {}
    for i in dataset:
        templavel = i[-1]
        if templavel not in diclavels.keys():
            diclavels[templavel] = 0
        diclavels[templavel] += 1
    shannonent = 0.0
    for key in diclavels.keys():
        temp = float(diclavels[key])/datalen
        shannonent -= temp * log(temp, 2)
    return shannonent   
根据所传入的dataset集中的结果标签分布计算混乱度,也就是香农熵。

step3:

dataset为要划分的数据集,axis为要划分特性的列,value为划分的特征值。

#根据特征划分数据集 参数为数据集,特性列数,特征值
def splitDataSet(dataset, axis, value):     
    newdataset = []
    for i in dataset:
        if i[axis] == value:
            newline = i[ : axis]
            newline.extend(i[axis + 1 : ])
            newdataset.append(newline)
    return newdataset

step4:

从dataset中选择一个最好的特性,计算信息增益,选择信息增益最大的那个特性。

#选择最好的特性进行分类
def chooseBestFeatureToSplit(dataset):
    featruenums = len(dataset[0]) - 1
    baseshannonent = countShannonEnt(dataset)
    bestfeatrue = -1
    bestgain = 0.0
    for i in range(featruenums):
        featruelist = [x[i] for x in dataset]
        newfeatruelist = set(featruelist)
        newent = 0.0
        for ii in newfeatruelist:
            subdataset = splitDataSet(dataset, i, ii)
            subshannon = countShannonEnt(subdataset)
            p = len(subdataset)/float(len(dataset))
            newent += p * subshannon
        tempgain = baseshannonent - newent
        if tempgain >= bestgain:
            bestgain = tempgain
            bestfeatrue = i
    return bestfeatrue    
step5:

当没有特性可以选取时,但数据集标签还没有统一,进行类似KNN的投票。

#类似KNN的投票器,当没有特性进行分类的时候选当前最多的标签作为该数据集的标签
def noFeatrueToSplit(mat):
    templavels = {}
    for i in mat:
        if i not in templavels.keys():
            templavels[i] = 0
        templavels[i] += 1
    sortlavels = sorted(templavels.iteritems(),\
    key = operator.itemgetter(1), reverse = True)
    return sortlavels[0][0]

step6:

树的创建:

先是判断是不是标签统一,然后判断是不是没有特性可以选取,没有特性可以选取的话进行step5的投票。

然后选取一个最优特性,删除特性标签中的最优特性对应的标签,然后递归进行树的划分,3个小细节。

1:创建树的时候特性标签要重新复制一个,因为引用传递的话会改变原数组的值,会影响后面的划分。

2:用set进行压缩重复的元素,这样可以得到该特性的几种分类。

3:用递归创建。

#树的创建
def createTree(dataset, lavels):
    lavelslist = [ll[-1] for ll in dataset]
    if lavelslist.count(lavelslist[0]) == len(lavelslist):
        return lavelslist[0]
    if len(dataset[0]) == 1:
        return noFeatrueToSplit(dataset)
    bestfeatrue = chooseBestFeatureToSplit(dataset)
    bestlavel = lavels[bestfeatrue]
    myTree = {bestlavel : {}}
    #删除标签里这一行,因为数据集中接下来分类的时候也要删除最佳特性这一行
    del (lavels[bestfeatrue])
    featruetimes = [ll[bestfeatrue] for ll in dataset]
    featruenum = set(featruetimes)
    for i in featruenum:
        sublavels = lavels[ : ]
        myTree[bestlavel][i] = createTree(splitDataSet(dataset, \
        bestfeatrue, i), sublavels)
    return myTree     
step7:

察看测试结果:

atep8:

决策树的分类函数根据之前得出的myTree,test参数为我们要进行测试的数据。

#决策树的分类函数
def type(myTree, lavels, test):
    #取得该树的分类特性标签
    firstfeatrue = myTree.keys()[0]
    feaindex = lavels.index(firstfeatrue)
    seconddict = myTree[firstfeatrue]
    for keytemp in seconddict.keys():
        if keytemp == test[feaindex]:
            if isinstance(seconddict[keytemp], dict):
                reslavel = type(seconddict[keytemp], lavels, test)
            else:
                reslavel = seconddict[keytemp]
    return reslavel

接下来进行隐形眼镜的预测:

step9:

从文本文件中读取数据并现实结果:

import ID3
f = open('lenses.txt')
lines = f.readlines()
lines
lenses = [line.strip().split('\t') for line in lines]
lenses
lenseslavels = ['age', 'prescript', 'astigmatic', 'tearRate']
lensesTree = ID3.createTree(lenses, lenseslavels)
lensesTree

结果正确,缺点是结果看着不好辨认,不如图形界面看起来直观,所以有时间看一下matplotlib图形化是怎么实现的,才算是真正完成了任务。

时间紧急,明天抓紧时间看基于概率论的分类方法:朴素贝叶斯。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值