kNN算法及实现 python

  1. 原理

测量不同特征值之间的距离来进行分类

优点:精度高,对异常值不敏感,无数据输入假定

缺点:计算复杂度高,空间复杂度高

适用数据类型:数值型,标称型

2.  面试题

  • knn三要素:k值选择;距离度量(欧式距离,马氏距离);分类决策规则(多数表决规则)
  • k值选择:k值越小模型越复杂,更容易过拟合;k值越大,模型越简单,当k=N时,无论什么样本都会属于训练集中类别最多的那个类
  • 优缺点 优点:思想简单,理论成熟,既可以分类又可以回归;可用于非线性分类;时间复杂度为O(n);准确率高,对数据没有假设,对异常值不敏感 缺点:计算量大;样本不平衡问题;需要大量内存
  • kd树,存储数据,快速计算距离,并且在数据量大的时候可以只计算部分数据的距离(后面详细补充)

3. 实现

算法流程:

  • 收集数据
  • 准备数据:距离计算需要数值,结构化的数据格式
  • 分析数据
  • 测试算法:计算错误率
  • 使用算法

算法实现(算法伪代码):使用k近邻算法将每组数据划分到某个类中:

  1. 对每个数据一次进行以下操作:
  2. 计算已知类别数据集中的点与当前点之间的距离;
  3. 按照距离递增次序排序;
  4. 选取与当前点距离最小的k个点;
  5. 确定前k个点所在类别的出现频率;
  6. 返回前k个点出现频率最高的类别作为当前点的预测分类。

4.项目练习

手写体识别

from numpy import *
import os
import operator
#将图片转换成向量
#knn算法,通过计算距离,来进行分类
def classify0(inX,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]
    diffMat= tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5  #计算欧式距离
    sortedDistIndicies = distances.argsort()  #排序
    classCount={}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]
def img2vector(filename):
    returnVect=zeros((1,1024))  #返回32*32=1024维向量
    fr = open(filename)
    for i in range(32):  #读取每一行
        linsStr = fr.readline()
        for j in range(32):
            returnVect[0,32*i+j]=int (linsStr[j])  #依次按列存储  按行不行吗?
    return returnVect

def handwritingTest():
    hwLabels = []
    trainingFileList = os.listdir('trainingDigits')
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
    testFileList = os.listdir('testDigits')
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        testMat= img2vector('trainingDigits/%s' % fileNameStr)
        calssifierResult = classify0(testMat,trainingMat,hwLabels,4)
        print("the classifer came back with :%d, the real answer is %d" %(calssifierResult,classNumStr))

        if calssifierResult!=classNumStr:
            errorCount+=1
    print("\n the total number of errors is :%d" %errorCount)
    print("\n the total errors rate is :%f" %(errorCount/float(mTest)))
handwritingTest()
扫描二维码关注公众号,回复: 5743841 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_32799915/article/details/82192457
今日推荐