决策树
西瓜书的中介绍了决策树的一些基本算法和思想,学习后,在此记录一番:
决策树是模拟人在生活中的一类分类思想,那就是基于样本的特征不断的划分,直至它归属于最终的一类。
1. 决策树的算法
输入:训练集 D={{x1,y1},{x2,y2},...{xm},{ym}}. D = { { x 1 , y 1 } , { x 2 , y 2 } , . . . { x m } , { y m } } .
属性集 A={a1,a2,...,am}. A = { a 1 , a 2 , . . . , a m } .
过程:函数TreeGenerate(D,A)
- 生成节点Node
- if D中样本全部属于同一类别C then
- 将Node节点标记为C类叶子结点 return
- endif
- if A=空集 OR D在A上的取值全部相同 then
- 将Node节点标记为叶子结点,分为D中样本最多的类别 return
- endif
- 从A中选择最优划分属性 a∗ a ∗
- for a∗ a ∗ 的每一个值 av∗ a ∗ v do
- 为node 生成一个分支;令 Dv D v 表示D中在 a∗ a ∗ 取值为 av∗ a ∗ v 的子集
- if Dv D v 为空集
- 将分支结点标记为叶子结点,类别为D中样本最多的类 return
- else
- 以TreeGenerate( Dv D v ,A\ a∗ a ∗ )为分支结点
- endif
- endfor
输出:以node结点为根结点的一颗决策树
递归生成一个决策树。
2. 选择最优划分
信息熵(information entropy):度量信息集合纯度的指标。
信息熵越小,信息纯度越大。
信息增益:信息集合划分前后的信息熵的差。
最优化分即划分后信息集合纯度和×集合大小的权值的值最大。
3.增益率
信息增益偏好于可取数目较多的属性,因此有时候并不可靠。
消除这种影响,则使用增益率代替信息增益:
增益率偏好于可取数目较少的属性,所以有启发式算法C4.5,先选出信息增益
高于平均的属性,再选择增益率最高的。
4.基尼指数
基尼值也是体现了信息集合的纯度的一种指标,它的含义是,在集合中任意
抽取两个样本,样本类别不一致的概率。
基尼值越小,信息集合纯度越高。
基尼指数大概类比信息增益:
选择基尼指数最小的属性为划分属性。
5. 剪枝处理
预剪枝和后剪枝两种,剪枝与否的依据是该次划分是否提高了决策树泛化
性能。泛化性能的度量使用性能评估方法,如留出法,交叉验证法,自助法。
评估决策树对验证集的泛化精度。决定是否展开结点分支。
特点:预剪枝,容易导致欠拟合,使得很多的分支不得展开。后剪枝,消耗的
时间很多,时间开销巨大,优点,比预处理的拟合度一般要好。
6. 连续值离散化
对于有的属性是连续的值,采用离散化的方法,例如:连续值属性a,D上
样本在属性a上有n个取值,则对n个属性取值排序,求得n-1个中间值,作为待
划分点,这些点就可以和普通的属性相同的看待了。所以一个待划分的属性a
变成了n-1个待划分的属性一样。对于这n-1个值中的任意值 ai a i ,D中样本比 ai a i
小的归为一个子集,比 ai a i 大的归为一个子集,所以算是一种二划分属性。书上
计算公式和Gain无异,故不再记录。
值得注意的是,连续属性在一次分类后,后续的分类任然要考虑此属性。
对于这里的处理我有写一点代码,模拟这种情况,数据来自西瓜书的p84页的西瓜
数据。
import re
from numpy import *
from math import log
def Ent(p0,p1):
sum = 0
if p0!=0:
sum += p0*log(p0,2)
if p1!=0:
sum +=p1*log(p1,2)
return -sum
file = open('mido.txt')
testArray = zeros((1,17))
testLabel = []
dataList = re.split(r'[ \n]',file.readline())
dataList.pop()
testLabel = re.split(r' ',file.readline())
file.close()
dataDir = {} #样本的字典
for i in range(len(dataList)):
dataDir[dataList[i]] = testLabel[i]
dataList = sorted(dataList) #样本有序化
t = []
for i in range(1,len(dataList)):
a = float(dataList[i-1])
b = float(dataList[i])
t.append((a+b)/2)
dataV = len(dataList) #样本空间的数量|y|
maxGain = -1
answer = 0
for i in range(1,dataV):
sum = 0.0
p0 = 0
p1 = 0
for j in range(i):
if dataDir[dataList[j]]== '0':
p0+=1
elif dataDir[dataList[j]]=='1':
p1+=1
sum += ((i)/dataV)*Ent(p0/i,p1/i)
p0=0
p1=0
for j in range(i,dataV):
if dataDir[dataList[j]]== '0':
p0+=1
elif dataDir[dataList[j]]=='1':
p1+=1
sum += (1-i/dataV)*Ent(p0/(dataV-i),p1/(dataV-i))
sum = Ent(8/dataV,9/dataV) - sum
print(sum)
if sum>maxGain:
answer = t[i-1]
maxGain = sum
print('最优的划分点:',answer,' 信息增益为:',maxGain)
手工写制,只是一个脚本文件略显粗糙,但是其思想与书上吻合,是决策树求最优
划分的集中实现,并没有直接求出决策树。计算的结果也是 一致的,因为初学,中
间的计算没有用到numpy的一些特性。
7.缺失值处理
当有样本中有些属性有部分样本缺失的情况下依然可以通过加权值处理,利用样本产生决策树。而不是浪费了数据。对于这样的样本,需要解决两个问题:
1. 在属性值缺失的情况下怎么选择划分属性。
2. 给定划分属性,如果样本在该属性上存在缺失,怎么对样本进行划分。
如果存在训练集D,属性a,
D˘
D
˘
为D中在a属性上不存在缺失的样本的子集。我们仅仅用
D˘
D
˘
验证a属性的优劣。若给定样本
x
x
的权值为。
基于上面的定义对信息增益式进行推广:
7.决策树算法
- IDE3 信息增益
- C4.5 增益率 缺失值处理 连续值离散处理
- CART 基尼指数