一、优缺点
1、优点:计算复杂度不高,输出结果易于理解,对中间值的确实不敏感,可以处理不相关的特征数据
2、缺点:可能会产生过度匹配问题
3、使用数据类型:数值型和标称型
二、决策树的一般流程
- 收集数据
- 准备数据
- 分析数据
- 训练算法
- 测试算法
- 使用算法
三、实例
# -*- coding: utf-8 -*-
# @Time : 19-4-2 下午6:44
# @Author : MRB
# @File : trees.py
# @Software: PyCharm Community Edition
from math import log
import operator
#创建一个数据集合
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
#change to discrete values
return dataSet, labels
'''
计算给定数据的香农熵
'''
def calcShannonEnt(dataSet):
numEntris = len(dataSet)
labelCounts = {}
for featVec in dataSet:
correntLabel = featVec[-1]
if correntLabel not in labelCounts.keys():
labelCounts[correntLabel] = 0
labelCounts[correntLabel] += 1
shannonEnt = 0.0
for key in labelCounts:
prob = float(labelCounts[key])/numEntris
shannonEnt -= prob * log(prob,2)
return shannonEnt
'''
按照给定特征划分数据集
'''
def splitDataSet(dataSet,axis,value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
'''
选择最好的数据集划分方式
该函数实现选取特征,划分数据集,计算得到最好的划分数据特征
'''
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1 #特征数量
bestEntropy = calcShannonEnt(dataSet) #计算熵
bestInfoGain = 0.0
bestFeture = -1
for i in range(numFeatures):
featList = [example[i] for example in dataSet]
uniqueVals = set(featList) #第i个特征的取值
newEntropy = 0.0
for value in uniqueVals:
subDataSet = splitDataSet(dataSet,i,value)
prob = len(subDataSet)/float(len(dataSet))
newEntropy += prob*calcShannonEnt(subDataSet)
infoGain = bestEntropy- newEntropy
if infoGain > bestInfoGain:
bestInfoGain = infoGain
bestFeture = i
return bestFeture
'''
投票表决
'''
def majorityCnt(classList):
classCount = {}
for vote in classList:
if vote not in classCount.keys():
classCount[vote] = 0
classCount[vote] += 1
sortedClassCount = sorted(classCount.items(),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:{}}
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
'''
使用决策树的分类函数(递归函数)
'''
def classify(inputTree,featLabels,testVec):
firstStr = list(inputTree.keys())[0]
secondDict = inputTree[firstStr]
featIndex = featLabels.index(firstStr)
for key in secondDict.keys():
if testVec[featIndex] == key:
if type(secondDict[key]).__name__=='dict':
classLabel = classify(secondDict[key],featLabels,testVec)
else:
classLabel = secondDict[key]
return classLabel
if __name__ == '__main__':
pass
#1、测试求香农熵
'''
熵越高,表示混合的数据也越多
'''
# dataSet,labels = createDataSet()
# # dataSet[0][-1] ='maybe'
# shannonEnt = calcShannonEnt(dataSet)
# print(shannonEnt)
#2、划分数据集
# dataSet, labels = createDataSet()
# result = chooseBestFeatureToSplit(dataSet)
# print(result)
#3、创建树
# dataSet, labels = createDataSet()
# result = createTree(dataSet,labels)
# print(result)
#4、使用决策树的分类函数
import copy
dataSet, labels = createDataSet()
_labels = copy.deepcopy(labels) #采用深拷贝
mytree = createTree(dataSet, _labels)
#预测
result = classify(mytree,labels,[1,1])
print(result)
result = classify(mytree, labels, [0, 1])
print(result)
四 、分析
4.1 ID3算法
ID3是基本的决策树构建算法,作为决策树经典的构建算法,其具有结构简单、清晰易懂的特点。虽然ID3比较灵活方便,但是有以下几个缺点:
(1)采用信息增益进行分裂,分裂的精确度可能没有采用信息增益率进行分裂高
(2)不能处理连续型数据,只能通过离散化将连续性数据转化为离散型数据
(3)不能处理缺省值
(4)没有对决策树进行剪枝处理,很可能会出现过拟合的问题
4.2 C4.5算法
C4.5在ID3的基础上对上述三个方面进行了相应的改进:
a) C4.5对节点进行分裂时采用信息增益率作为分裂的依据;
b) 能够对连续数据进行处理;
c) C4.5采用剪枝的策略,对完全生长的决策树进行剪枝处理,一定程度上降低过拟合的影响。
4.3 总结
C4.5是分类树最终要的算法,算法的思想其实很简单,但是分类的准确性高。可以说C4.5是ID3的升级版和强化版,解决了ID3未能解决的问题。要重点记住以下几个方面:
1.C4.5是采用信息增益率选择分裂的属性,解决了ID3选择属性时的偏向性问题;
2.C4.5能够对连续数据进行处理,采用一刀切的方式将连续型的数据切成两份,在选择切割点的时候使用信息增益作为择优的条件;
3.C4.5采用悲观剪枝的策略,一定程度上降低了过拟合的影响。