机器学习实战之决策树最有特征的选取

在学习了jack cui机器学习博客后,为了给自己留下一个理解的笔记,本人比较笨,以后方便查看。他的博客地址在下方,写得很好。

点击打开链接

决策树机器学习的一种分类方法,机器学习实战之决策树最有特征的选取机器学习实战之决策树最有特征的选取

拿相亲来说,决策树模型就是上面这一个,长方形为这个人的某个特征,决策树有内部节点和叶节点。内部节点就是这个长方形,是其特征。叶节点是椭圆,就是其得到的结果,是备胎还是值得考虑。而特征也是一个分类的规则条件。是将它继续划分到哪一边。每一个特征都会影响这个决策树分类的结果。

决策树的构建这一过程要分为3个步骤:

特征选择,决策树的生成和决策树的修剪。

使用决策树做预测需要一下过程:收集数据-->准备数据-->分析数据-->训练算法-->测试算法-->使用算法

1.特征选择:

特征选择就是选取具有分类能力的特征,如果某个特征对本次分类不会产生影响或则说产生的影响很低,那么我们就可以选择抛弃这个特征。这个特征就是没有分类能力的,无用特征。而在选取特征上,有一个方法就是计算某个特征的信息增益,然后看其信息增益的大小,越大的说明它对本次分类结果影响越大,反之亦然。

这里有一个实例,就是贷款申请的样本数据:

机器学习实战之决策树最有特征的选取

这次我们通过说给的数据学习一个贷款申请的决策树,用于对未来某个客户提出申请贷款时,我们可以根据这个人的一些特征数据考虑是否给这个人贷款。

那么我们要构建一个决策树模型,就应该选择分类能力大的特征,现在看上面那个表单,不会看到什么不同。这是就需要我们计算信息增益了,在计算信息增益之前,我们需要计算一个香农熵。

(1)香农熵(经验
机器学习实战之决策树最有特征的选取
根据此公式计算经验熵H(D),分析贷款申请样本数据表中的数据。最终分类结果只有两类,即放贷和不放贷。根据表中的数据统计可知,在15个数据中,9个数据的结果为放贷,6个数据的结果为不放贷。所以数据集D的经验熵H(D)为

机器学习实战之决策树最有特征的选取

所以H(D)经验熵为0.971

那么现在需要的一个就是条件熵,也就是某个特征的信息增益:

机器学习实战之决策树最有特征的选取

在上面我给的那个博客地址上已经讲得很好了,很容易理解

以贷款申请样本数据表为例进行说明。看下年龄这一列的数据,也就是特征A1,一共有三个类别,分别是:青年、中年和老年。我们只看年龄是青年的数据,年龄是青年的数据一共有5个,所以年龄是青年的数据在训练数据集出现的概率是十五分之五,也就是三分之一。同理,年龄是中年和老年的数据在训练数据集出现的概率也都是三分之一。现在我们只看年龄是青年的数据的最终得到贷款的概率为五分之二,因为在五个数据中,只有两个数据显示拿到了最终的贷款,同理,年龄是中年和老年的数据最终得到贷款的概率分别为五分之三、五分之四。所以计算年龄的信息增益,过程如下:

机器学习实战之决策树最有特征的选取

机器学习实战之决策树最有特征的选取


好了,现在就来解读整个代码,这也是我这个小白写笔记的原因,方便以后复习


在编写代码之前,我们先对数据集进行属性标注。

  • 年龄:0代表青年,1代表中年,2代表老年;
  • 有工作:0代表否,1代表是;
  • 有自己的房子:0代表否,1代表是;
  • 信贷情况:0代表一般,1代表好,2代表非常好;
  • 类别(是否给贷款):no代表否,yes代表是。
[python] view plain copy
  1. from math import log  
  2.   
  3. ''''' 
  4. 函数说明: 
  5. 创建测试数据集 
  6. Parameters(参数): 
  7.  
  8. returns: 
  9. dataSet:数据集 
  10. labels 分类属性 
  11. '''  
  12. def createDataSet():  
  13.      dataSet = [[0000'no'],                        #数据集  
  14.             [0001'no'],  
  15.             [0101'yes'],  
  16.             [0110'yes'],  
  17.             [0000'no'],  
  18.             [1000'no'],  
  19.             [1001'no'],  
  20.             [1111'yes'],  
  21.             [1012'yes'],  
  22.             [1012'yes'],  
  23.             [2012'yes'],  
  24.             [2011'yes'],  
  25.             [2101'yes'],  
  26.             [2102'yes'],  
  27.             [2000'no']]  
  28.      labels=['不放贷','放贷']  
  29.      return dataSet,labels  
  30. ''''' 
  31. 函数说明: 
  32. 计算给定数据集的经验熵(香农熵) 
  33. Parameters: 
  34. dataSet 
  35. Returns: 
  36. shannonEnt-经验熵(香农熵) 
  37. '''  
  38. def calcShannonEnt(dataSet):  
  39.     #这个函数对计算经验熵和条件熵都是相同的,因为公式其实并无区别。只是条件熵加上了一个条件,数据集变小了而已  
  40.     numEntires=len(dataSet)  
  41.     #计算这个数据集有多少行  
  42.     labelCounts={}  
  43.       
  44. #定义一个空字典  
  45.     for featVec in dataSet:  
  46.         #循环遍历数据集中的每行数据  
  47.         currentLabel=featVec[-1]  
  48.         #得到每行数据中的最后一个标签  
  49.         if currentLabel not in labelCounts.keys():  
  50.             #判断这个标签是否在这个字典里面  
  51.             labelCounts[currentLabel]=0  
  52.             #如果没有先初始化这个标签名(label)  
  53.         labelCounts[currentLabel]+=1  
  54.         #记录标签名出现的次数,记录字典里的键值  
  55.     shannonEnt=0.0  
  56.     #定义一个浮点数,是用来保存香农熵的  
  57.     for key in labelCounts:  
  58.         #循环遍历字典里的键名  
  59.         prob=float(labelCounts[key])/numEntires  
  60.         #得到yes或no 这个标签的概率  
  61.         shannonEnt -=prob * log(prob,2)  
  62.         #公式计算香农熵  
  63.     return shannonEnt  
  64. """ 
  65. 函数说明:按照给定特征划分数据集 
  66.   
  67. Parameters: 
  68.     dataSet - 待划分的数据集 
  69.     axis - 划分数据集的特征 
  70.     value - 需要返回的特征的值 
  71. Returns: 
  72.     无 
  73. Author: 
  74.     Jack Cui 
  75. Modify: 
  76.     2017-03-30 
  77. """  
  78. def splitDataSet(dataSet, axis, value):         
  79.     retDataSet = []  #定义一个列表来保存我们需要的子集                                        
  80.     for featVec in dataSet: #遍历每行                              
  81.         if featVec[axis] == value:#如果这一行的这一列(axis)有一个元素是我们要找的,比如在第一列有我们要找的青年,就把这一行数据保存下来  
  82.             ''''' 
  83.             reducedFeatVec = featVec[:axis]                
  84.             reducedFeatVec.extend(featVec[axis+1:])     
  85.             retDataSet.append(reducedFeatVec) 
  86.             '''  
  87.             retDataSet.append(featVec)#我觉得博主写的这个好像有点多余,因为我们将数据带入calShannonEnt()函数中就是看它后面的标签是否放贷,所以将某一行的这个元素去掉,没必要  
  88.     return retDataSet                                        
  89.    
  90. ''''' 
  91. 函数说明:计算每个特征的信息增益,然后选择最优特征 
  92. Parameters: 
  93. dataSet-数据集 
  94. Returns: 
  95. bestFeature-信息增益最大的特征的索引值 
  96. '''  
  97. def chooseBestFeatureToSplit(dataSet):  
  98.     numFeatures=len(dataSet[0])-1#得到特征数  
  99.     baseEntropy=calcShannonEnt(dataSet)#得到总数据的香农熵  
  100.     bestInfoGain=0.0#定义一个浮点数,来接受经验熵的值  
  101.     bestFeature=-1#定义一个数接受最优特征是第几列  
  102.     for i in range(numFeatures):  
  103.         #循环遍历4个特征  
  104.         featList = [example[i] for example in dataSet]#将每列的特征的数据存入这个列表,这个列表就保存每列特征的数据,下一列的数据会覆盖掉上一列数据  
  105.         uniqueVals = set(featList)#创建set集合{},保存的元素不可重复                       
  106.         newEntropy = 0.0                                   
  107.         for value in uniqueVals:  
  108.             #遍历集合中的每个元素,计算信息增益,例如:年龄中的青年,中年,老年。因为字典中的每个不同元素就代表了青年,中年,老年  
  109.             subDataSet = splitDataSet(dataSet, i, value)#划分包含了value的某些子集,就是某些包含了value的行,将它变成一个数据集,然后计算他的信息增益(条件熵),然后我们转到这个函数           
  110.             prob = len(subDataSet) / float(len(dataSet))#下面的就是计算步骤了,没什么区别           
  111.             newEntropy += prob * calcShannonEnt(subDataSet) #这是累加,我们计算的是这一列的条件熵,例如为年龄的条件熵,所以就将青年,中年,老年的加起来   
  112.         infoGain = baseEntropy - newEntropy #这就是真正的信息增益了,经验熵减去条件熵               
  113.         print("第%d个特征的增益为%.3f" % (i, infoGain))#输出每列特征的增益  
  114.         if (infoGain > bestInfoGain): #比较每个增益,输出最大增益                             
  115.             bestInfoGain = infoGain                               
  116.             bestFeature = i#保留它是第几列,后面方便输出  
  117.     return bestFeature       
  118.       
  119.       
  120.   
  121. if __name__=="__main__":  
  122.     dataSet, features = createDataSet()  
  123.     print("最优特征索引值:" + str(chooseBestFeatureToSplit(dataSet)))  



机器学习实战之决策树最有特征的选取