机器学习实战之决策树

来源:互联网 发布:园林设计用什么软件 编辑:程序博客网 时间:2024/05/21 15:00

1.决策树与k近邻算法对比

  • k近邻算法最大的缺点就是无法给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解.
  • 决策树由结点和有向边组成,结点包含2种类型:内部结点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类.
  • 决策树分类时,从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子结点;这时,每个子结点都对应该特征的一个取值,如此递归地对实例进行测试并分配,直到达到叶结点,最后将实例分到叶节点的类中.

2.决策树的优缺点

  • 优点
              计算复杂度不高,输出结果易理解,比较适合处理有缺失属性值的样本,可以处理不相关特征数据.
  • 缺点
              可能产生过度匹配问题,为了减少过度匹配,可以裁剪决策树,去掉一些不必要的叶子节点.若叶子节点只能增加少量信息,可以删除该节点,将其并入其它叶子节点中.

3.决策树的产生过程

(1)关键思想:

本次采用ID3算法;在决策树哥哥节点上应用信息增益准则选择特征,递归的构建决策树;

具体方法:

  • 从根节点开始,对节点计算所有可能的特征的信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值创建子节点;由特征的不同取值可以将原数据集划分为几个不同的数据集,分别计算信息增益;
  • 对子结点递归的调用上述步骤,构建决策树;
  • 直到所有数据属于同一个分类或没有特征可以选择为止,得到最终的决策树.

(2)算法结束条件:

        若当前数据集的所有实例都属于同一类k,则此时的决策树T为单节点,将类k作为该节点的类标记,并返回T;

       若当前数据集的特征集为空,则将数据集中出现次数最多的类k作为该节点的类标记,返回该节点;

(3)创建决策树的流程:

检测数据集中的每个子项是否属于同一个分类:

        if so return 类标签;

        else

              寻找划分数据集的决定性特征

              划分数据集

              创建分支节点

                        for 每个划分的子集

                                调用此函数并增加返回结果到分支节点中

               return 分支节点


实现python代码如下:

输入为训练数据集和训练数据集对应的特征集;

<span style="font-size:14px;">def createTrees(dataSet,label):classList = [example[-1] for example in dataSet]#the label is totally same, end the iterif classList.count(classList[0]) == len(dataSet): #数据集都属于同一个分类return classList[0]#only one feature, take th majority features  if len(dataSet[0]) == 1: #特征集为空,选择数据集中出现次数最多的类返回return majorityLabel(classList)bestFeatureIndex = chooseBestFeature(dataSet)bestFeature = label[bestFeatureIndex]myTree = {bestFeature:{}}del(label[bestFeatureIndex])featureValue = [example[bestFeatureIndex] for example in dataSet]uniqueFeatureValue = set(featureValue)for value in uniqueFeatureValue:subLabel = label[:]myTree[bestFeature][value] = createTrees(splitDataSet(dataSet,bestFeatureIndex,value),subLabel)return myTree</span>


4.如何寻找决定性特征

划分数据集的基本原则是:将无序的数据变得更加有序.

划分数据集的方法:

(1)使用信息论度量信息:

  • 熵(entropy)表示随机变量不确定性的度量.

         x是一个取有限个值(可以取n个不同值)的离散随机变量,其概率分布为p(x=xi)=pi,i=1,2,...,n,则随机变量x的熵定义为H(x)=-(p1logp1+p2logp2+....+pnlog(pn))

         熵依赖于x的分布,与x的取值无关,因此x的熵也可以写作H(p).0<=H(p)<=logn;熵越大,随机变量的不确定性就越大.

  • 条件熵(condition entropy)H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性.即随机变量X给定的条件下随机变量Y的条件熵,定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

         H(Y|X)=P1*H(Y|X=x1)+P2*H(Y|X=x2)+...+PN*H(Y|X=xn)  其中,Pi=P(X=xi)

  • 当熵和条件熵中的概率由数据估计(特别是极大似然估计)得到时,所对应的熵与条件熵称为经验熵和经验条件熵
  •  信息增益(information gain):表示得知特征x的信息而使得类y的信息的不确定性减少的程度

          特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即g(D,A)=H(D)-H(D|A),信息增益也称为互信息.

  • 信息增益比(information gaim ratio):特征A对训练数据集D的信息增益比为其信息增益g(D,A)和训练数据集D的经验熵H(D)的比.信息增益比也是值越大越好.


信息增益表示由于特征A而使得对数据集D的分类的不确定性减少的程度,信息增益大的特征具有更强的分类能力;

根据信息增益准则的特征选择方法是:对训练数据集D,计算其每个特征的信息增益,并比较其大小,选择信息增益最大的特征.

计算数据集的熵的过程如下:即使用所有类标签的发生频率计算类别出现的概率.熵越高,混合的数据也就越多.

<span style="font-size:14px;">def calcShannonEnt(dataSet):numbers = len(dataSet)labelCount = {}for featVector in dataSet :featLabel = featVector[-1]if featLabel not in labelCount.keys():labelCount[featLabel] = 0labelCount[featLabel] += 1shannon = 0.0for key in labelCount:labelTimes = labelCount[key]labelPro = float(labelTimes)/numbersshannon -= labelPro*log(labelPro,2)return shannon</span>

根据信息增益选择当前最优的划分特征代码如下:

<span style="font-size:14px;">def chooseBestFeature(dataSet):numOfeatures = len(dataSet[0])-1baseEntropy = calcShannonEnt(dataSet)bestInfoGain = 0.0bestFeatureIndex = -1numOdata = len(dataSet)for i in range(numOfeatures):#get the ith column of dataSetfeatureList = [example[i] for example in dataSet]uniqueFeatureValue = set(featureList)newEntropy = 0.0for value in uniqueFeatureValue:newDataSet = splitDataSet(dataSet,i,value)prob = len(newDataSet)/float(numOdata)newEntropy += prob * calcShannonEnt(newDataSet)infoGain = baseEntropy - newEntropyif (infoGain > bestInfoGain):bestInfoGain = infoGainbestFeatureIndex = ireturn bestFeatureIndex</span>


(2)度量集合无需程度的方法是基尼不纯度,简单的说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率.

5.使用决策树进行分类

使用决策树分类:

      在执行数据分类时,需要决策树/用于构造决策树的特征向量.然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进入叶子节点,最后将测试数据定义为叶子节点所属的类型.

实现代码如下:

实现tip:引入构造决策树的特征向量,方便程序确定此特征在数据集中的存放位置.

<span style="font-size:14px;">def classify(inputTree,featLabels,testVec):firstStr = inputTree.keys()[0]secondDict = inputTree[firstStr]featureIndex = featLabels.index(firstStr)for key in secondDict.keys():if (key==testVec[featureIndex]):if type(secondDict[key]).__name__=='dict':classLabel = classify(secondDict[key],featLabels,testVec)else:classLabel = secondDict[key]return classLabel</span>

6.决策树的存储

构造决策树非常耗时,为了节省计算时间,最好能够在每次执行分类时,调用已经构造好的决策树.

为解决这个问题,引入python的pickle模块序列化对象:序列化对象可以在磁盘上保存对象,并在需要的时候读取,任何对象都可以执行序列化操作,字典对象也是.

实现代码如下:

<span style="font-size:14px;">def storeTree(inputTree,filename):import picklefw = open(filename,'w')pickle.dump(inputTree,fw)fw.close()def grabTree(filename):import picklefr = open(filename)return pickle.load(fr)</span>


实现多数表决的代码如下:

def majorityLabel(classList):classCount = {}for vote in classList:if vote not in classCount.keys():classCount[vote] = 0classCount[vote] += 1#descending the classCount according to the value of the label sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)return sortedClassCount[0][0]





0 0
原创粉丝点击