《机器学习》西⽠书课后习题4.3——python实现基于信息熵划分的决策树算法
(简单、全⾯)
学python看谁的视频比较好
《机器学习》西⽠书课后习题4.3——python实现基于信息熵划分的决策树算法
《机器学习》西⽠书P93
4.3 试编程实现基于信息熵进⾏划分选择的决策树算法,并为表4.3中数据⽣成⼀棵决策树。
以下内容是使⽤sklearn快捷⽣成的决策树,由于该函数的局限性,所得到的决策树是⼆叉树,但是也能做到相对正确的分类,同时在敲代码的过程中参考了⼤量资料和博客,在此⽂中⼀并总结了决策树构造所踩的坑和学到的东西,请⼤家仔细阅读
前⾔(都是坑、运⾏代码前务必阅读、理解以下部分并配置好相关的环境)
初识sklearn构造决策树
python中的sklearn库中含有DecisionTree的构造⽅法,在本实例中我们主要是采⽤该⽅法来构造决策树,⼀般⽅法代码量较⼤且复杂,如果想要详细实现决策树构建的每⼀步请参见其他博客。下⾯介绍⼀下python中的DecisionTree构造⽅法。
python中sklearn库中的DecisionTreeClaasifier使⽤⽅法参见官⽅⽂档:官⽅⽂档
在python使⽤此类⽅法是ID3和CART之间存在差别,具体参见博客:
数据编码
注意:在使⽤sklearn构造决策树的过程中你会发现,该⽅法只针对数据部分为数值的数据集进⾏构造,像“⾊泽:青绿”这种字符串类型是⽆法进⾏处理的,因此,我们需要解决的问题是如何将这些字符串转换成数字来标识,该思路简⾔之就是对字符串进⾏编码处理。
同样地,在sklearn中也存在⼀部分函数⽤于离散型编码,对于不同的函数对应于不同的编码类型,为了降低编码这⼀过程对决策树的产⽣所造成的影响最低,同时也要考虑最终输出结果能够清晰明了,那么我们究竟该选择哪⼀种编码⽅式对我们的数据进⾏合适的编码呐?
关于sklearn中的多种离散型编码⽅式,参见博客:
经过最终的⽐较和分析,我们选定使⽤DictVectorizer⽅法来对数据中的离散型内容进⾏编码,同时使⽤preprocessing.LabelBinarizer对标记进⾏编码,原因如下
1. 使⽤preprocessing.LabelBinarizer对标记进⾏编码很容易理解,就是将标签进⾏⼆值化,即’1’代表’是‘,’0‘代表‘否’。
从⽽将字符转换为0-1表⽰。
2. DictVectorizer的处理对象是符号化(⾮数字化)的但是具有⼀定结构的特征数据,如字典等,将符号转成数字0/1表⽰。这句话是什么
意思呐?下⾯看⼀个例⼦就能明⽩
#-*- coding:utf-8 -*-
#学习⽬标:使⽤DictVectorizer对使⽤字典存储的数据进⾏特征抽取和向量化
#定义⼀组字典列表,⽤来表⽰多个数据样本(每个字典代表⼀个数据样本)
measurements =[{'city':'Beijing','temperature':33.},{'city':'London','temperature':12.},{'city':'San Fransisco','temperature':18.}]
#从sklearn.feature_extraction导⼊DictVectorizer
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer()
#输出转化后的特征矩阵
print vec.fit_transform(measurements).toarray()
#输出各个维度的特征含义
_feature_names()
输出结果为:
[[  1.  0.  0.  33.]
[  0.  1.  0.  12.]
[  0.  0.  1.  18.]]
['city=Dubai', 'city=London', 'city=San Fransisco', 'temperature']
我们不难发现,DictVectorizer对⾮数字化的处理⽅式是,借助原特征的名称,组合成新的特征,并采⽤0/1的⽅式进⾏量化,⽽数值型的特征转化⽐较⽅便,⼀般情况维持原值即可。
其中[ 1. 0. 0. 33.]代表的含义是’city=Dubai,temperature=33’,因为数组第⼀个元素为1,故表⽰‘city=Dubai’被选中,最后的元素代表‘temperature’的具体的值;该⽅法只针对离散型的值进⾏编码,对原本为数值的不修改值。
那么对于我们的西⽠数据集2.0为什么适⽤于这种⽅法呐?
⾸先,我们的数据集中‘密度’和‘含糖率’是连续的,其他属性是离散的,因此使⽤上述⽅法可以统⼀进⾏⼀次性编码,⽆需分开编码后再合并。
第⼆,该⽅法中的离散型数据均使⽤0-1来表⽰,就好像线性模型中的对率回归中使⽤的“单位阶跃函数”⼀样,对于x>0.5,可认为x=1,⽽x<0.5代表x=0,虽然表⾯看似是连续性的数值,实际其离散的特性已经隐含其中,并未因编码⽽对数据原本的特性产⽣较⼤的影响。
接下来我们来谈⼀谈决策树的可视化问题……
决策树的可视化
同样的,python中也提供了决策树可视化的库和函数,即Graphviz,我们只需要在决策树建⽴完成之后将其导出到graphviz,
可视化软件 免费下载地址:
运⾏程序后会产⽣⼀个dot⽂件,使⽤打开即可,注意:由于我的程序的问题最终产⽣的dot⽂件中⽂⽆法正确输出,需要以txt ⽂本打开后在⽂本中添加多⾏命令:fontname=“SimSun”,添加到节点内,具体的操作百度搜索⼀下就知道了……
综上,我们⼤致可以得到编程的主要思路,读取数据后使⽤⼆值化进⾏编码,将字符串类型的数据编码为0、1,⽽数字型数据保持float类型不做改变,然后利⽤sklearn建⽴决策树,完成之后利⽤graphviz进⾏可视化输出即可。
下⾯给出每⼀步实现的程序代码,并在个别代码附加详细解释和说明……
数据集——西⽠数据集3.0.csv(我们csv⽂件的编码类型是GBK,在使⽤⽂件读取数据的时候注意下!)
编号,⾊泽,根蒂,敲声,纹理,脐部,触感,密度,含糖率,好⽠
1,青绿,蜷缩,浊响,清晰,凹陷,硬滑,0.697,0.46,是
2,乌⿊,蜷缩,沉闷,清晰,凹陷,硬滑,0.774,0.376,是
3,乌⿊,蜷缩,浊响,清晰,凹陷,硬滑,0.634,0.264,是
4,青绿,蜷缩,沉闷,清晰,凹陷,硬滑,0.608,0.318,是
5,浅⽩,蜷缩,浊响,清晰,凹陷,硬滑,0.556,0.215,是
6,青绿,稍蜷,浊响,清晰,稍凹,软粘,0.403,0.237,是
7,乌⿊,稍蜷,浊响,稍糊,稍凹,软粘,0.481,0.149,是
8,乌⿊,稍蜷,浊响,清晰,稍凹,硬滑,0.437,0.211,是
9,乌⿊,稍蜷,沉闷,稍糊,稍凹,硬滑,0.666,0.091,否
10,青绿,硬挺,清脆,清晰,平坦,软粘,0.243,0.267,否
11,浅⽩,硬挺,清脆,模糊,平坦,硬滑,0.245,0.057,否
12,浅⽩,蜷缩,浊响,模糊,平坦,软粘,0.343,0.099,否
13,青绿,稍蜷,浊响,稍糊,凹陷,硬滑,0.639,0.161,否
14,浅⽩,稍蜷,沉闷,稍糊,凹陷,硬滑,0.657,0.198,否
15,乌⿊,稍蜷,浊响,清晰,稍凹,软粘,0.36,0.37,否
16,浅⽩,蜷缩,浊响,模糊,平坦,硬滑,0.593,0.042,否
17,青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,0.719,0.103,否
17,青绿,蜷缩,沉闷,稍糊,稍凹,硬滑,0.719,0.103,否
主要代码块
1. 建⽴⼀个函数is_number,作⽤是将数据中的字符型数字转换为float类型。
def is_number(n):
is_number =True
try:
num =float(n)
# 检查 "nan"
is_number = num == num  # 或者使⽤ `math.isnan(num)`
except ValueError:
is_number =False
return is_number
2. 建⽴⼀个函数⽤于读取数据,并将数据进⾏预处理
def loadData(filename):
data=open(filename,'r',encoding='GBK')
reader = ader(data)
headers =next(reader)
featureList =[]
labelList =[]
for row in reader:
labelList.append(row[len(row)-1])
rowDict ={}
for i in range(1,len(row)-1):
if is_number(row[i])==True:
rowDict[headers[i]]=float(row[i])
else:
rowDict[headers[i]]=row[i]
featureList.append(rowDict)
print(featureList)
print(labelList)
return featureList,labelList
3. 构造决策树并进⾏可视化输出
def createDTree(featureList,labelList):
vec = DictVectorizer()
dummyX = vec.fit_transform(featureList).toarray()
# print("dummyX:"+str(dummyX))
# _feature_names())
# print("labelList:"+str(labelList))
lb = preprocessing.LabelBinarizer()
dummyY = lb.fit_transform(labelList)
# print("dummyY: ",str(dummyY))
clf = tree.DecisionTreeClassifier(criterion='gini')
clf = clf.fit(dummyX,dummyY)
print("clf: ",str(clf))
_feature_names())
print(dummyX)
print(dummyY)
target_name=['不是好⽠','是好⽠']
with open("DecisionTree_gini.dot",'w')as f:
f = port_graphviz(clf,feature__feature_names(),class_names=target_name,out_file=f)
4. 外部调⽤函数
filename='西⽠数据集3.0.csv'
featureList,labelList=loadData(filename)
createDTree(featureList,labelList)决策树可视化展⽰
1. 基于基尼指数建⽴的决策树
2. 基于基尼指数建⽴的决策树2

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。