【机器学习】决策树
来源:互联网 发布:html5media.js 编辑:程序博客网 时间:2024/06/05 03:00
第5章 决策树
《统计学习方法》李航 第五章 决策树
《机器学习实战》 第3章 决策树
决策树:
1.树形结构(内部节点表示一个特征或属性,叶节点表示一个类)
2.if-then规则的集合(决策树上所有根节点到叶节点路径的集合)互斥且完备
3.定义在特征空间与类空间上的条件概率分布。(将特征空间划分为互不相交的单元,并在每个单元定义一个类的概率分布,将节点实例归为条件概率最大的一类)
优点:模型具有可读性、分类速度快、可同时处理类别和数值(离散化处理)数据
决策树学习
· 本质:从训练集中归纳出一组分类规则,使它与训练数据矛盾较小,且具有良好的泛化能力。(训练集估计条件概率模型)
· 策略:损失函数最小化(损失函数通常为:正则化的极大似然函数)
· 算法:递归地选择最优特征,并根据该特征对训练数据集进行分割,使得对各个子数据集有一个最好的分类过程
<启发式算法>
(1)特征选择
(2)决策树的生成 <模型的局部选择,只考虑局部最优>
(3)决策树的剪枝 <模型的全局选择,全局最优>
特征选择
根据特征的分类能力选择最优特征
准则:信息增益(ID3)、信息增益率(C4.5)熵
随机变量不确定性的度量
设X是一个取有限个值的离散随机变量,其概率分布为P(X=xi)=pi,i=1,2,...,n
则随机变量X的熵定义为H(p)=H(X)=−∑i=1npilogpi
· 对同一个随机变量,当其概率分布为均匀分布时,不确定性最大,熵最大
· 对有相同概率分布的不同随机变量,取值最多的随机变量,熵最大
经验熵:熵中的概率由数据估计(特别是极大似然估计)得到
信息增益:得知特征X的信息而使得类Y的信息不确定性减少的程度
偏向于选择取值较多的特征 (->可添加罚项)
信息增益的算法:
(1)数据集D的经验熵H(D)
(2)计算特征A对数据集D的经验条件熵H(D|A)
(3)计算信息增益
ID3 相当于用极大似然法进行概率模型的估计
Python 代码
from math import logimport operator#计算信息熵def calcShannonEnt(dataSet): #获取数据集的行数 numEntries=len(dataSet) #设置字典的数据结构 labelCounts={} #提取数据集每一行的特征向量 for featVec in dataSet: #获取特征向量最后一列的标签 currentLabel=featVec[-1] #-1表示输出数组的最后一个元素 #若标签不在字典的关键字中 if currentLabel not in labelCounts.keys(): #将该标签-0键值存入字典 labelCounts[currentLabel]=0 #若存在,则键值+1 labelCounts[currentLabel]+=1 #初始化香农熵为0 shannonEnt=0.0 for key in labelCounts: #计算各个类别出现的概率 prob=float(labelCounts[key])/numEntries #计算各个类别信息的期望值 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#按照给定特征划分数据集#axis:划分数据集的特征#value:特征的取值def splitDataSet(dataSet,axis,value): #python语言传递参数列表时,传递的是列表的引用 #为了不修改原始数据集,创建一个新的列表对象进行操作 retDataSet=[] #提取数据集每行的特征向量 for featVec in dataSet: #针对axis特征不同的取值,将数据集划分为不同的分支 if featVec[axis]==value: #将原始数据集去掉当前划分数据的特征列 reducedFeatVec=featVec[:axis] reducedFeatVec.extend(featVec[axis+1:]) #注意extend和append的区别 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): #得到特征i的特征值列表 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 #获得是的信息增益最大的特征 if(infoGain>bestInfoGain): bestInfoGain=infoGain bestFeature=i return bestFeature#遍历完所有的特征属性,类标签仍然不唯一(分支下仍有不通分类的实例)#采用多数表决的方法完成分类def majorityCnt(classList): classCount={} for vote in classList: if vote not in classCount.keys(): classCount[vote]=0 classCount[vote]+=1 #对字典中的键对应的值所在的列进行从大到小的排序 #classCount.iteritems()列表对象 #key=operator.itemgetter(1)获取列表对象的第一个域的值 #reverse=True 降序 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:{}} #复制当前特征标签列表,防止改变原始列表的内容 subLabels=labels[:] #删除属性列表中当前分类数据集特征 del(subLabels[bestFeat]) featValues=[example[bestFeat]for example in dataSet] uniqueValues=set(featValues) for value in uniqueValues: myTree[bestFeatLabel][value]=createTree(splitDataSet\ (dataSet,bestFeat,value),subLabels) return myTree#使用决策树的分类函数def classify(inputTree,featLabels,testVec): #获得第一个用于划分数据集的特征属性 # firstStr=inputTree.keys()[0] #python2 firstSides=list(inputTree.keys()) firstStr=firstSides[0] #获得第一个节点的子节点 secondDict=inputTree[firstStr] #找到第一个特征属性在特征列表的中位置 featIndex=featLabels.index(firstStr) for key in secondDict.keys(): if testVec[featIndex]==key: #判断secondDict[key]是否为字典(判断当前节点是否是叶子节点) if type(secondDict[key]).__name__=='dict': classLabel=classify(secondDict[key],featLabels,testVec) else: classLabel=secondDict[key] return classLabel# 决策树的序列化 def storeTree(inputTree,filename): # 导入pyton模块 import pickle # 以写的方式打开文件 fw = open(filename,'w') # 决策树序列化 pickle.dump(inputTree,fw) # 读取序列化的树 def grabTree(filename): import pickle fr = open(filename) # 返回读到的树 return pickle.load(fr) if __name__=='__main__': myData,labels=createDataSet() '''myData=[['sunny','hot','high','false','no'], ['sunny','hot','high','true','no'], ['overcast','hot','high','false','yes'], ['rainy','mild','high','false','yes'], ['rainy','cool','normal','false','yes'], ['rainy','cool','normal','true','no'], ['overcast','cool','normal','true','yes'], ['sunny','mild','high','false','no'], ['sunny','cool','normal','false','yes'], ['rainy','mild','normal','false','yes'], ['sunny','mild','normal','true','yes'], ['overcast','mild','high','true','yes'], ['overcast','hot','normal','false','yes'], ['rainy','mild','high','true','no']] labels=['outlook','temperature','humidity','windy']''' print(labels) myTree=createTree(myData,labels) print(myTree) print(classify(myTree,labels,[1,0]))
- 机器学习算法---决策树
- 机器学习2决策树
- 机器学习-决策树
- 机器学习---决策树
- 机器学习实战---决策树
- 机器学习之决策树
- 机器学习-决策树
- 机器学习实战-决策树
- 面试:机器学习--决策树
- 机器学习实战---决策树
- 机器学习实战 决策树
- 【机器学习】决策树
- 机器学习 之 决策树
- [机器学习实战]-决策树
- 机器学习--决策树
- 机器学习-决策树
- 机器学习之决策树
- 机器学习 - 决策树
- angular之表单验证ngMessages
- HTML页面3秒后自动跳转的三种常见方法
- C++构造函数执行顺序
- 4-4 特征选择和模型建立
- 细说Angular ng-class
- 【机器学习】决策树
- MySQL C语言接口-预处理语句
- centos7 编译php7
- SQL数据库日期查询格式
- 带阴影的TextView
- 经典SQL语句大全
- 用list集合实现栈
- pythonhan新手驾到
- vueJs的学习笔记(四)