zoukankan      html  css  js  c++  java
  • KNN分类算法

                      

    原理:近朱者赤,近墨者黑

    一 . K-近邻算法(KNN)概述 

        最简单最初级的分类器是将全部的训练数据所对应的类别都记录下来,当测试对象的属性和某个训练对象的属性完全匹配时,便可以对其进行分类。但是怎么可能所有测试对象都会找到与之完全匹配的训练对象呢,其次就是存在一个测试对象同时与多个训练对象匹配,导致一个训练对象被分到了多个类的问题,基于这些问题呢,就产生了KNN。

         KNN是通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

         下面通过一个简单的例子说明一下:如下图,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。

     

    由此也说明了KNN算法的结果很大程度取决于K的选择。

         在KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,避免了对象之间的匹配问题,在这里距离一般使用欧氏距离或曼哈顿距离:

                          

    同时,KNN通过依据k个对象中占优的类别进行决策,而不是单一的对象类别决策。这两点就是KNN算法的优势。

       接下来对KNN算法的思想总结一下:就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:

    1)计算测试数据与各个训练数据之间的距离;

    2)按照距离的递增关系进行排序;

    3)选取距离最小的K个点;

    4)确定前K个点所在类别的出现频率;

    5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

    二 .python实现

    首先呢,需要说明的是我用的是python3.4.3,里面有一些用法与2.7还是有些出入。

    建立一个KNN.py文件对算法的可行性进行验证,如下:

     
    #coding:utf-8
    
    from numpy import *
    import operator
    
    ##给出训练数据以及对应的类别
    def createDataSet():
        group = array([[1.0,2.0],[1.2,0.1],[0.1,1.4],[0.3,3.5]])
        labels = ['A','A','B','B']
        return group,labels
    
    ###通过KNN进行分类
    def classify(input,dataSe t,label,k):
        dataSize = dataSet.shape[0]
        ####计算欧式距离
        diff = tile(input,(dataSize,1)) - dataSet
        sqdiff = diff ** 2
        squareDist = sum(sqdiff,axis = 1)###行向量分别相加,从而得到新的一个行向量
        dist = squareDist ** 0.5
        
        ##对距离进行排序
        sortedDistIndex = argsort(dist)##argsort()根据元素的值从大到小对元素进行排序,返回下标
    
        classCount={}
        for i in range(k):
            voteLabel = label[sortedDistIndex[i]]
            ###对选取的K个样本所属的类别个数进行统计
            classCount[voteLabel] = classCount.get(voteLabel,0) + 1
        ###选取出现的类别次数最多的类别
        maxCount = 0
        for key,value in classCount.items():
            if value > maxCount:
                maxCount = value
                classes = key
    
        return classes    
     

    接下来,在命令行窗口输入如下代码:

    #-*-coding:utf-8 -*-
    import sys
    sys.path.append("...文件路径...")
    import KNN
    from numpy import *
    dataSet,labels = KNN.createDataSet()
    input = array([1.1,0.3])
    K = 3
    output = KNN.classify(input,dataSet,labels,K)
    print("测试数据为:",input,"分类结果为:",output)

    回车之后的结果为:

    测试数据为: [ 1.1  0.3] 分类为: A

    答案符合我们的预期,要证明算法的准确性,势必还需要通过处理复杂问题进行验证。

    三、通过sklearn对数据使用KNN算法进行分类

    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from sklearn import neighbors
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    ## 导入鸢尾花数据集
    iris = datasets.load_iris()
    data = iris.data[:, :2]
    target = iris.target
    
    ## 区分训练集和测试集,75%的训练集和25%的测试集
    train_data, test_data = train_test_split(np.c_[data, target])
    ## 训练并预测,其中选取k=15
    clf = neighbors.KNeighborsClassifier(15, 'distance')
    clf.fit(train_data[:, :2], train_data[:, 2])
    Z = clf.predict(test_data[:, :2])
    print('准确率:', clf.score(test_data[:, :2], test_data[:, 2]))
    
    colormap = dict(zip(np.unique(target), sns.color_palette()[:3]))
    plt.scatter(train_data[:, 0], train_data[:, 1], edgecolors=[colormap[x] for x in train_data[:, 2]], c='', s=80,
                label='all_data')
    plt.scatter(test_data[:, 0], test_data[:, 1], marker='^', color=[colormap[x] for x in Z], s=20, label='test_data')
    plt.legend()
    plt.show()

    结果如下:

    摘自:https://www.cnblogs.com/ybjourney/p/4702562.html

  • 相关阅读:
    前端笔试题目总结——应用JavaScript函数递归打印数组到HTML页面上
    HTM5新增结构化元素&非结构化元素&新增属性详解
    HTML 5 与HTML 4 的区别
    HTML5框架、背景和实体、XHTML的使用规范
    百度前端笔试题目--css 实现一个带尖角的正方形
    HTML5表单提交和PHP环境搭建
    HTML5列表、块、布局
    HTML5 格式化、样式、链接、表格
    2020-09-13助教一周总结(第二周)
    2020-09-10上课小结
  • 原文地址:https://www.cnblogs.com/catxjd/p/14016087.html
Copyright © 2011-2022 走看看