《机器学习实战》——决策树

基本原理:每个数据集都有一个或者多个特征作为已知条件,现在根据这些特征分类。K-近邻算法是已知部分分类,通过比较特征距离来将新的数据划分到旧的分类,但是你不知道它是如何划分,也就不知道分类是什么含义。决策树则是将一堆全新的数据,通过一个一个问答的形式,逐步缩小范围,给出最终分类,行成一个树形图。它通过遍历比较信息熵信息增益选出当前最适合分类的特征,从而得出一系列规则。

(参考博客园描述)因此先回忆一下信息论中有关信息量(就是“熵”)的定义。说有这么一个变量X,它可能的取值有n多种,分别是x1,x2,……,xn,每一种取到的概率分别是P1,P2,……,Pn,那么X的熵就定义为:

意思就是一个变量可能的变化越多(反而跟变量具体的取值没有任何关系,只和值的种类多少以及发生概率有关),它携带的信息量就越大。
对分类系统来说,类别C是变量,它可能的取值是C1,C2,……,Cn,而每一个类别出现的概率是P(C1),P(C2),……,P(Cn),因此n就是类别的总数。此时分类系统的熵就可以表示为:

信息增益是针对一个一个的特征而言的,就是看一个特征t,系统有它和没它的时候信息量各是多少。于是有了条件熵:(1)系统不包含特征t;(2)系统虽然包含特征t,但是t已经固定了,不能变化。

特征X被固定为值xi时的条件熵:

特征X被固定时的条件熵:

注意区别。从刚才计算均值的讨论可以看出来,第二个式子与第一个式子的关系就是:

因此固定t时系统的条件熵就有了,为了区别t出现时的符号与特征t本身的符号,我们用T代表特征,而用t代表T出现,那么:

与刚才的式子对照一下,含义很清楚对吧,P(t)就是T出现的概率,就是T不出现的概率。这个式子可以进一步展开,其中的

另一半就可以展开为:

因此特征T给系统带来的信息增益就可以写成系统原本的熵与固定特征T后的条件熵之差:

关键词:信息熵; 条件熵; 信息增益; 树形图

案例:

信息增益Gain(R)表示属性R给分类带来的信息量,我们寻找Gain最大的属性,就能使分类尽可能的纯,即最可能的把不同的类分开。不过我们发现对所以的属性Info(D)都是一样的,所以求最大的Gain可以转化为求最新的InfoR(D)。这里引入Info(D)只是为了说明背后的原理,方便理解,实现时我们不需要计算Info(D)。举一个例子,数据集D如下:

记录ID 年龄 输入层次 学生 信用等级 是否购买电脑
1 青少年 一般
2 青少年 良好
3 中年 一般
4 老年 一般
5 老年 一般
6 老年 良好
7 中年 良好
8 青少年 一般
9 青少年 一般
10 老年 一般
11 青少年 良好
12 中年 良好
13 中年 一般
14 老年 良好

  这个数据集是根据一个人的年龄、收入、是否学生以及信用等级来确定他是否会购买电脑,即最后一列“是否购买电脑”是类标。现在我们用信息增益选出最最佳的分类属性,计算按年龄分裂后的信息量:

  整个式子由三项累加而成,第一项为青少年,14条记录中有5条为青少年,其中2(占2/5)条购买电脑,3(占3/5)条不购买电脑。第二项为中年,第三项为老年。类似的,有:

  可以得出Info年龄(D)最小,即以年龄分裂后,分得的结果中类标最纯,此时已年龄作为根结点的测试属性,根据青少年、中年、老年分为三个分支:

  注意,年龄这个属性用过后,之后的操作就不需要年龄了,即把年龄从attributeList中删掉。往后就按照同样的方法,构建D1,D2,D3对应的决策子树。ID3算法使用的就是基于信息增益的选择属性方法。


算法实施:

1. 创建数据集,给出特征标签——createDataSet()

2. 计算香农熵——getShannonEnt()

3. 根据特征、特征值抽出符合条件的分类结果——splitDataSet()

4. 选择最佳划分的特征:每个特征按不同的值划分类别,分别计算各个类别香农熵并相加作为该特征划分的香农熵。用初始香农熵减去求出的新熵即为信息增益。信息增益越大,说明熵越小,包含信息种类越少,该特征就越好。遍历所有特征,选出最大的信息增益,选择该增益对应的特征作为返回值.调用2,3.

——chooseBestFeatureToSplit()

5. 选择最后一个特征内部的最大类返回:作为终止条件——majorityCnt()

6. 创建树:两个终止条件——类别完全相同 or 到达最后一个特征。首先选择最佳划分特征,打印出它的label;删除该label,剩余的标签作为新的递归标签组;针对之前选好的特征,遍历其取值划分出一个类别,在此基础上建立子树。递归调用形成整棵决策树。——createTree()

# coding:utf-8
from math import log
def getDataSet():
	dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
	labels = ['no surfacing', 'flippers']
	return dataSet, labels
def getShangnonEnt(dataset):
	####### 得到信息熵,首先统计实例总数 #######
	N = len(dataset)
	labelCounts = {}
	for item in dataset:
		nowLabel = item[-1]
		if nowLabel not in labelCounts.keys():
			labelCounts[nowLabel] = 0
		labelCounts[nowLabel] += 1
	# 开始求熵
	shannonEnt = 0.0
	for key in labelCounts:
		prob = float(labelCounts[key])/N
		shannonEnt -= prob * log(prob, 2)
	return shannonEnt
def splitDataSet(dataSet, axis, value):
	####### 根据特征项axis的value值划分类,并返回该分类 #######
	newData = []
	for item in dataSet:
		if item[axis] == value:
			reducePart = item[:axis]
			reducePart.extend(item[axis+1:])
			newData.append(reducePart)
	return newData
def getBestFeatureToSplit(dataSet):
	###### 计算最大的信息增益,选出最佳划分特征。信息增益:基本熵减新熵######
	numFeature = len(dataSet[0])-1	# 特征总数
	baseEntropy = getShangnonEnt(dataSet)
	bestInfoGain = 0.0
	bestFeature = -1
	# 选择所有特征,逐个计算
	for i in range(numFeature):
		myList = [item[i] for item in dataSet]
		uniqueList = set(myList)
		newEntropy = 0.0
		# 计算当前特征的所有可能值的信息熵
		for value in uniqueList:
			subDataSet = splitDataSet(dataSet, i, value)
			prob = len(subDataSet)/float(len(dataSet))
			newEntropy += prob * getShangnonEnt(subDataSet)
		infoGain = baseEntropy - newEntropy
		if (infoGain > bestInfoGain):
			bestInfoGain = infoGain
			bestFeature = i
	print("bestFeature",bestFeature)
	return bestFeature
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
def createTree(dataSet, labels):
	classList = [item[-1] for item in dataSet]
	if classList.count(classList[0]) == len(classList):
		# 类别完全相同则停止划分
		return classList[0]
	if len(dataSet[0]) == 1:
		# 遍历玩所有特征,返回出现次数最多的
		return majorityCnt(classList)
	bestFeat = getBestFeatureToSplit(dataSet)
	bestFeatLabel = labels[bestFeat]
	myTree = {bestFeatLabel:{}}
	del(labels[bestFeat])
	# 得到列表包含的所有属性值
	featValues = [item[bestFeat] for item in dataSet]
	uniqueVals = set(featValues)
	for value in uniqueVals:
		subLabels = labels[:]
		myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)
	return myTree
dataSet, labels = getDataSet()
print("dataSet:", dataSet, labels)
tree = createTree(dataSet, labels)
print("myTree:", tree)


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
决策树算法是一种广泛应用于分类和回归的机器学习算法,它基于树形结构对样本进行分类或预测。决策树算法的主要思想是通过一系列的判断来对样本进行分类或预测。在决策树中,每个节点表示一个属性或特征,每个分支代表该属性或特征的一个取值,而每个叶子节点代表一个分类或预测结果。 决策树算法的训练过程主要包括以下步骤: 1. 特征选择:根据某种指标(如信息增益或基尼系数)选择最优的特征作为当前节点的分裂属性。 2. 决策树生成:根据选择的特征将数据集分成若干个子集,并递归地生成决策树。 3. 剪枝:通过剪枝操作来提高决策树的泛化性能。 决策树算法的优点包括易于理解和解释、计算复杂度较低、对缺失值不敏感等。但是,决策树算法也存在一些缺点,如容易出现过拟合、对离散数据敏感等。 下面是一个决策树算法的案例:假设我们要根据一个人的年龄、性别、教育程度和职业预测其收入水平(高于或低于50K)。首先,我们需要将这些特征进行编码,将其转换为数值型数据。然后,我们可以使用决策树算法对这些数据进行训练,并生成一个决策树模型。最后,我们可以使用该模型对新的数据进行分类或预测。例如,根据一个人的年龄、性别、教育程度和职业,我们可以使用决策树模型预测该人的收入水平。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值