【机器学习实战学习笔记(2-2)】决策树python3.6实现及简单应用
文章目录
通过决策树原理及相关概念细节我们知道,决策树的学习算法主要包括3个步骤:特征选择、决策树生成算法、决策树剪枝,我们按照这个思路来一一实现相关功能。
本文的实现目前主要涉及特征选择、ID3及C4.5算法。剪枝及CART算法暂未涉及,后期补上。
1.ID3及C4.5算法基础
前面文章我们提到过,ID3与C4.5的主要区别是特征选择准则的不同:
- ID3:信息增益
- C4.5:信息增益比
1.1 计算香农熵
不管是这两者的哪一种,都涉及到信息增益的计算,而计算信息增益的基础又是计算香农熵。所以我们先来实现计算香农熵的代码。
from math import log
import operator
# 计算给定数据集的香农熵
def 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) # 以2为底求对数
return shannonEnt
然后创建书中的数据集,并计算该数据集的香农熵:
# 创建自己的数据集
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
return dataSet, labels
myDat,labels=createDataSet()
myDat # [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
calcShannonEnt(myDat) # 0.9709505944546686
1.2 按照给定特征划分数据集
# 按照给定特征划分数据集
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
测试:
splitDataSet(myDat,0,1) # [[1, 'yes'], [1, 'yes'], [0, 'no']]
1.3 选择最优特征
# 选择最好的数据集划分方式
# 选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0; bestFeature = -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 # ID3
# infoGain = baseEntropy - newEntropy # C4.5
# 计算最好的信息增益
if (infoGain > bestInfoGain):
bestInfoGain = infoGain
bestFeature = i
return bestFeature
1.4 多数表决实现
在ID3、C4.5算法的停止条件之一是:没有特征可以选择时停止算法,但如果这时该结点类标签依然不是唯一的,此时我们需要决定如何定义该叶子结点。在这种情况下,通常采用多数表决的方法决定该叶子结点的分类。
# 多数表决实现
def majorityCnt(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys():
classCount[vote] = 0
classCount[vote] += 1
# 对字典进行排序
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
# Python3中不再支持iteritems(),将iteritems()改成items()
return sortedClassCount[0][0]
对于“多数表决实现”函数的注释:
- 1.dict.items()
作用:是可以将字典中的所有项,以列表方式返回。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。 - 2.operator.itemgetter()
operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号. - 3.sorted()函数,排序
list.sort()是对已经存在的列表进行操作,进而可以改变进行操作的列表;
sorted返回的是一个新的list,而不是在原来的基础上进行的操作
2.基于ID3、C4.5生成算法创建决策树
这里主要介绍基于ID3生成算法创建决策树,C4.5只需要在ID3生成决策树代码上将chooseBestFeatureToSplit(dataSet)函数中infoGain = baseEntropy - newEntropy换成infoGain = baseEntropy - newEntropy即可 。
# 创建树的函数代码
def creatTree(dataSet,labels):
classList = [example[-1] for example in dataSet]
labels2 = labels[:]
# 类别完全相同则停止继续划分
if classList.count(classList[0]) == len(classList):
return classList[0]
# 遍历完所有特征时返回出现次数最多的类别
if len(dataSet[0]) == 1:
return majorityCnt(classList)
bestFeat = chooseBestFeatureToSplit(dataSet)
bestFeatLabel = labels2[bestFeat]
myTree = {bestFeatLabel:{}}
del (labels2[bestFeat])
# 得到列表包含的(选定为最佳特征的)所有属性值
featValues = [example[bestFeat] for example in dataSet]
uniqueVals = set(featValues)
for value in uniqueVals:
subLabels = labels2[:] # 复制类标签
# 递归
myTree[bestFeatLabel][value] = creatTree(splitDataSet(dataSet, bestFeat, value),subLabels)
return myTree
对于“creatTree”函数的注释:
1.list.count(obj)
统计某个元素在列表中出现的次数2.del,list.remove(),list.pop()
del:根据索引位置来删除单个值或指定范围内的值;
list.remove():删除单个元素,删除首个符合条件的元素,按值删除,返回值为空;
list.pop():删除索引位置元素,无参情况下删除最后一个元素,返回删除的元素值;
测试:
myTree = creatTree(myDat, labels)
myTree # {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
3.使用决策树进行分类
# 使用决策树的分类函数
def classify(inputTree, featLabels, testVec):
firstStr = list(inputTree.keys())[0]
secondDict = inputTree[firstStr]
featIndex = featLabels.index(firstStr)
for key in secondDict.keys():
if testVec[featIndex] == key:
if type(secondDict[key]).__name__=='dict':
#if isinstance(secondDict[key], dict): 这个也可以
classLabel = classify(secondDict[key],featLabels,testVec)
else:
classLabel = secondDict[key]
return classLabel
对于“classify”的注释:
1.type(a).name == ‘dict’:
可判断a的类型是否类型为dict,list tuple 这些也适用2.也可以用isinstance(变量名,类型)判断类型:
判断该变量是否是该类型,或者是否是该类和该类的父类类型;小注:
type(变量名):获取该变量名的类型,结合==判断该变量的类型是否等于目标类型(等号右边value值) 比如:a类继承b类,实例c=a()
isinstance(c,a)和isinstance(c,b)都是True
type(c)的value值是a,a是不等于b的,所以a==b为False即:type(c)==b为False
3.==和is
==:变量名的value值是否相等
is:变量名的id(地址)是否相等(数字类型的value值相等则id相等)
测试:
classify(myTree, labels, [1,0]) # 'no'
classify(myTree, labels, [1,1]) # 'yes'
4.存储决策树
import pickle
# 使用pickle模块存储决策树
def storeTree(inputTree, filename):
with open(filename, 'wb') as f:
pickle.dump(inputTree, f)
# 加载决策树
def grabTree(filename):
with open(filename, 'rb') as f:
return pickle.load(f)
测试:
storeTree(myTree,'classifierStorage.txt')
grabTree('classifierStorage.txt') # {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
参考资料:
《机器学习实战》第三章
【机器学习实战学习笔记(2-2)】决策树python3.6实现及简单应用的更多相关文章
- 【机器学习实战学习笔记(1-1)】k-近邻算法原理及python实现
笔者本人是个初入机器学习的小白,主要是想把学习过程中的大概知识和自己的一些经验写下来跟大家分享,也可以加强自己的记忆,有不足的地方还望小伙伴们批评指正,点赞评论走起来~ 文章目录 1.k-近邻算法概述 ...
- 【机器学习实战学习笔记(1-2)】k-近邻算法应用实例python代码
文章目录 1.改进约会网站匹配效果 1.1 准备数据:从文本文件中解析数据 1.2 分析数据:使用Matplotlib创建散点图 1.3 准备数据:归一化特征 1.4 测试算法:作为完整程序验证分类器 ...
- 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...
- 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...
- 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...
- 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...
- python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样
python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样,IDLE shell编辑器,快捷键:ALT+p,上一个历史输入内容,ALT+n 下一个历史输入 ...
- TensorFlow机器学习框架-学习笔记-001
# TensorFlow机器学习框架-学习笔记-001 ### 测试TensorFlow环境是否安装完成-----------------------------```import tensorflo ...
- Redis in Action : Redis 实战学习笔记
1 1 1 Redis in Action : Redis 实战学习笔记 1 http://redis.io/ https://github.com/antirez/redis https://ww ...
随机推荐
- 使用forin循环时的注意事项
由于遍历的对象为nil,从而导致的现象是里面的循环体根本就没有执行,并且编译器和运行期都不会报错.因为,OC语法是运行向nil发送消息的. for (WSFActivitySelectSpaceCel ...
- change事件和input事件的区别
input事件: input事件在输入框输入的时候回实时响应并触发 change事件: change事件在input失去焦点才会考虑触发,它的缺点是无法实时响应.与blur事件有着相似的功能,但与bl ...
- 【转载】如何快速转载CSDN中的博客
前言 对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间 ...
- 彻底搞懂 JS 中 this 机制
彻底搞懂 JS 中 this 机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 目录 this 是什么 this 的四种绑定规 ...
- 二、Navicat、IDEA、nopad、eclipse、excle工具使用、问题、快捷键
1.Navicat工具: 目的:本地数据库与远程数据库之间数据导入导出 步骤1:文件--新建oracle链接/mysql的连接 步骤2:工具-选项:将本地oracle的bin\oci.dll 的路径复 ...
- mysql数据库的索引类型
MySQL索引类型: 1.普通索引 最基本的索引,它没有任何限制,用于加速查询. 创建方法: a. 建表的时候一起创建 CREATE TABLE mytable ( name VARCHAR(32 ...
- lunix下的redis安装
https://blog.csdn.net/qq_35992900/article/details/82950157
- luogu P3357 最长k可重线段集问题
这题和3358一模一样,建模形式直接不用变,就两点不一样,一是len变化了,加入y后再更新即可,还有就是可能会出现x0=x1的情况,即一条开线段垂直x轴,如果我们依旧按照上一题的建图方法,就会出现负权 ...
- GET乱码以及POST乱码的解决方法
GET乱码以及POST乱码的解决方法 作者:东坡下载 来源:uzzf 发布时间:2010-10-14 11:40:01 点击: 一.GET乱码的解决方法 在tomcat的server.xml文件 ...
- MVC5仓库管理系统
下载