博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
机器学习实战之决策树(一)
阅读量:4054 次
发布时间:2019-05-25

本文共 4947 字,大约阅读时间需要 16 分钟。

最近在看《机器学习实战》的第三章,记录一下

KNN算法无法给出数据内部的联系,而决策树算法通过提取一系列的规则,从而了解数据之间的内部联系。

决策树算法适用于数值型和标称型。数值型表示无限数据中,数据较为具体化,通常用于回归分析。标称型表示一般在有限的数据中取得,而且只存在是和否两种结果。

构造决策树时,首先需要知道哪个特征在划分数据分类时会起决定化的作用。这里我们就需要划分数据集。决策树的一般流程包括:收集数据,准备数据(树构造算法只适用于标称型的数据,数值型的数据必须离散化),分析数据,训练数据(构造树的数据结构),测试算法(使用经验树计算错误率),使用算法。

下面将以海洋生物数据表作为测试数据

………….不浮出水面是否可以生存 ………. 是否有脚蹼 ……… 属于鱼类

1…………………..是………………………………是………………..是
2…………………..是………………………………是………………..是
3…………………..是………………………………否………………..否
4…………………..否………………………………是………………..否
5…………………..否………………………………是………………..否

所以利用createDataSet() 得到表的鉴定集

def createDataSet():    dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]    label = ['no sufacing','flippers']    return dataSet,label

测试一下

>>> import chosetree as ct>>> dataset,label = ct.createDataSet()>>> dataset[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]>>> label['no sufacing', 'flippers']

在说下面内容时,先谈一谈几个概念(公式写的都比较粗糙,别介意啊)

信息增益:在划分数据集之前之后信息发生的变化。在这里我们可以认为是特征熵和数据集熵的差值;
熵(香农熵):集合信息的度量方式,是信息的期望值。
第i分类的信息公式为l(xi) = log2P(xi)
以上表(第三列)为例:
p(x)=2/5 表示‘是‘的比例,p(x)=3/5表示否的比例
为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,
公式为 H = -∑i=1p(xi)log2p(xi)
以上表(第三列)为例:
H= -(2/5)*log2(2/5) - (3/5)*log2(3/5)=0.97095….

计算给定数据集的香农熵:

from math import logdef 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        shannonEnt -= prob*log(prob,2)    return shannonEnt

测试一下

>>> shannonEnt = ct.calcShannonEnt(dataset)>>> shannonEnt0.9709505944546686

说明; 熵越大说明类别越多,即混合的数据较为多

划分数据集

先放代码
这里使用了三个输入参数:带划分的数据集,划分数据集的特征(在这里实际上就是选择第几列特征),需要返回的特征的值

def splitDataSet(dataSet,axis,value):#创建空列表,存放划分后的数据集    retDataSet = []    for featVec in dataSet:    #判断axis所对应的数据与要求的value是否相同,如果相同则将每一行除featVec[axis]之外的所有数据放在reduceFeatVec中        if featVec[axis]==value:            reduceFeatVec = featVec[:axis]            reduceFeatVec.extend(featVec[axis+1:])            retDataSet.append(reduceFeatVec)    return retDataSet

测试

>>> retDataSet = ct.splitDataSet(dataset,0,1)>>> retDataSet[[1, 'yes'], [1, 'yes'], [0, 'no']]

上述测试表示第0列的数据是否等于1 ,等于1就将符合条件的列表输出

选出最好的数据集划分方式

代码:

def chooseBestFeatureToSplit(dataSet):#计算所有的特征数    numFeatures = len(dataSet[0])-1    #调用函数获得数据集的香农熵    baseEntropy = calcShannonEnt(dataSet)    bestInfoGain = 0.0    bastFeature = -1    for i in range(numFeatures):        #获得该列特征的所有数值,并去重        featList = [example[i] for example in dataSet]        uniqueVals = set(featList)        newEntropy = 0.0        #计算该列的香农熵        for value in uniqueVals:            subDataSet = splitDataSet(dataSet,i,value)            prob = len(subDataSet)/float(len(dataSet))            newEntropy = prob*calcShannonEnt(subDataSet)        infoGain = baseEntropy - newEntropy        #选出熵最大的特征划分数据集        if infoGain > bestInfoGain :            bestInfoGain = infoGain            bestFeature = i    return bestFeature

测试

>>> bestFeature = ct.chooseBestFeatureToSplit(dataset)>>> bestFeature0

bestFeature所代表的意思:

>>> label[0]'no sufacing'

递归构建决策树

先思考一个问题:如果数据集已经处理列所有的属性,但类标签依然不是唯一的,此时我们需要决定如何定义该叶子节点,在这种情况下,我们通常会采用多数表决的方法决定该叶子节点的分类。

def majorityCnt(classList):    classCount = {}    for vote in classList:        if vote not in classCount.keys():            classCount[vote] = 0        classCount[vote] += 1        #@classCount.items 列表对象    #@key=operator.itemgetter(1) 获取列表对象的第一个域的值    #@reverse=true 降序排序,默认是升序排序    sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)    return sortedClassCount[0][0]

创建树的函数代码

def createTree(dataSet,labels):#获得所有的类标签    classList = [example[-1] for example in dataSet]    #当所有的类标签为同一个时,直接返回该类标签    if classList.count(classList[0]) == len(classList):        return classList[0]     #当使用完所有特征值仍然不能将数据集划分为仅包含唯一类别的分组,即调用majorityCnt函数    if len(dataSet[0]) ==1:        return majorityCnt(classList)        #选择最好的特征值    bestFeat = chooseBestFeatureToSplit(dataSet)    bestFeatlabel = labels[bestFeat]    #构建决策树    myTree = {bestFeatlabel:{}}    #删除以使用过的标签,防止对后面迭代产生影响    del(labels[bestFeat])    featvalues = [example[bestFeat] for example in dataSet]    uniqueVals = set(featvalues)    for value in uniqueVals:            #采用递归的方法利用该特征对数据集进行分类        #@bestFeatLabel 分类特征的特征标签值        #@dataSet 要分类的数据集        #@bestFeat 分类特征的标称值        #@value 标称型特征的取值        #@subLabels 去除分类特征后的子特征标签列表        subLabels = labels[:]        myTree[bestFeatlabel][value] = createTree(splitDataSet(dataSet,bestFeat,value),subLabels)    return myTree

测试代码:

>>> mytree = ct.createTree(dataset,label)>>> mytree{
'no sufacing': {
0: 'no', 1: {
'flippers': {
0: 'no', 1: 'yes'}}}}

好啦,暂时先写这么多,下一节我在放上测试算法和使用决策树预测隐形眼镜类型的例子

个人见解,如有错误请帮忙指出,谢谢

转载地址:http://pwhci.baihongyu.com/

你可能感兴趣的文章
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux irqdebug
查看>>
git 常用命令
查看>>
linux位操作API
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
忽略图片透明区域的事件(Flex)
查看>>
AS3 Flex基础知识100条
查看>>
Flex动态获取flash资源库文件
查看>>
01Java基础语法-16. while循环结构
查看>>
Django框架全面讲解 -- Form
查看>>
今日互联网关注(写在清明节后):每天都有值得关注的大变化
查看>>
”舍得“大法:把自己的优点当缺点倒出去
查看>>
[今日关注]鼓吹“互联网泡沫,到底为了什么”
查看>>
[互联网学习]如何提高网站的GooglePR值
查看>>
[关注大学生]求职不可不知——怎样的大学生不受欢迎
查看>>