文章目录
一.
1.1决策树模型结构
分类决策树模型一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型:内部结点和叶结点。内部结点表示一个特征或属性,叶结点表示一个类。
1.2决策树递归思想
决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得对各个子数据集有一个最好的分类的过程。这一过程对应着特征空间的划分,也对应着决策树的构建。开始,构建根节点,将所有训练数据都放在根结点。选择一个最优特征,按照这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。如果这些子集已经能够被基本正确分类,那么构建叶结点,并将这些子集分到所对应叶结点中去;如果还有子集不能够被基本正确分类,那么就对这些子集选择新的最优特征,继续对其进行分割,构建相应的结点。如此递归地进行下去,直至所有训练数据子集被基本正确分类,或者没有合适的特征为止。最后每个子集都被分到叶结点上,即都有了明确的类。这就生成了一棵决策树。
二.
2.2信息增益
特征A对训练数据集D的信息增益g(D, A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即
g
(
D
,
A
)
=
H
(
D
)
−
H
(
D
∣
A
)
g(D,A) = H(D) - H(D|A)
g(D,A)=H(D)−H(D∣A)
一般地,熵H(Y)与条件熵H(Y|X)之差称为互信息。决定决策树学习中的信息增益等价于训练数据集中类与特征的互信息。
而决策树就是利用信息增益准则来选择特征
2.2信息增益率
信息增益值的大小是相对于训练数据集而言的,并没有绝对意义。在分类问题困难时,也就是说在训练数据集的经验熵大的时候,信息增益值会偏大。反之,信息增益值会偏小。使用信息增益比可以对这一问题进行校正。这是特征选择的另一准则。
信息增益比:特征A对训练数据集D的信息增益比
g
R
(
D
,
A
)
g_R(D,A)
gR(D,A)定义为其信息增益g(D, A)与训练数据集D的经验熵H(D)之比:
g
R
(
D
,
A
)
=
g
(
D
,
A
)
H
(
D
)
g_R(D,A) = \frac{g(D,A)}{H(D)}
gR(D,A)=H(D)g(D,A)
三.
3.1 ID3算法
ID3算法的核心是在决策树各个结点上应用信息增益准则选择特征,递归地构建决策树。具体方法是:从根节点(root node)开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子结点;再对子结点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或者没有特征可以选择为止。最后得到一个决策树。ID3相当于用极大似然法进行概率模型的选择
优点:
简单
缺点:
1)ID3算法采用信息增益来选择最优划分特征,然而人们发现,信息增益倾向与取值较多的特征,对于这种具有明显倾向性的属性,往往容易导致结果误差;
2)ID3算法没有考虑连续值,对与连续值的特征无法进行划分;
3)ID3算法无法处理有缺失值的数据;
4)ID3算法没有考虑过拟合的问题,而在决策树中,过拟合是很容易发生的;
5)ID3算法采用贪心算法,每次划分都是考虑局部最优化,而局部最优化并不是全局最优化,当然这一缺点也是决策树的缺点,获得最优决策树本身就是一个NP难题,所以只能采用局部最优;
3.2 C4.5算法
C4.5算法的提出旨在解决ID3算法的缺点 ,是对ID3算法的改进。
1)采用信息增益比来替代信息增益作为寻找最优划分特征,信息增益比的定义是信息增益和特征熵的比值,对于特征熵,特征的取值越多,特征熵就倾向于越大;
2)对于连续值的问题,将连续值离散化,在这里只作二类划分,即将连续值划分到两个区间,划分点取两个临近值的均值,因此对于m个连续值总共有m-1各划分点,对于每个划分点,依次算它们的信息增益,选取信息增益最大的点作为离散划分点;
3)对于缺失值的问题,我们需要解决两个问题,第一是在有缺失值的情况下如何选择划分的属性,也就是如何得到一个合适的信息增益比;第二是选定了划分属性,对于在该属性的缺失特征的样本该如何处理。
4)对于过拟合的问题,采用了后剪枝算法和交叉验证对决策树进行剪枝处理,这个在CART算法中一起介绍。
还存在的不足:
1)C4.5的剪枝算法不够优秀;
2)C4.5和ID3一样,都是生成的多叉树,然而在计算机中二叉树模型会比多叉树的运算效率高,采用二叉树也许效果会更好;
3)在计算信息熵时会涉及到大量的对数运算,如果是连续值还需要进行排序,寻找最优离散划分点,这些都会增大模型的运算;
4)C4.5算法只能处理分类问题,不能处理回归问题,限制了其应用范围。
四
4.1划分数据集
def split_data_set(dataSet, axis, value):
"""
:param dataSet: 数据集
:param axis: 划分数据集特征的列号0,1,或者列名
:param value: 返回特征的值
:return:
"""
re_data_set = []
for feat_vector in dataSet:
if feat_vector[axis] == value:
reduceFeatVec =feat_vector[:axis]
reduceFeatVec.extend(feat_vector[axis+1 :])
re_data_set .append(reduceFeatVec)
4.1选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1
# 计算整个数据集的原始香农熵
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0; bestFeature = -1
# 遍历数据集中的所有特征
for i in range(numFeatures):
# 将数据集中所有第i个特征值或者所有可能存在的值写入这个新list中
featList = [example[i] for example in dataSet]
# 使用set数据类型得到互不相同的元素值
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
4.3创建树的代码
def createTree(dataSet,labels):
'''
:param dataSet: 数据集
:param labels: 标签列表
:return: 决策树信息,字典类型
'''
# 创建列表包含数据集的所有类标签
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