机器学习实战之决策树

1.决策树与k近邻算法对比

  • k近邻算法最大的缺点就是无法给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解.
  • 决策树由结点和有向边组成,结点包含2种类型:内部结点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类.
  • 决策树分类时,从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子结点;这时,每个子结点都对应该特征的一个取值,如此递归地对实例进行测试并分配,直到达到叶结点,最后将实例分到叶节点的类中.

2.决策树的优缺点

  • 优点
              计算复杂度不高,输出结果易理解,比较适合处理有缺失属性值的样本,可以处理不相关特征数据.
  • 缺点
              可能产生过度匹配问题,为了减少过度匹配,可以裁剪决策树,去掉一些不必要的叶子节点.若叶子节点只能增加少量信息,可以删除该节点,将其并入其它叶子节点中.

3.决策树的产生过程

(1)关键思想:

本次采用ID3算法;在决策树哥哥节点上应用信息增益准则选择特征,递归的构建决策树;

具体方法:

  • 从根节点开始,对节点计算所有可能的特征的信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值创建子节点;由特征的不同取值可以将原数据集划分为几个不同的数据集,分别计算信息增益;
  • 对子结点递归的调用上述步骤,构建决策树;
  • 直到所有数据属于同一个分类或没有特征可以选择为止,得到最终的决策树.

(2)算法结束条件:

        若当前数据集的所有实例都属于同一类k,则此时的决策树T为单节点,将类k作为该节点的类标记,并返回T;

       若当前数据集的特征集为空,则将数据集中出现次数最多的类k作为该节点的类标记,返回该节点;

(3)创建决策树的流程:

检测数据集中的每个子项是否属于同一个分类:

        if so return 类标签;

        else

              寻找划分数据集的决定性特征

              划分数据集

              创建分支节点

                        for 每个划分的子集

                                调用此函数并增加返回结果到分支节点中

               return 分支节点


实现python代码如下:

输入为训练数据集和训练数据集对应的特征集;

<span style="font-size:14px;">def createTrees(dataSet,label):
	classList = [example[-1] for example in dataSet]
	#the label is totally same, end the iter
	if classList.count(classList[0]) == len(dataSet): #数据集都属于同一个分类
		return classList[0]
	#only one feature, take th majority features
  	if len(dataSet[0]) == 1: #特征集为空,选择数据集中出现次数最多的类返回
		return majorityLabel(classList)

	bestFeatureIndex = chooseBestFeature(dataSet)
	bestFeature = label[bestFeatureIndex]

	myTree = {bestFeature:{}}
	del(label[bestFeatureIndex])
	
	featureValue = [example[bestFeatureIndex] for example in dataSet]
	uniqueFeatureValue = set(featureValue)
	for value in uniqueFeatureValue:
		subLabel = label[:]
		myTree[bestFeature][value] = createTrees(splitDataSet(dataSet,bestFeatureIndex,value),subLabel)
	return myTree</span>


4.如何寻找决定性特征

划分数据集的基本原则是:将无序的数据变得更加有序.

划分数据集的方法:

(1)使用信息论度量信息:

  • 熵(entropy)表示随机变量不确定性的度量.

         x是一个取有限个值(可以取n个不同值)的离散随机变量,其概率分布为p(x=xi)=pi,i=1,2,...,n,则随机变量x的熵定义为H(x)=-(p1logp1+p2logp2+....+pnlog(pn))

         熵依赖于x的分布,与x的取值无关,因此x的熵也可以写作H(p).0<=H(p)<=logn;熵越大,随机变量的不确定性就越大.

  • 条件熵(condition entropy)H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性.即随机变量X给定的条件下随机变量Y的条件熵,定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

         H(Y|X)=P1*H(Y|X=x1)+P2*H(Y|X=x2)+...+PN*H(Y|X=xn)  其中,Pi=P(X=xi)

  • 当熵和条件熵中的概率由数据估计(特别是极大似然估计)得到时,所对应的熵与条件熵称为经验熵和经验条件熵
  •  信息增益(information gain):表示得知特征x的信息而使得类y的信息的不确定性减少的程度

          特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即g(D,A)=H(D)-H(D|A),信息增益也称为互信息.

  • 信息增益比(information gaim ratio):特征A对训练数据集D的信息增益比为其信息增益g(D,A)和训练数据集D的经验熵H(D)的比.信息增益比也是值越大越好.


信息增益表示由于特征A而使得对数据集D的分类的不确定性减少的程度,信息增益大的特征具有更强的分类能力;

根据信息增益准则的特征选择方法是:对训练数据集D,计算其每个特征的信息增益,并比较其大小,选择信息增益最大的特征.

计算数据集的熵的过程如下:即使用所有类标签的发生频率计算类别出现的概率.熵越高,混合的数据也就越多.

<span style="font-size:14px;">def calcShannonEnt(dataSet):
	numbers = len(dataSet)
	labelCount = {}
	for featVector in dataSet :
		featLabel = featVector[-1]
		if featLabel not in labelCount.keys():
			labelCount[featLabel] = 0
		labelCount[featLabel] += 1
	shannon = 0.0
	for key in labelCount:
		labelTimes = labelCount[key]
		labelPro = float(labelTimes)/numbers
		shannon -= labelPro*log(labelPro,2)
	return shannon</span>

根据信息增益选择当前最优的划分特征代码如下:

<span style="font-size:14px;">def chooseBestFeature(dataSet):
	numOfeatures = len(dataSet[0])-1
	baseEntropy = calcShannonEnt(dataSet)
	bestInfoGain = 0.0
	bestFeatureIndex = -1
	numOdata = len(dataSet)
	for i in range(numOfeatures):
		#get the ith column of dataSet
		featureList = [example[i] for example in dataSet]
		uniqueFeatureValue = set(featureList)
		newEntropy = 0.0
		for value in uniqueFeatureValue:
			newDataSet = splitDataSet(dataSet,i,value)
			prob = len(newDataSet)/float(numOdata)
			newEntropy += prob * calcShannonEnt(newDataSet)
		infoGain = baseEntropy - newEntropy
		if (infoGain > bestInfoGain):
			bestInfoGain = infoGain
			bestFeatureIndex = i
	return bestFeatureIndex</span>


(2)度量集合无需程度的方法是基尼不纯度,简单的说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率.

5.使用决策树进行分类

使用决策树分类:

      在执行数据分类时,需要决策树/用于构造决策树的特征向量.然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进入叶子节点,最后将测试数据定义为叶子节点所属的类型.

实现代码如下:

实现tip:引入构造决策树的特征向量,方便程序确定此特征在数据集中的存放位置.

<span style="font-size:14px;">def classify(inputTree,featLabels,testVec):
	firstStr = inputTree.keys()[0]
	secondDict = inputTree[firstStr]
	featureIndex = featLabels.index(firstStr)
	for key in secondDict.keys():
		if (key==testVec[featureIndex]):
			if type(secondDict[key]).__name__=='dict':
				classLabel = classify(secondDict[key],featLabels,testVec)
			else:
				classLabel = secondDict[key]
	return classLabel
</span>

6.决策树的存储

构造决策树非常耗时,为了节省计算时间,最好能够在每次执行分类时,调用已经构造好的决策树.

为解决这个问题,引入python的pickle模块序列化对象:序列化对象可以在磁盘上保存对象,并在需要的时候读取,任何对象都可以执行序列化操作,字典对象也是.

实现代码如下:

<span style="font-size:14px;">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)</span>


实现多数表决的代码如下:

def majorityLabel(classList):
	classCount = {}
	for vote in classList:
		if vote not in classCount.keys():
			classCount[vote] = 0
		classCount[vote] += 1
	#descending the classCount according to the value of the label 
	sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
	return sortedClassCount[0][0]





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值