实验介绍

1.实验内容

本实验学习并实现决策树算法。

2.实验目标

通过本实验掌握决策树算法的基本原理。

3.实验知识点

  • 香农熵
  • 信息增益

4.实验环境

  • python 3.6.5

5.预备知识

  • Python编程基础

准备工作

  点击屏幕右上方的下载实验数据模块,选择下载decision_tree_glass.tgz到指定目录下,然后再依次选择点击上方的File->Open->Upload,上传刚才下载的数据集压缩包,再使用如下命令解压:

!tar -zxvf decision_tree_glass.tgz
decision_tree_glass/
decision_tree_glass/lenses.txt
decision_tree_glass/classifierStorage.txt

xt

决策树构建—ID3算法

  ID3算法的核心是在决策树各个结点上对应信息增益准则选择特征,递归地构建决策树。具体方法是:从根结点(root node)开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子节点;再对子结点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止。最后得到一个决策树。ID3相当于用极大似然法进行概率模型的选择。
  利用决策树实验求得的结果,由于特征A3(有自己的房子)的信息增益值最大,所以选择特征A3作为根结点的特征。它将训练集D划分为两个子集D1(A3取值为"是")和D2(A3取值为"否")。由于D1只有同一类的样本点,所以它成为一个叶结点,结点的类标记为“是”。对D2则需要从特征A1(年龄),A2(有工作)和A4(信贷情况)中选择新的特征,计算各个特征的信息增益:

  根据计算,选择信息增益最大的特征A2(有工作)作为结点的特征。由于A2有两个可能取值,从这一结点引出两个子结点:一个对应"是"(有工作)的子结点,包含3个样本,它们属于同一类,所以这是一个叶结点,类标记为"是";另一个是对应"否"(无工作)的子结点,包含6个样本,它们也属于同一类,所以这也是一个叶结点,类标记为"否"。
  这样就生成了一个决策树,该决策树只用了两个特征(有两个内部结点),生成的决策树如下图所示:

【练习】决策树构建—编写代码构建决策树

我们使用字典存储决策树的结构,比如上小节我们分析出来的决策树,用字典可以表示为:
  {‘有自己的房子’: {0: {‘有工作’: {0: ‘no’, 1: ‘yes’}}, 1: ‘yes’}}
创建函数majorityCnt统计classList中出现此处最多的元素(类标签),创建函数createTree用来递归构建决策树。编写代码如下:

# -*- coding: UTF-8 -*-
from math import log
import operator
"""
函数说明:计算给定数据集的经验熵(香农熵)
Parameters:dataSet - 数据集
Returns:shannonEnt - 经验熵(香农熵)
"""
def calcShannonEnt(dataSet):### Start Code Here ###                      numEntires = len(dataSet)                        #返回数据集的行数labelCounts = {}                                #保存每个标签(Label)出现次数的字典for featVec in dataSet:                            #对每组特征向量进行统计currentLabel = featVec[-1]                    #提取标签(Label)信息if currentLabel not in labelCounts.keys():    #如果标签(Label)没有放入统计次数的字典,添加进去labelCounts[currentLabel] = 0labelCounts[currentLabel] += 1                #Label计数shannonEnt = 0.0                                #经验熵(香农熵)for key in labelCounts:                            #计算香农熵prob = float(labelCounts[key]) / numEntires    #选择该标签(Label)的概率shannonEnt -= prob * log(prob, 2)            #利用公式计算return shannonEnt                                #返回经验熵(香农熵)### End Code Here ###

"""
函数说明:创建测试数据集
Parameters:无
Returns:dataSet - 数据集labels - 特征标签
"""
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                             #返回数据集和分类属性
"""
函数说明:按照给定特征划分数据集
Parameters:dataSet - 待划分的数据集axis - 划分数据集的特征value - 需要返回的特征的值
Returns:无
"""
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                                      #返回划分后的数据集
"""
函数说明:选择最优特征
Parameters:dataSet - 数据集
Returns:bestFeature - 信息增益最大的(最优)特征的索引值
"""
def chooseBestFeatureToSplit(dataSet):### Start Code Here ###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("第%d个特征的增益为%.3f" % (i, infoGain))            #打印每个特征的信息增益if (infoGain > bestInfoGain):                             #计算信息增益bestInfoGain = infoGain                             #更新信息增益,找到最大的信息增益bestFeature = i                                     #记录信息增益最大的特征的索引值return bestFeature                                             #返回信息增益最大的特征的索引值### End Code Here ###
"""
函数说明:统计classList中出现此处最多的元素(类标签)
Parameters:classList - 类标签列表
Returns:sortedClassCount[0][0] - 出现此处最多的元素(类标签)
"""
def majorityCnt(classList):classCount = {}for vote in classList:                                        #统计classList中每个元素出现的次数if vote not in classCount.keys():classCount[vote] = 0   classCount[vote] += 1sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)        #根据字典的值降序排序return sortedClassCount[0][0]                                #返回classList中出现次数最多的元素
"""
函数说明:创建决策树
Parameters:dataSet - 训练数据集labels - 分类属性标签featLabels - 存储选择的最优特征标签
Returns:myTree - 决策树
"""
def createTree(dataSet, labels, featLabels):#取分类标签(是否放贷:yes or no)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]                            featLabels.append(bestFeatLabel)#根据最优特征的标签生成树myTree = {bestFeatLabel:{}}   #删除已经使用特征标签del(labels[bestFeat])                    #得到训练集中所有最优特征的属性值featValues = [example[bestFeat] for example in dataSet] #去掉重复的属性值uniqueVals = set(featValues) #遍历特征,创建决策树。for value in uniqueVals:                                                           myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), labels, featLabels)return myTreeif __name__ == '__main__':dataSet, labels = createDataSet()featLabels = []myTree = createTree(dataSet, labels, featLabels)print(myTree)
第0个特征的增益为0.083
第1个特征的增益为0.324
第2个特征的增益为0.420
第3个特征的增益为0.363
第0个特征的增益为0.252
第1个特征的增益为0.918
第2个特征的增益为0.474
{'有自己的房子': {0: {'有工作': {0: 'no', 1: 'yes'}}, 1: 'yes'}}

  递归创建决策树时,递归有两个终止条件:第一个停止条件是所有的类标签完全相同,则直接返回该类标签;第二个停止条件是使用完了所有特征,仍然不能将数据划分仅包含唯一类别的分组,即决策树构建失败,特征不够用。此时说明数据纬度不够,由于第二个停止条件无法简单地返回唯一的类标签,这里挑选出现数量最多的类别作为返回值。

【练习】使用决策树进行分类

  依靠训练数据构造了决策树之后,我们可以将它用于实际数据的分类。在执行数据分类时,需要决策树以及用于构造树的标签向量。然后,程序比较测试数据与决策树上的数值,递归执行该过程直到进入叶子结点;最后将测试数据定义为叶子结点所属的类型。在构建决策树的代码,可以看到,有个featLabels参数,它就是用来记录各个分类结点的,在用决策树做预测的时候,我们按顺序输入需要的分类结点的属性值即可。举个例子,比如用上节已经训练好的决策树做分类,那么只需要提供这个人是否有房子,是否有工作这两个信息即可,无需提供冗余的信息。
  用决策树做分类的代码很简单,编写代码如下:

# -*- coding: UTF-8 -*-"""
函数说明:使用决策树分类
Parameters:inputTree - 已经生成的决策树featLabels - 存储选择的最优特征标签testVec - 测试数据列表,顺序对应最优特征标签
Returns:classLabel - 分类结果
"""
def classify(inputTree, featLabels, testVec):### Start Code Here ####实现分类函数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    ### End Code Here ###if __name__ == '__main__':dataSet, labels = createDataSet()featLabels = []myTree = createTree(dataSet, labels, featLabels)testVec = [0,1]                                        #测试数据result = classify(myTree, featLabels, testVec)if result == 'yes':print('放贷')if result == 'no':print('不放贷')
第0个特征的增益为0.083
第1个特征的增益为0.324
第2个特征的增益为0.420
第3个特征的增益为0.363
第0个特征的增益为0.252
第1个特征的增益为0.918
第2个特征的增益为0.474
放贷

  这里只增加了classify函数,用于决策树分类。输入测试数据[0,1],它代表没有房子,但是有工作。

【练习】基于决策树预测隐形眼睛类型—使用Sklearn

  一旦理解了决策树的工作原理,我们就可以帮助人们判断需要佩戴的镜片类型。隐形眼镜数据集是非常著名的数据集,它包含很多换着眼部状态的观察条件以及医生推荐的隐形眼镜类型。隐形眼镜类型包括硬材质(hard)、软材质(soft)以及不适合佩戴隐形眼镜(no lenses)。
  数据集一共有24组数据,数据的Labels依次是age、prescript、astigmatic、tearRate、class,也就是第一列是年龄,第二列是症状,第三列是是否散光,第四列是眼泪数量,第五列是最终的分类标签。数据如下图所示:

  接下来我们来说如何使用Sklearn构建决策树。sklearn.tree模块提供了决策树模型,用于解决分类问题和回归问题。方法如下图所示:

  我们使用DecisionTreeClassifie构建决策树,这个函数共有12个参数:

参数说明如下:
  criterion:特征选择标准,可选参数,默认是gini,可以设置为entropy。gini是基尼不纯度,是将来自集合的某种结果随机应用于某一数据项的预期误差率。entropy是香农熵。
  splitter:特征划分点选择标准,可选参数,默认是best,可以设置为random。每个结点的选择策略。best参数是根据算法选择最佳的切分特征,例如gini、entropy。random随机的在部分划分点中找局部最优的划分点。默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random"。
  max_features:划分时考虑的最大特征数,可选参数,默认是None。寻找最佳切分时考虑的最大特征数(n_features为总共的特征数),有如下6种情况:      
     如果max_features是整型的数,则考虑max_features个特征;
    如果max_features是浮点型的数,则考虑int(max_features * n_features)个特征;
    如果max_features设为auto,那么max_features = sqrt(n_features);
    如果max_features设为sqrt,那么max_featrues = sqrt(n_features),跟auto一样;
    如果max_features设为log2,那么max_features = log2(n_features);
    如果max_features设为None,那么max_features = n_features,也就是所有特征都用。
  一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
  max_depth:决策树最大深,可选参数,默认是None。这个参数是这是树的层数的。层数的概念就是,比如在贷款的例子中,决策树的层数是2层。如果这个参数设置为None,那么决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。或者如果设置了min_samples_slipt参数,那么直到少于min_smaples_split个样本为止。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。
  min_samples_split:内部节点再划分所需最小样本数,可选参数,默认是2。这个值限制了子树继续划分的条件。如果min_samples_split为整数,那么在切分内部结点的时候,min_samples_split作为最小的样本数,也就是说,如果样本已经少于min_samples_split个样本,则停止继续切分。如果min_samples_split为浮点数,那么min_samples_split就是一个百分比,ceil(min_samples_split * n_samples),数是向上取整的。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
  min_samples_leaf:叶子节点最少样本数,可选参数,默认是1。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。叶结点需要最少的样本数,也就是最后到叶结点,需要多少个样本才能算一个叶结点。如果设置为1,哪怕这个类别只有1个样本,决策树也会构建出来。如果min_samples_leaf是整数,那么min_samples_leaf作为最小的样本数。如果是浮点数,那么min_samples_leaf就是一个百分比,同上,celi(min_samples_leaf * n_samples),数是向上取整的。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值   
  class_weight:类别权重,可选参数,默认是None,也可以字典、字典列表、balanced。指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。类别的权重可以通过{class_label:weight}这样的格式给出,这里可以自己指定各个样本的权重,或者用balanced,如果使用balanced,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的None。
  random_state:可选参数,默认是None。随机数种子。如果是证书,那么random_state会作为随机数生成器的随机数种子。随机数种子,如果没有设置随机数,随机出来的数与当前系统时间有关,每个时刻都是不同的。如果设置了随机数种子,那么相同随机数种子,不同时刻产生的随机数也是相同的。如果是RandomState instance,那么random_state是随机数生成器。如果为None,则随机数生成器使用np.random。
  min_impurity_split:节点划分最小不纯度,可选参数,默认是1e-7。这是个阈值,这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。
  min_weight_fraction_leaf:叶子节点最小的样本权重和,可选参数,默认是0。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。    max_leaf_nodes:最大叶子节点数,可选参数,默认是None。通过限制最大叶子节点数,可以防止过拟合。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。
  presort:数据是否预排序,可选参数,默认为False,这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。
除了这些参数要注意以外,其他在调参时的注意点有:
  1)当样本数量少但是样本特征非常多的时候,决策树很容易过拟合,一般来说,样本数比特征数多一些会比较容易建立健壮的模型。
  2)如果样本数量少但是样本特征非常多,在拟合决策树模型前,推荐先做维度规约,比如主成分分析(PCA),特征选择(Losso)或者独立成分分析(ICA)。这样特征的维度会大大减小。再来拟合决策树模型效果会好。
  3)推荐多用决策树的可视化,同时先限制决策树的深度,这样可以先观察下生成的决策树里数据的初步拟合情况,然后再决定是否要增加深度。
  4)在训练模型时,注意观察样本的类别情况(主要指分类树),如果类别分布非常不均匀,就要考虑用class_weight来限制模型过于偏向样本多的类别。
  5)决策树的数组使用的是numpy的float32类型,如果训练数据不是这样的格式,算法会先做copy再运行。
  6)如果输入的样本矩阵是稀疏的,推荐在拟合前调用csc_matrix稀疏化,在预测前调用csr_matrix稀疏化。
sklearn.tree.DecisionTreeClassifier()提供了一些方法供我们使用,如下图所示:

【练习】基于决策树预测隐形眼睛类型—编写代码

# -*- coding: UTF-8 -*-
from sklearn import tree
if __name__ == '__main__':fr = open('decision_tree_glass/lenses.txt')lenses = [inst.strip().split('\t') for inst in fr.readlines()]print(lenses)lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']clf = tree.DecisionTreeClassifier()lenses = clf.fit(lenses, lensesLabels)
[['young', 'myope', 'no', 'reduced', 'no lenses'], ['young', 'myope', 'no', 'normal', 'soft'], ['young', 'myope', 'yes', 'reduced', 'no lenses'], ['young', 'myope', 'yes', 'normal', 'hard'], ['young', 'hyper', 'no', 'reduced', 'no lenses'], ['young', 'hyper', 'no', 'normal', 'soft'], ['young', 'hyper', 'yes', 'reduced', 'no lenses'], ['young', 'hyper', 'yes', 'normal', 'hard'], ['pre', 'myope', 'no', 'reduced', 'no lenses'], ['pre', 'myope', 'no', 'normal', 'soft'], ['pre', 'myope', 'yes', 'reduced', 'no lenses'], ['pre', 'myope', 'yes', 'normal', 'hard'], ['pre', 'hyper', 'no', 'reduced', 'no lenses'], ['pre', 'hyper', 'no', 'normal', 'soft'], ['pre', 'hyper', 'yes', 'reduced', 'no lenses'], ['pre', 'hyper', 'yes', 'normal', 'no lenses'], ['presbyopic', 'myope', 'no', 'reduced', 'no lenses'], ['presbyopic', 'myope', 'no', 'normal', 'no lenses'], ['presbyopic', 'myope', 'yes', 'reduced', 'no lenses'], ['presbyopic', 'myope', 'yes', 'normal', 'hard'], ['presbyopic', 'hyper', 'no', 'reduced', 'no lenses'], ['presbyopic', 'hyper', 'no', 'normal', 'soft'], ['presbyopic', 'hyper', 'yes', 'reduced', 'no lenses'], ['presbyopic', 'hyper', 'yes', 'normal', 'no lenses']]---------------------------------------------------------------------------ValueError                                Traceback (most recent call last)<ipython-input-8-79a6415291d2> in <module>7     lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']8     clf = tree.DecisionTreeClassifier()
----> 9     lenses = clf.fit(lenses, lensesLabels)/opt/conda/lib/python3.6/site-packages/sklearn/tree/tree.py in fit(self, X, y, sample_weight, check_input, X_idx_sorted)799             sample_weight=sample_weight,800             check_input=check_input,
--> 801             X_idx_sorted=X_idx_sorted)802         return self803 /opt/conda/lib/python3.6/site-packages/sklearn/tree/tree.py in fit(self, X, y, sample_weight, check_input, X_idx_sorted)114         random_state = check_random_state(self.random_state)115         if check_input:
--> 116             X = check_array(X, dtype=DTYPE, accept_sparse="csc")117             y = check_array(y, ensure_2d=False, dtype=None)118             if issparse(X):/opt/conda/lib/python3.6/site-packages/sklearn/utils/validation.py in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, warn_on_dtype, estimator)525             try:526                 warnings.simplefilter('error', ComplexWarning)
--> 527                 array = np.asarray(array, dtype=dtype, order=order)528             except ComplexWarning:529                 raise ValueError("Complex data not supported\n"/opt/conda/lib/python3.6/site-packages/numpy/core/_asarray.py in asarray(a, dtype, order)83 84     """
---> 85     return array(a, dtype, copy=False, order=order)86 87 ValueError: could not convert string to float: 'young'

  我们可以看到程序报错了,这是为什么?因为在fit()函数不能接收string类型的数据,通过打印的信息可以看到,数据都是string类型的。在使用fit()函数之前,我们需要对数据集进行编码,这里可以使用两种方法:
  LabelEncoder :将字符串转换为增量值
  OneHotEncoder:使用One-of-K算法将字符串转换为整数
  为了对string类型的数据序列化,需要先生成pandas数据,这样方便我们的序列化工作。这里使用的方法是:原始数据->字典->pandas数据,编写代码如下:

# -*- coding: UTF-8 -*-
import pandas as pd
if __name__ == '__main__':with open('decision_tree_glass/lenses.txt', 'r') as fr:                                        #加载文件lenses = [inst.strip().split('\t') for inst in fr.readlines()]        #处理文件lenses_target = []                                                        #提取每组数据的类别,保存在列表里for each in lenses:lenses_target.append(each[-1])lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']            #特征标签       lenses_list = []                                                        #保存lenses数据的临时列表lenses_dict = {}                                                        #保存lenses数据的字典,用于生成pandasfor each_label in lensesLabels:                                            #提取信息,生成字典for each in lenses:lenses_list.append(each[lensesLabels.index(each_label)])lenses_dict[each_label] = lenses_listlenses_list = []print(lenses_dict)                                                        #打印字典信息lenses_pd = pd.DataFrame(lenses_dict)                                    #生成pandas.DataFrameprint(lenses_pd)
{'age': ['young', 'young', 'young', 'young', 'young', 'young', 'young', 'young', 'pre', 'pre', 'pre', 'pre', 'pre', 'pre', 'pre', 'pre', 'presbyopic', 'presbyopic', 'presbyopic', 'presbyopic', 'presbyopic', 'presbyopic', 'presbyopic', 'presbyopic'], 'prescript': ['myope', 'myope', 'myope', 'myope', 'hyper', 'hyper', 'hyper', 'hyper', 'myope', 'myope', 'myope', 'myope', 'hyper', 'hyper', 'hyper', 'hyper', 'myope', 'myope', 'myope', 'myope', 'hyper', 'hyper', 'hyper', 'hyper'], 'astigmatic': ['no', 'no', 'yes', 'yes', 'no', 'no', 'yes', 'yes', 'no', 'no', 'yes', 'yes', 'no', 'no', 'yes', 'yes', 'no', 'no', 'yes', 'yes', 'no', 'no', 'yes', 'yes'], 'tearRate': ['reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal', 'reduced', 'normal']}age prescript astigmatic tearRate
0        young     myope         no  reduced
1        young     myope         no   normal
2        young     myope        yes  reduced
3        young     myope        yes   normal
4        young     hyper         no  reduced
5        young     hyper         no   normal
6        young     hyper        yes  reduced
7        young     hyper        yes   normal
8          pre     myope         no  reduced
9          pre     myope         no   normal
10         pre     myope        yes  reduced
11         pre     myope        yes   normal
12         pre     hyper         no  reduced
13         pre     hyper         no   normal
14         pre     hyper        yes  reduced
15         pre     hyper        yes   normal
16  presbyopic     myope         no  reduced
17  presbyopic     myope         no   normal
18  presbyopic     myope        yes  reduced
19  presbyopic     myope        yes   normal
20  presbyopic     hyper         no  reduced
21  presbyopic     hyper         no   normal
22  presbyopic     hyper        yes  reduced
23  presbyopic     hyper        yes   normal

  从运行结果可以看出,顺利生成pandas数据。
  接下来,将数据序列化,编写代码如下:

#!pip install pydotplus
# -*- coding: UTF-8 -*-
import pandas as pd
from sklearn.preprocessing import LabelEncoder
import pydotplus
from sklearn.externals.six import StringIO
if __name__ == '__main__':with open('decision_tree_glass/lenses.txt', 'r') as fr:                                        #加载文件lenses = [inst.strip().split('\t') for inst in fr.readlines()]        #处理文件lenses_target = []                                                        #提取每组数据的类别,保存在列表里for each in lenses:lenses_target.append(each[-1])lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']            #特征标签       lenses_list = []                                                        #保存lenses数据的临时列表lenses_dict = {}                                                        #保存lenses数据的字典,用于生成pandasfor each_label in lensesLabels:                                            #提取信息,生成字典for each in lenses:lenses_list.append(each[lensesLabels.index(each_label)])lenses_dict[each_label] = lenses_listlenses_list = []# print(lenses_dict)                                                        #打印字典信息lenses_pd = pd.DataFrame(lenses_dict)                                    #生成pandas.DataFrameprint(lenses_pd)                                                        #打印pandas.DataFramele = LabelEncoder()                                                        #创建LabelEncoder()对象,用于序列化            for col in lenses_pd.columns:                                            #为每一列序列化lenses_pd[col] = le.fit_transform(lenses_pd[col])print(lenses_pd)
           age prescript astigmatic tearRate
0        young     myope         no  reduced
1        young     myope         no   normal
2        young     myope        yes  reduced
3        young     myope        yes   normal
4        young     hyper         no  reduced
5        young     hyper         no   normal
6        young     hyper        yes  reduced
7        young     hyper        yes   normal
8          pre     myope         no  reduced
9          pre     myope         no   normal
10         pre     myope        yes  reduced
11         pre     myope        yes   normal
12         pre     hyper         no  reduced
13         pre     hyper         no   normal
14         pre     hyper        yes  reduced
15         pre     hyper        yes   normal
16  presbyopic     myope         no  reduced
17  presbyopic     myope         no   normal
18  presbyopic     myope        yes  reduced
19  presbyopic     myope        yes   normal
20  presbyopic     hyper         no  reduced
21  presbyopic     hyper         no   normal
22  presbyopic     hyper        yes  reduced
23  presbyopic     hyper        yes   normalage  prescript  astigmatic  tearRate
0     2          1           0         1
1     2          1           0         0
2     2          1           1         1
3     2          1           1         0
4     2          0           0         1
5     2          0           0         0
6     2          0           1         1
7     2          0           1         0
8     0          1           0         1
9     0          1           0         0
10    0          1           1         1
11    0          1           1         0
12    0          0           0         1
13    0          0           0         0
14    0          0           1         1
15    0          0           1         0
16    1          1           0         1
17    1          1           0         0
18    1          1           1         1
19    1          1           1         0
20    1          0           0         1
21    1          0           0         0
22    1          0           1         1
23    1          0           1         0

  从打印结果可以看到,我们已经将数据顺利序列化,接下来。我们就可以fit()数据,构建决策树了。

【练习】基于决策树预测隐形眼睛类型—预测

  确定好决策树之后,我们就可以做预测了。可以根据自己的眼睛情况和年龄等特征,看一看自己适合何种材质的隐形眼镜。使用如下代码就可以看到预测结果:
print(clf.predict([[1,1,1,0]]))
  完整代码如下:

# -*- coding: UTF-8 -*-
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.externals.six import StringIO
from sklearn import tree
import pandas as pd
import numpy as np
import pydotplusif __name__ == '__main__':with open('decision_tree_glass/lenses.txt', 'r') as fr:                                        #加载文件lenses = [inst.strip().split('\t') for inst in fr.readlines()]        #处理文件lenses_target = []                                                        #提取每组数据的类别,保存在列表里for each in lenses:lenses_target.append(each[-1])print(lenses_target)lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']            #特征标签       lenses_list = []                                                        #保存lenses数据的临时列表lenses_dict = {}                                                        #保存lenses数据的字典,用于生成pandasfor each_label in lensesLabels:                                            #提取信息,生成字典for each in lenses:lenses_list.append(each[lensesLabels.index(each_label)])lenses_dict[each_label] = lenses_listlenses_list = []# print(lenses_dict)                                                        #打印字典信息lenses_pd = pd.DataFrame(lenses_dict)                                    #生成pandas.DataFrame# print(lenses_pd)                                                        #打印pandas.DataFramele = LabelEncoder()                                                        #创建LabelEncoder()对象,用于序列化           for col in lenses_pd.columns:                                            #序列化lenses_pd[col] = le.fit_transform(lenses_pd[col])# print(lenses_pd)                                                        #打印编码信息### Start Code Here ####创建DecisionTreeClassifier()对象clf = tree.DecisionTreeClassifier()#使用数据,构建决策树clf.fit(lenses_pd,lenses_target)### End Code Here ###          dot_data = StringIO()tree.export_graphviz(clf, out_file = dot_data,                            #绘制决策树feature_names = lenses_pd.keys(),class_names = clf.classes_,filled=True, rounded=True,special_characters=True)graph = pydotplus.graph_from_dot_data(dot_data.getvalue())  print(clf.predict([[1,1,1,0]]))                                            #保存绘制好的决策树,以PDF的形式存储。
['no lenses', 'soft', 'no lenses', 'hard', 'no lenses', 'soft', 'no lenses', 'hard', 'no lenses', 'soft', 'no lenses', 'hard', 'no lenses', 'soft', 'no lenses', 'no lenses', 'no lenses', 'no lenses', 'no lenses', 'hard', 'no lenses', 'soft', 'no lenses', 'no lenses']
['hard']

实验总结

  通过本实验掌握决策树算法的构建分类工作并实现基于决策树的隐形眼镜预测。

【机器学习】基于决策树的隐性眼镜选择相关推荐

  1. 【活动打卡】【Datawhale】第16期 机器学习算法梳理(AI入门体验) Task02:基于决策树的分类预测

    1.决策树的介绍和应用 1.1 决策树的介绍 决策树是一种常见的分类模型,在金融风控.医疗辅助诊断等诸多行业具有较为广泛的应用.决策树的核心思想是基于树结构对数据进行划分,这种思想是人类处理问题时的本 ...

  2. 机器学习之决策树模型最优属性选择方法

    决策树模型是用于解决分类问题的一个模型,它的特点是简答.逻辑清晰.可解释性好. 决策树是基于"树"结构进行决策的. 每个"内部结点"对应于某个属性上的" ...

  3. 机器学习算法(二):基于决策树的分类预测

    机器学习算法(二):基于决策树的分类预测 决策树的介绍和应用 简介 决策树构建的伪代码 特征划分选择 信息增益 信息增益率 基尼系数 应用场景 优缺点 基于企鹅数据集的决策树实战 Step1:函数库导 ...

  4. 机器学习算法(六):基于决策树的分类预测

    机器学习算法(六):基于决策树的分类预测 1 决策树的介绍和应用 1.1决策树的介绍 1.2 决策树的应用 2. 实验室手册 2.1 学习目标 2.2 代码流程 2.3 算法实战 2.3.1 Demo ...

  5. 【机器学习】实验1布置:基于决策树的英雄联盟游戏胜负预测

    ML_class 学堂在线<机器学习>实验课代码+报告(其中实验1和实验6有配套PPT),授课老师为张敏老师.课程链接:https://www.xuetangx.com/training/ ...

  6. 【机器学习】决策树知识点小结

    决策树原理简述 决策树是一类常见的机器学习方法,它是基于树的结构进行决策的.每次做决策时选择最优划分属性,一般而言,随着划分过程不断进行,我们希望决策树的分支节点所包含的样本尽可能属于同一个类别,即节 ...

  7. 基于决策树的多分类_R中基于决策树的糖尿病分类—一个零博客

    基于决策树的多分类 Article Outline 文章大纲 What is a decision tree?什么是决策树? Why use them?为什么要使用它们? Data Backgroun ...

  8. 基于决策树的高层次语义图像检索

    随着现代通信技Internet的广泛普及,数字图像的数量出现了急剧增长.如何从这些海量的图像数据中快速有效地找出需要的信息, 是一个非常有理论价值和实际意义的课题.从图像检索发展的历程来看,其主要经历 ...

  9. 【机器学习】决策树(Decision Tree)

    [机器学习]k近邻算法(KNN) [机器学习]决策树(Decision Tree) [机器学习]朴素贝叶斯(Naive Bayes) 一.概述 决策树(Decision Tree)是有监督学习中的一种 ...

最新文章

  1. mysql_connect 废弃_解决Deprecated: mysql_connect():
  2. vb.net2019-多线程并行计算(6)
  3. 行向量,列向量,行主序矩阵,列主序矩阵
  4. 全自动化虽然还早,但机器人劳力确实越来越便宜了
  5. memcached搭建缓存系统
  6. 影响机器视觉检测系统不稳定性因素分析
  7. Window10问题一揽子解决方案(自动唤醒,自动更新,卸载自带office16,华硕卸载myasus以及myasus频繁提示更新,停用WindowDefender)
  8. 代码制作数字流星雨_js代码实现流星雨
  9. 9种常用的数据分析方法
  10. Dorado7 文件上传
  11. windows中批量修改文件后缀名
  12. 【css】boder-sizing 中content-box与boder-box的区别
  13. 求两个数的最小公倍数和最大公因数
  14. windows易升_直播用“易升”工具升级至Windows10 2020年5月更新
  15. Android制作logo
  16. 浙大PAT 1033
  17. 基于STM32F103单片机的智能扫地机器人 循迹避障车 原理图PCB设计
  18. R语言实战应用精讲50篇(十二)-正态分布与方差齐性的检验方法与SPSS操作
  19. linux一次三行显示文件内容,Linux 命令合集(二):查看文件及内容处理命令
  20. 英雄联盟 LCUAPI

热门文章

  1. Excel导入数据下载模板示例
  2. 读取imei手机串号
  3. 如何修复ntdll.dll错误
  4. mendeley添加知网的论文
  5. 1.极限——夹逼定理_5
  6. jav1.8 Stream详解
  7. vagrant doc
  8. itunes卸载不了怎么办?如何在Mac上卸载iTunes?
  9. springboot 整合 swagger2 配置账号密码登录 demo代码
  10. HCIA-Datacom 网络技术实验指南 第2章 构建互联互通的IP网络