决策树

kNN
k近邻算法(有效并易于掌握)

优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。

适用数据范围:数值型和标称型。

​原理:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

流程
收集数据​-准备数据-分析数据-训练算法-测试算法-使用算法

​对未知类别属性的数据集中的每个点依次执行以下操作:
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的k个点;
(4)确定前k个点所在类别的出现频率;
(5)返回前k个点出现频率最高的类别作为当前点的预测分类。
ile()
重复某数组
argsort()
将元素从小到大排列,提取对应索引。
operator.itemgetter()
定义了一个函数,函数作用到对象上才能获取值,可用于排序,reverse参数接受False或True表示是否逆序
readlines()
以列表形式逐行读取文件
zeros()
创建一个全为0的矩阵
split()
通过指定分隔符对字符串进行切片
axis
最外面的括号代表着 axis=0,依次往里的括号对应的 axis 的计数就依次加 1(引用)

​决策树的一般流程
(1)收集数据:可以使用任何方法。
(2)准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
(3)分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
(4)训练算法:构造树的数据结构。
(5)测试算法:使用经验树计算错误率。
(6)使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
​划分数据集的大原则是:将无序的数据变得更加有序。
划分数据集之前之后发生的变化称为信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。
​集合信息的度量方式称为香农熵或者简称为熵。(熵定义为信息的期望值)
p(xi)是选择该分类的概率
import operator
from math import log

#计算给定数据的香农熵
def calcShannonEnt(dataSet):
numEntires=len(dataSet)
labelCounts={}
for featVec in dataSet:
currentLabel=featVec[-1]
if currentLabe not in labelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel]+=1
shannonEnt=0.0
for key in labelCounts:
prob=float(labelCounts[key])/numberEntries
shannonEnt-=prob*log(prob,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

#按照给定特征划分数据集
def splitDataSet(dataSet,axis,value):
retDataSet=[]
if featVec[axis]==value:
reducedFeatVec=featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet

#选择最好的数据划分方式
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-newEntorpy
if(infoGain>bestInfoGain):
bestInfoGain=infoGain
bestFeature=i
return bestFeature

‘’‘上面的代码与第2章classify0部分的投票表决代码非常
类似,该函数使用分类名称的列表,然后创建键值为classList中唯一值
的数据字典,字典对象存储了classList中每个类标签出现的频率,最后
利用operator操作键值排序字典,并返回出现次数最多的分类名称。’’’
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]
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:
subLabels = labels[:]
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
return myTree

#使用文本注解绘制树节点
import matplotlib.pyplot as plt

decisionNode = dict(boxstyle=“sawtooth”, fc=“0.8”)
leafNode = dict(boxstyle=“round4”, fc=“0.8”)
arrow_args = dict(arrowstyle="<-")

def plotNode(nodeTxt, centerPt, parentPt, nodeType):
createPlot.ax1.annotate(nodeTxt, xy=parentPt,xycoords=‘axes fraction’,xytext=centerPt, textcoords=‘axes fraction’,va=“center”, ha=“center”, bbox=nodeType, arrowprops=arrow_args)

def createPlot():
fig = plt.figure(1, facecolor=‘white’)
fig.clf()
reatePlot.ax1 = plt.subplot(111, frameon=False)
plotNode(U’决策节点’, (0.5, 0.1), (0.1, 0.5), decisionNode)
plotNode(U’叶节点’, (0.8, 0.1), (0.3, 0.8), leafNode)
plt.show()

#获取叶节点的数目和树的层数
def getNumLeafs(myTree):
numLeafs = 0
firstStr = myTree.keys()[0]
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).name==‘dict’:
numLeafs += getNumLeafs(secondDict[key])
else: numLeafs +=1
return numLeafs

def getTreeDepth(myTree):
maxDepth = 0
firstStr = myTree.keys()[0]
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).name==‘dict’:
thisDepth = 1 + getTreeDepth(secondDict[key])
else: thisDepth = 1
if thisDepth > maxDepth: maxDepth = thisDepth
return maxDepth

#用于预测,返回预定义的树结构
def retrieveTree(i):
listOfTrees =[{‘no surfacing’: {0: ‘no’, 1: {‘flippers’:{0: ‘no’, 1: ‘yes’}}}},{‘no surfacing’: {0: ‘no’, 1: {‘flippers’:{0: {‘head’: {0: ‘no’, 1: ‘yes’}}, 1: ‘no’}}}}]
return listOfTrees[i]

#plotTree函数
‘’‘函数createPlot()是我们使用的主函数,
它调用了plotTree(),函数plotTree又依次
调用了前面介绍的函数和plotMidText()。’’’
def plotMidText(cntrPt, parentPt, txtString):
xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]
yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]
createPlot.ax1.text(xMid, yMid, txtString, va=“center”, ha=“center”, rotation=30)

def plotTree(myTree, parentPt, nodeTxt):
numLeafs = getNumLeafs(myTree)
depth = getTreeDepth(myTree)
firstStr = myTree.keys()[0]
cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff),
plotMidText(cntrPt, parentPt, nodeTxt)
plotNode(firstStr, cntrPt, parentPt, decisionNode)
secondDict = myTree[firstStr]
plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD
for key in secondDict.keys():
if type(secondDict[key]).name==‘dict’:
plotTree(secondDict[key],cntrPt,str(key))
else:
plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW
plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff),cntrPt, leafNode)
plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD

def createPlot(inTree):
fig = plt.figure(1, facecolor=‘white’)
fig.clf()
axprops = dict(xticks=[], yticks=[])
createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)
plotTree.totalW = float(getNumLeafs(inTree))
plotTree.totalD = float(getTreeDepth(inTree))
plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;
plotTree(inTree, (0.5,1.0), ‘’)
plt.show()

#使用决策树的分类函数
def classify(inputTree,featLabels,testVec):
firstStr = 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’:
classLabel = classify(secondDict[key],featLabels,testVec)
else: classLabel = secondDict[key]
return classLabel

#使用pickle模块存储决策树
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)

在这里插入代码片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值