一、【实验目的】
理解决策树算法原理,掌握决策树算法框架;
理解决策树学习算法的特征选择、树的生成和树的剪枝;
能根据不同的数据类型,选择不同的决策树算法;
针对特定应用场景及数据,能应用决策树算法解决实际问题。
二、【实验内容】
设计算法实现熵、经验条件熵、信息增益等方法。
针对给定的房贷数据集(数据集表格见附录1)实现ID3算法。
熟悉sklearn库中的决策树算法;
针对iris数据集,应用sklearn的决策树算法进行类别预测。
三、【实验报告要求】
对照实验内容,撰写实验过程、算法及测试结果;
代码规范化:命名规则、注释;
查阅文献,讨论ID3、5算法的应用场景;
查询文献,分析决策树剪枝策略。
【附录1】
年龄 有工作 有自己的房子 信贷情况 类别
0 青年 否 否 一般 否 1 青年 否 否 好 否 2 青年 是 否 好 是 3 青年 是 是 一般 是 4 青年 否 否 一般 否 5 中年 否 否 一般 否 6 中年 否 否 好 否 7 中年 是 是 好 是 8 中年 否 是 非常好 是 9 中年 否 是 非常好 是 10 老年 否 是 非常好 是 11 老年 否 是 好 是 12 老年 是 否 好 是 13 老年 是 否 非常好 是 14 老年 否 否 一般 否
四、实验内容及结果
实验代码及截图
1、决策树
(1)导包
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline from collections import Counter import math from math import log
(2)创建数据
def createDataSet(): dataSet = [[0, 0, 0, 0, 'no'], # 数据集 [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'], [0, 1, 1, 0, 'yes'], [0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'], [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'], [1, 0, 1, 2, 'yes'], [1, 0, 1, 2, 'yes'], [2, 0, 1, 2, 'yes'], [2, 0, 1, 1, 'yes'], [2, 1, 0, 1, 'yes'], [2, 1, 0, 2, 'yes'], [2, 0, 0, 0, 'no']] labels = ['年龄', '有工作', '有自己的房子', '信贷情况','类别'] # 分类属性 return dataSet, labels
dataSet,labels = createDataSet()
train_data = pd.DataFrame(dataSet, columns=labels)
train_data
(3)计算信息熵
def splitDataSet(dataSet, axis, value): retDataSet = [] # 创建返回的数据集列表 for featVec in dataSet: # 遍历数据集 if featVec[axis] == value: reducedFeatVec = featVec[:axis] # 去掉axis特征 reducedFeatVec.extend(featVec[axis + 1:]) # 将符合条件的添加到返回的数据集 retDataSet.append(reducedFeatVec) return retDataSet # 返回划分后的数据集 def chooseBestFeatureToSplit(dataSet): numFeatures = len(dataSet[0]) - 1 # 特征数量 baseEntropy = calcShannonEnt(dataSet) # 计算数据集的香农熵 bestInfoGain = 0.0 # 信息增益 bestFeature = -1 # 最优特征的索引值 for i in range(numFeatures): # 遍历所有特征 # 获取dataSet的第i个所有特征 featList = [example[i] for example in dataSet] uniqueVals = set(featList) # 创建set集合{},元素不可重复 newEntropy = 0.0 # 经验条件熵 for value in uniqueVals: # 计算信息增益 subDataSet = splitDataSet(dataSet, i, value) # subDataSet划分后的子集 prob = len(subDataSet) / float(len(dataSet)) # 计算子集的概率 newEntropy += prob * calcShannonEnt(subDataSet) # 根据公式计算经验条件熵 infoGain = baseEntropy - newEntropy # 信息增益 print(u"第%i特征信息的信息增量为:%.3f"%(i,infoGain)) # 打印每个特征的信息增益 if (infoGain > bestInfoGain): # 计算信息增益 bestInfoGain = infoGain # 更新信息增益,找到最大的信息增益 bestFeature = i # 记录信息增益最大的特征的索引值 return bestFeature # 返回信息增益最大的特征的索引值 def majorityCnt(classList): classCount = {} for vote in classList: # 统计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] # 返回classList中出现次数最多的元素
(4)创建决策树
def createTree(dataSet, labels, featLabels): classList = [example[-1] for example in dataSet] # 取分类标签(是否放贷:yes or no) if classList.count(classList[0]) == len(classList): # 如果类别完全相同则停止继续划分 return classList[0] if len(dataSet[0]) == 1: # 遍历完所有特征时返回出现次数最多的类标签 return majorityCnt(classList) bestFeat = chooseBestFeatureToSplit(dataSet) # 选择最优特征 bestFeatLabel = labels[bestFeat] # 最优特征的标签 featLabels.append(bestFeatLabel) print(u"此时最优索引为:"+str(bestFeatLabel)) myTree = {bestFeatLabel: {}} # 根据最优特征的标签生成树 del (labels[bestFeat]) # 删除已经使用特征标签 featValues = [example[bestFeat] for example in dataSet] # 得到训练集中所有最优特征的属性值 uniqueVals = set(featValues) # 去掉重复的属性值 for value in uniqueVals: subLabels = labels[:] # 递归调用函数createTree(),遍历特征,创建决策树。 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels, featLabels) return myTree def classify(inputTree, featLabels, testVec): firstStr = next(iter(inputTree)) # 获取决策树结点 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__': dataSet, labels = createDataSet() featLabels = [] myTree = createTree(dataSet, labels, featLabels) print(myTree) testVec = [0,0] # 测试数据 result = classify(myTree, featLabels, testVec) if result == 'yes': print('放贷') if result == 'no': print('不放贷')
2、运用sklearn生成决策树
import numpy as np from sklearn import tree import graphviz #画图需要自己安装 dataset=[ # 数据集 [1,0,0,1,0], [1,0,0,2,0], [1,1,0,2,1], [1,1,1,1,1], [1,0,0,1,0], [2,0,0,2,0], [2,0,0,2,0], [2,1,1,2,1], [2,0,1,3,1], [2,0,1,2,1], [3,0,1,3,1], [3,0,1,2,1], [3,1,0,3,1], [3,1,0,3,1], [3,0,0,1,0] ] feature =['年龄','没有工作','没有自己的房子','信贷情况'] classname =['不放贷','放贷'] X = [x[0:4] for x in dataset] print(X) Y = [y[-1] for y in dataset] print(Y) tree_clf = DecisionTreeClassifier(max_depth=4) # 最深分为4层 tree_clf.fit(X, Y) dot_data = tree.export_graphviz( #实现可视化 tree_clf, out_file=None, feature_names=feature, class_names=classname, rounded=True, filled=True, ) graph = graphviz.Source(dot_data) graph
3.运用sklearn中iris数据集创建决策树进行测试
(1)导包及测试
from sklearn import tree #导入树 from sklearn.tree import DecisionTreeClassifier #导入决策树分类器 from sklearn.datasets import load_iris #导入鸢尾花数据集 from sklearn.model_selection import train_test_split #分训练集测试集的类 import pandas as pd iris = load_iris() #将数据集实例化,别忘了括号 Xtrain,Xtest,Ytrain,Ytest = train_test_split(iris.data,iris.target,test_size=0.3) #实例化模型,括号不填criterion默认是‘gini’,也可以填criterion = 'entropy' clf = DecisionTreeClassifier() #训练数据集 clf = clf.fit(Xtrain, Ytrain) #评估数据集 score = clf.score(Xtest, Ytest) score #将评估结果打印出来,因为测试集和训练集划分的不同,可能每个人的结果也不同
(2)实现可视化,画出决策树
import graphviz from sklearn.tree import DecisionTreeClassifier from sklearn.tree import export_graphviz dot_data=tree.export_graphviz(clf,out_file=None, feature_names=iris.feature_names, class_names=True,filled=False,rounded=True) graph = graphviz.Source(dot_data) graph
五、实验问题与解决方法
问题:实现可视化的时候出现了:No module named 'graphive',
解决方法:下载graphviz软件后,在Anaconda Prompt下输入conda install python-graphviz安装
六、实验小结
(1)、讨论ID3和C4.5算法的应用场景1、ID3应用场景
ID3算法的核心是在决策树各个结点上应用信息增益准则选择特征,递归地构建决策树,他的优点总的来说,就是理论清晰、方法简单、学习能力较强,他已被广泛应用于数据挖掘和人工智能中,也常用于机器学习和自然语言处理领域,得到了极大的发展
2、C4.5应用场景
C4.5算法与ID3算法一样使用了信息熵的概念,ID3使用的是熵的变化值,而C4.5用的是信息增益率,可分类也可回归,他的优点条理清晰,防止过拟合,产生的分类规则易于理解,准确率较高。在机器学习,金融分析,遥感影响,数据挖掘等领域得到广泛应用
(2)、分析决策树剪枝策略
剪枝是决策树算法对付过拟合的主要手段。因为决策树在划分过程中为了尽可能正确分类训练样本,可能会不断重复,产生过拟合现象。
预剪枝:是在决策树的生成过程中,对每个结点在划分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划分即结束树的构建并将当前节点标记为叶结点;
优点:这不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。
缺点:预剪枝基于“贪心”本质禁止这些分支展开,给预剪枝决策树带来了欠拟合的风险。
后剪枝:是先从训练集生成一棵完整的决策树,然后自底向上地对叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化为性能提升,则将该子树替换为叶结点。
优点:有效避免欠拟合现象,正确率较高。
缺点:需要先生成完整的决策树,开销大
标签:dataSet,算法,实验,import,yes,sklearn,决策树 From: https://www.cnblogs.com/s010307/p/16820962.html