决策树算法是一种逼近离散函数值的方法。它是一种典型的分类方法,首先对数据进行处理,利用归纳算法生成可读的规则和决策树,然后使用决策对新数据进行分析。本质上决策树是通过一系列规则对数据进行分类的过程。
决策树算法构造决策树来发现数据中蕴涵的分类规则.如何构造精度高、规模小的决策树是决策树算法的核心内容。决策树构造可以分两步进行。第一步,决策树的生成:由训练样本集生成决策树的过程。一般情况下,训练样本数据集是根据实际需要有历史的、有一定综合程度的,用于数据分析处理的数据集。第二步,决策树的剪枝:决策树的剪枝是对上一阶段生成的决策树进行检验、校正和修下的过程,主要是用新的样本数据集(称为测试数据集)中的数据校验决策树生成过程中产生的初步规则,将那些影响预衡准确性的分枝剪除。
在构建决策树的时候,我们得考虑哪个属性来当根节点?哪些属性来当内部决策节点?这里是有一个依据原则的。在说这个原则之前,我们先说一下熵的概念。
熵(entropy):用来表示物体内部的混乱程度。一个物体内部构成越纯,熵越小;越混乱,熵越大。在机器学习中,表示随机变量分布的混乱程度。
信息熵(information entropy):信息熵通常用来描述整个随机分布所带来的信息量平均值,更具统计特性。一个系统越是有序,信息熵就越低;反之,一个系统越是混乱,信息熵就越高。
假设样本集合 D 中第 i 类样本所占的比例是 pi(i=1,2,⋯,N) ,则样本集合 D 的信息熵为
注:随机变量的取值个数越多,信息熵就越大,混乱程度就越大。当随机分布为均匀分布时,熵最大。
条件熵 (Conditional entropy): 现在我们假设将样本集合 D 按属性 a 进行划分,假设属性 a 有 v 个可能的取值,则按 a 属性进行分裂出的 v 个子集(即树中的 v 个分支),每个可能取值集合为 D^v ,则 a 属性的条件熵计算方法为( |D^v| 和 |D| 表示集合中元素的个数)
决策树模型创建的核心就是选择合适的树根 , 将重要的属性放在树根 , 然后子树中 , 继续选择子树中重要的属性放在子树的树根 , 依次递归 , 最终得到决策结果 ( 叶子节点 ) ;
随着树深度的增加,节点的熵可以迅速地降低。熵降低的速度越来越快,得到一个最矮的高度树。
a.选择属性 : 递归由上到下决定每一个节点的属性 , 依次递归构造决策树 ;
b.数据集划分 : 开始决策时 , 所有的数据都在树根 , 由树根属性来划分数据集 ;
c.属性离散化 : 如果属性的值是连续值 , 需要将连续属性值离散化 ; 如 : 100 分满分 , 将 60 分以下分为不及格数据 , 60 分以上分为及格数据 ;
a.子树分类完成 : 节点上的子数据集都属于同一个类别 , 该节点就不再向下划分 , 称为叶子节点 ;
b.属性 ( 节点 ) 全部分配完毕 : 所有的属性都已经分配完毕 , 决策树的高度等于属性个数 ;
c.所有样本分类完毕 : 所有的样本数据集都分类完成 ;
def CreateTree(DataSet):
#获取所有特征标签
index_list = list(DataSet.columns)
#获取最后一列(分类标签)的类别
label_series = DataSet.iloc[:,-1].value_counts()
#判断类别标签最多一个是否等于数据样本数、或者数据集是否只有一列
if label_series[0]==DataSet.shape[0] or DataSet.shape[1] == 1:
return label_series.index[0] #返回类标签
# 获取最优特征列索引
col = ChooseBF(DataSet)
# 获取最优特征
BestFeature = index_list[col]
#将最优特征依次填入字典中
TheTree = {BestFeature:{}}
# 从标签列表中删去该特征标签
del index_list[col]
#提取最佳切分列的所有属性值
value_list = set(DataSet.iloc[:,col])
#利用递归方法建树,每次对象为当前最优特征
for value in value_list:
TheTree[BeatFeature][value] = CreateTree(splitSet(DataSet,col,value))
return TheTree
运行上述代码即可得到 TheTree:
{'tearRate': {0: 'no lenses', 1: {'astigmatic': {0: {'age': {0: 'soft', 1: 'soft', 2: {'prescript': {0: 'no lenses', 1: 'soft'}}}}, 1: {'prescript': {0: 'hard', 1: {'age': {0: 'hard', 1: 'no lenses', 2: 'no lenses'}}}}}}}}
"""
函数功能:对一个测试实例进行分类
参数说明:
inputTree:已经生成的决策树
labels:存储选择的最优特征标签
testVec:测试数据列表,顺序对应原数据集
返回:
classLabel:分类结果
"""
def classify(inputTree,labels, testVec):
firstStr = next(iter(inputTree)) #获取决策树第一个节点
secondDict = inputTree[firstStr] #下一个字典
featIndex = labels.index(firstStr) #第一个节点所在列的索引
for key in secondDict.keys():
if testVec[featIndex] == key:
if type(secondDict[key]) == dict :
classLabel = classify(secondDict[key], labels, testVec)
else:
classLabel = secondDict[key]
return classLabel
"""
函数功能:对测试集进行预测,并返回预测后的结果
参数说明:
train:训练集
test:测试集
返回:
test:预测好分类的测试集
"""
def acc_classify(train,test):
inputTree = createTree(train) #根据测试集生成一棵树
labels = list(train.columns) #数据集所有的列名称
result = []
for i in range(test.shape[0]): #对测试集中每一条数据进行循环
testVec = test.iloc[i,:-1] #测试集中的一个实例
classLabel = classify(inputTree,labels,testVec) #预测该实例的分类
result.append(classLabel) #将分类结果追加到result列表中
test['predict']=result #将预测结果追加到测试集最后一列
acc = (test.iloc[:,-1]==test.iloc[:,-2]).mean() #计算准确率
print(f'模型预测准确率为{acc}')
return test
测试函数:
train = dataSet
test = dataSet.iloc[:3,:]
acc_classify(train,test)
#导入相应的包
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
import graphviz
#特征
Xtrain = dataSet.iloc[:,:-1]
#标签
Ytrain = dataSet.iloc[:,-1]
labels = Ytrain.unique().tolist()
Ytrain = Ytrain.apply(lambda x: labels.index(x)) #将本文转换为数字
#绘制树模型
clf = DecisionTreeClassifier()
clf = clf.fit(Xtrain, Ytrain)
tree.export_graphviz(clf)
dot_data = tree.export_graphviz(clf, out_file=None)
graphviz.Source(dot_data)
#给图形增加标签和颜色
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=['no surfacing', 'flippers'],
class_names=['fish', 'not fish'],
filled=True, rounded=True,
special_characters=True)
graphviz.Source(dot_data)
#利用render方法生成图形
graph = graphviz.Source(dot_data)
graph.render("fish")
这样就实现了决策树的分类及展示了