python机器学习理论与实战(二)决策树


Posted in Python onJanuary 19, 2018

        决策树也是有监督机器学习方法。 电影《无耻混蛋》里有一幕游戏,在德军小酒馆里有几个人在玩20问题游戏,游戏规则是一个设迷者在纸牌中抽出一个目标(可以是人,也可以是物),而猜谜者可以提问题,设迷者只能回答是或者不是,在几个问题(最多二十个问题)之后,猜谜者通过逐步缩小范围就准确的找到了答案。这就类似于决策树的工作原理。(图一)是一个判断邮件类别的工作方式,可以看出判别方法很简单,基本都是阈值判断,关键是如何构建决策树,也就是如何训练一个决策树。

python机器学习理论与实战(二)决策树

(图一)

构建决策树的伪代码如下:

Check if every item in the dataset is in the same class:
    If so return the class label
    Else 
      find the best feature to split the data
       split the dataset 
       create a branch node
       for each split
          call create Branch and add the result to the branch node

      return branch node

         原则只有一个,尽量使得每个节点的样本标签尽可能少,注意上面伪代码中一句说:find the best feature to split the data,那么如何find thebest feature?一般有个准则就是尽量使得分支之后节点的类别纯一些,也就是分的准确一些。如(图二)中所示,从海洋中捞取的5个动物,我们要判断他们是否是鱼,先用哪个特征?

python机器学习理论与实战(二)决策树

(图二)

         为了提高识别精度,我们是先用“离开陆地能否存活”还是“是否有蹼”来判断?我们必须要有一个衡量准则,常用的有信息论、基尼纯度等,这里使用前者。我们的目标就是选择使得分割后数据集的标签信息增益最大的那个特征,信息增益就是原始数据集标签基熵减去分割后的数据集标签熵,换句话说,信息增益大就是熵变小,使得数据集更有序。熵的计算如(公式一)所示:

python机器学习理论与实战(二)决策树

有了指导原则,那就进入代码实战阶段,先来看看熵的计算代码:

def calcShannonEnt(dataSet): 
  numEntries = len(dataSet) 
  labelCounts = {} 
  for featVec in dataSet: #the the number of unique elements and their occurance 
    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) #log base 2 计算熵 
  return shannonEnt

有了熵的计算代码,接下来看依照信息增益变大的原则选择特征的代码:

def splitDataSet(dataSet, axis, value): 
  retDataSet = [] 
  for featVec in dataSet: 
    if featVec[axis] == value: 
      reducedFeatVec = featVec[:axis]   #chop out axis used for splitting 
      reducedFeatVec.extend(featVec[axis+1:]) 
      retDataSet.append(reducedFeatVec) 
  return retDataSet 
   
def chooseBestFeatureToSplit(dataSet): 
  numFeatures = len(dataSet[0]) - 1   #the last column is used for the labels 
  baseEntropy = calcShannonEnt(dataSet) 
  bestInfoGain = 0.0; bestFeature = -1 
  for i in range(numFeatures):    #iterate over all the features 
    featList = [example[i] for example in dataSet]#create a list of all the examples of this feature 
    uniqueVals = set(featList)    #get a set of unique values 
    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   #calculate the info gain; ie reduction in entropy 
    if (infoGain > bestInfoGain):    #compare this to the best gain so far  #选择信息增益最大的代码在此 
      bestInfoGain = infoGain     #if better than current best, set to best 
      bestFeature = i 
  return bestFeature           #returns an integer

        从最后一个if可以看出,选择使得信息增益最大的特征作为分割特征,现在有了特征分割准则,继续进入一下个环节,如何构建决策树,其实就是依照最上面的伪代码写下去,采用递归的思想依次分割下去,直到执行完成就构建了决策树。代码如下:

def majorityCnt(classList): 
  classCount={} 
  for vote in classList: 
    if vote not in classCount.keys(): classCount[vote] = 0 
    classCount[vote] += 1 
  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]#stop splitting when all of the classes are equal 
  if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet 
    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: 
    subLabels = labels[:]    #copy all of labels, so trees don't mess up existing labels 
    myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels) 
  return myTree

用图二的样本构建的决策树如(图三)所示:

python机器学习理论与实战(二)决策树

(图三)

有了决策树,就可以用它做分类咯,分类代码如下:

def classify(inputTree,featLabels,testVec): 
  firstStr = inputTree.keys()[0] 
  secondDict = inputTree[firstStr] 
  featIndex = featLabels.index(firstStr) 
  key = testVec[featIndex] 
  valueOfFeat = secondDict[key] 
  if isinstance(valueOfFeat, dict):  
    classLabel = classify(valueOfFeat, featLabels, testVec) 
  else: classLabel = valueOfFeat 
  return classLabel

最后给出序列化决策树(把决策树模型保存在硬盘上)的代码:

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)

优点:检测速度快

缺点:容易过拟合,可以采用修剪的方式来尽量避免

参考文献:machine learning in action

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
简单的通用表达式求10乘阶示例
Mar 03 Python
Python简单定义与使用字典dict的方法示例
Jul 25 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
Nov 11 Python
Python实现的归并排序算法示例
Nov 21 Python
python设置环境变量的原因和方法
Jun 24 Python
tensorflow 实现从checkpoint中获取graph信息
Feb 10 Python
python GUI库图形界面开发之PyQt5窗口布局控件QStackedWidget详细使用方法
Feb 27 Python
浅析python标准库中的glob
Mar 13 Python
Python drop方法删除列之inplace参数实例
Jun 27 Python
python+opencv实现视频抽帧示例代码
Jun 11 Python
Python并发编程实例教程之线程的玩法
Jun 20 Python
Python基础 括号()[]{}的详解
Nov 07 Python
Python三种遍历文件目录的方法实例代码
Jan 19 #Python
python机器学习理论与实战(一)K近邻法
Jan 28 #Python
python机器学习理论与实战(六)支持向量机
Jan 19 #Python
Python logging管理不同级别log打印和存储实例
Jan 19 #Python
python机器学习理论与实战(五)支持向量机
Jan 19 #Python
Python读取图片为16进制表示简单代码
Jan 19 #Python
Python实现pdf文档转txt的方法示例
Jan 19 #Python
You might like
PHP写的求多项式导数的函数代码
2012/07/04 PHP
浅析使用Turck-mmcache编译来加速、优化PHP代码
2013/06/20 PHP
php类的定义与继承用法实例
2015/07/07 PHP
Zend Framework动作助手(Zend_Controller_Action_Helper)用法详解
2016/03/05 PHP
如何使用php等比例缩放图片
2016/10/12 PHP
php创建图像具体步骤
2017/03/13 PHP
PHP数组中头部和尾部添加元素的方法(array_unshift,array_push)
2017/04/10 PHP
PHP基于堆栈实现的高级计算器功能示例
2017/09/15 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
PHP设计模式之外观模式(Facade)入门与应用详解
2019/12/13 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
2020/03/27 PHP
Google AJAX 搜索 API实现代码
2010/11/17 Javascript
15条JavaScript最佳实践小结
2013/08/09 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
2014/02/17 Javascript
Javascript中的Array数组对象详谈
2014/03/03 Javascript
jQuery使用before()和after()在元素前后添加内容的方法
2015/03/26 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
CSS javascript 结合实现悬浮固定菜单效果
2015/08/23 Javascript
javascript学习小结之prototype
2015/12/03 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单
2016/11/25 Javascript
jQuery Mobile漏洞会有跨站脚本攻击风险
2017/02/12 Javascript
vue 组件内获取actions的response方式
2019/11/08 Javascript
JS实现的定时器展示简单秒表、页面弹框及跳转操作完整示例
2020/01/26 Javascript
[43:03]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
python文件和目录操作函数小结
2014/07/11 Python
Python中用于返回绝对值的abs()方法
2015/05/14 Python
python 获取当天每个准点时间戳的实例
2018/05/22 Python
TensorFlow梯度求解tf.gradients实例
2020/02/04 Python
基于python实现破解滑动验证码过程解析
2020/05/28 Python
CSS3毛玻璃效果(blur)有白边问题的解决方法
2016/11/15 HTML / CSS
打印机墨盒:123Inkjets
2017/02/16 全球购物
计算机专业毕业生的自我评价
2013/11/18 职场文书
大学新生军训方案
2014/05/03 职场文书
2015年度党员自我评价范文
2015/03/03 职场文书
Mysql外键约束的创建与删除的使用
2022/03/03 MySQL
OpenCV实现常见的四种图像几何变换
2022/04/01 Python