【机器学习】基于决策树的隐形眼镜选择

2023-10-25 18:40

本文主要是介绍【机器学习】基于决策树的隐形眼镜选择,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验介绍

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

决策树构建---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)                        #保存每个标签(Label)出现次数的字典labelCounts = {}                       #对每组特征向量进行统计for featVec in dataSet:               #提取标签(Label)信息currentLabel = featVec[-1]#如果标签(Label)没有放入统计次数的字典,添加进去if currentLabel not in labelCounts.keys():    #如果标签(Label)没有放入统计次数的字典,添加进去labelCounts[currentLabel] = 0#Label计数labelCounts[currentLabel] += 1                          #经验熵(香农熵)shannonEnt = 0.0                     #计算香农熵for key in labelCounts:#选择该标签(Label)的概率prob = float(labelCounts[key]) / numEntires #利用公式计算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]#创建set集合{},元素不可重复uniqueVals = set(featList)#经验条件熵newEntropy = 0.0#计算信息增益for value in uniqueVals:#subDataSet划分后的子集subDataSet = splitDataSet(dataSet, i, value)#计算子集的概率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-11-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']

实验总结

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

这篇关于【机器学习】基于决策树的隐形眼镜选择的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/284476

相关文章

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss