鸢尾花数据集(KNN、决策树、朴素贝叶斯分析)

目录

1、问题描述

2、数据准备与数据预处理

2.1 收集数据

2.2划分数据集

3、数据可视化

4、模型基本原理与算法实现

4.1 KNN算法基本原理及主程序

4.2决策树模型算法及基本原理

4.3朴素贝叶斯算法及基本原理

5、测试方法与结果

5.1KNN测试结果

5.2决策树测试结果

5.3朴素贝叶斯测试结果

6.总结

7.问题

1、问题描述
iris是鸢尾植物,这里存储了其萼片和花瓣的长宽,共4个属性,鸢尾植物分三类。假定现在出现了一株鸢尾植物,如何通过其所具有的特征来推断出它属于三类中的哪一类?这就是机器学习中的分类问题了。该数据集一共包含4个特征变量,1个类别变量。共有150个样本,鸢尾有三个亚属,分别是山鸢尾 (Iris-setosa),变色鸢尾(Iris-versicolor)和维吉尼亚鸢尾(Iris-virginica)。

2、数据准备与数据预处理
2.1收集数据
在本次问题过程中,所使用的是一个较经典的数据集,所以在scikit-learn的数据库中可以找到。也可以在UCI数据集上下载完成。

image.png

数据集一共分为四个变量,分别为:花萼长度、花萼宽度、花瓣长度、花瓣宽度

image.png

2.2划分数据集
从上面对样本集的输出我们可以看出Iris数据集给出的三种花是按照顺序来的,前50个是第0类,51-100是第1类,101~150是第二类,如果我们分训练集和测试集的时候要把顺序打乱。在这里我们选取120个为训练集,30个为测试集。为实现随机性,选取三个部分的每部分的最后十组数据作为测试集元素。

train_data = np.concatenate((iris.data[0:40, :], iris.data[50:90, :], iris.data[100:140, :]), axis = 0)  #训练集  
 
train_target = np.concatenate((iris.target[0:40], iris.target[50:90], iris.target[100:140]), axis = 0)  #训练集样本类别  
 
test_data = np.concatenate((iris.data[40:50, :], iris.data[90:100, :], iris.data[140:150, :]), axis = 0)  #测试集  
 
test_target = np.concatenate((iris.target[40:50], iris.target[90:100], iris.target[140:150]), axis = 0) #测试集样本类别  

3.数据可视化
由于花瓣宽度变化很小,将其省略后根据前三维数据画出散点图,如下所示:

image.png

4、模型基本原理与算法实现
4.1算法基本原理及主程序
k近邻法是一种基本的多分类和回归的算法,给定一个训练数据集,对新的输入实例,在数据集中找到与该实例最近邻的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类。kNN的三要素是k,距离度量和分类决策规则。

第一步,计算输入实例和数据集各个数据的欧氏距离。
第二步,将计算的距离按照从小到大排序,统计前k个数据的类别,这里假设k为3,则前3个距离最近的数据类为AAB。
第三步,将输入实例判断为频率最高的类,本例中A的频率最高(为2),即输入实例是A类数据。

以下为主程序段:

def kNN(x, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    distance1 = tile(x, (dataSetSize,1)) - dataSet #欧氏距离计算开始
    distance2 = distance1 ** 2 #每个元素平方
    distance3 = distance2.sum(axis=1) #矩阵每行相加
    distance4 = distance3 ** 0.5 #欧氏距离计算结束
    sortedIndex = distance4.argsort() #返回从小到大排序的索引
    classCount = {}
    for i in range (k): #统计前k个数据类的数量
        label = labels[sortedIndex[i]]
        classCount[label] = classCount.get(label,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) #从大到小按类别数目排序
    return sortedClassCount[0][0]

4.2决策树模型算法及基本原理
决策树是一个属性结构的预测模型,代表对象属性和对象值之间的一种映射关系。它又节点和有向边组成,其节点有两种类型:内节点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类。决策树的学习本质上是从训练集中归纳出一组分类规则,得到与数据集矛盾较小的决策树,同时具有很好的泛化能力。决策树学习的损失函数通常是正则化的极大似然函数,通常采用启发式方法,近似求解这一最优化问题。

决策树学习算法包含特征选择、决策树生成与决策树的剪枝。决策树表示的是一个条件概率分布,所以深浅不同的决策树对应着不同复杂程度的概率模型。决策树的生成对应着模型的局部选择(局部最优),决策树的剪枝对应着全局选择(全局最优)。决策树常用的算法有ID3,C4.5,CART。

为了计算信息增益,引入熵的概念,通过计算香农熵来将数据集划分不同的类别。

程序段:


def calcShannonEnt(dataSet):
       numEntries = len(dataSet)
    labelCounts = {}
    for featVec in dataSet:
        currentLabel = featVec[-1]
        if currentLabel not in labelCounts.keys(): 
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key]) / numEntries
        shannonEnt -= prob * log(prob,2) # 以2为底的对数
    return shannonEnt

 

  在计算了信息增益后,应选择最好的数据集划分方式,在这里选择ID3算法进而绘制决策树。

  

def chooseBestFeatureToSplitByID3(dataSet):#选择最好的数据集划分方式
    umFeatures = len(dataSet[0]) - 1 
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0
    bestFeature = -1
    for i in range(numFeatures):  # 遍历所有特征
        infoGain = calcInformationGain(dataSet, baseEntropy, i)     # 计算信息增益
        if (infoGain > bestInfoGain):  # 选择最大的信息增益
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature  
def majorityCnt(classList):# 采用多数表决的方法决定叶结点的分类
    classCount={}
    for vote in classList:                         if vote not in classCount.keys():
            classCount[vote] = 0
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) 
    return sortedClassCount[0][0]
 
def createTree(dataSet,labels):#创建决策树
    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 = chooseBestFeatureToSplitByID3(dataSet)   
    bestFeatLabel = labels[bestFeat]
    myTree = {bestFeatLabel:{}}         
    del(labels[bestFeat])
    featValues = [example[bestFeat] for example in dataSet]
    uniqueVals = set(featValues)
    for value in uniqueVals:
        subLabels = labels[:]       
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
    return myTree

4.3朴素贝叶斯算法及基本原理
朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。朴素贝叶斯分类的核心算法如下:

image.png

那么现在的关键就是如何计算第3步中的各个条件概率。我们可以这么:

1、已知分类的待分类项集合,这个集合叫做训练样本

2、统计得到在各类别下各个特征属性的条件概率估计。

3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:

image.png

因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:
image.png

为朴素贝叶斯的工作流程图:

image.png

5、测试方法与结果

5.1测试结果
对150个鸢尾花样本进行随机分割后,选取了其中的30个作为测试集,120个作为训练集,再计算他们的准确率、召回率和F值。结果如下:


image.png

看出准确率在93%,召回率为90%,说明是一次较为成功的训练。

5.2决策树测试结果

image.png

看出在决策树训练的样本中,30组测试集完全正确,但这有可能是由以下原因造成的:

1、测试集和训练集数目都太少,在数值上可能并不太符合要求。

2、决策树本身算法易出现过拟合的现象,需要注意。

绘制结果如下:


image.png

5.3朴素贝叶斯测试结果
本次作业中关于应用朴素贝叶斯方法进行分类和测试,我是使用了sklearn中自带的分类器,并应用了其中两种相关算法。分别是:多项式朴素贝叶斯和高斯朴素贝叶斯

结果如下:

image.png

可以看出,两种朴素贝叶斯的相关算法在此训练集上都有较好的应用。

6.总结
通过本次学习,我了解到决策树学习算法包含特征选择、决策树的生成与剪枝过程。决策树易于理解和实现,人们在在学习过程中不需要使用者了解很多的背景知识,这同时是它的能够直接体现数据的特点,只要通过解释后都有能力去理解决策树所表达的意义,非常直观。但是从此次实验的结果可以看出,30个测试样本全部正确,决策树算法非常容易过拟合,可以通过设置节点最少样本数量和限制决策树深度来改进。

而KNN算法是一种简单,易于理解,易于实现,无需估计参数,无需训练的方法,但是它的缺点是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。如需改变其准确率可以通过改变其k值来进行测试,找到最优的分类方法。

朴素贝叶斯朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。对缺失数据不太敏感,算法也比较简单,常用于文本分类。但是需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。

7.问题
1、如何解决决策树中的过拟合问题?

2、朴素贝叶斯方法“对输入数据的表达形式很敏感”是什么意思?

3、如何最优选择KNN算法中的K?

注:本文所使用的为64位系统,Python3.64版本,其中导入了与scikit-learn相关的数据包例如:DecisionTreeClassifier、sklearn.externals.six、pydot等。

本文部分程序参考:

CSDN论坛

Python机器学习基础教程——人民邮电出版社

Python编程从入门到实践——人民邮电出版社

机器学习实战——人民邮电出版社

你可能感兴趣的:(鸢尾花数据集(KNN、决策树、朴素贝叶斯分析))