您现在的位置是:首页 >技术杂谈 >K近邻算法(手写代码+图像识别实践)网站首页技术杂谈

K近邻算法(手写代码+图像识别实践)

羊咩咩咩咩咩 2023-06-11 08:00:02
简介K近邻算法(手写代码+图像识别实践)

        k近邻算法作为一个分类算法,他通过计算不同特征值之间的距离来进行分类,它的工作原理是存在一个样本集合作为训练样本集,且每个样本都存在一个标签,此时,输入一个新的样本不存在标签,我们通过计算这个新样本到这些训练样本集的距离,找出k个最靠近的样本,再对这些样本的标签进行统计,数量最多的则为新样本的标签。

        这里的距离可以有很多,曼哈顿距离,欧式距离等等,后面的代码都使用欧氏距离,K-NN的伪代码如下:

(1)计算所有已知类别的数据集中的点到新的点的距离。

(2)按照距离进行排序。

(3)选取k个与新的点距离最小的k个点。

(4)计算k个点所在类别的频率。

(5)返回k个点出现频率最高的类别作为当前点的预测分类

下面进行实现:

def distance(target,dataset):
    length =dataset.shape[0]
    distances=[]
    for i in range(length):
        diff=0
        for j in range(dataset[i].shape[0]):
            diff += (dataset[i][j]-target[j])**2
            distance =diff**0.5
        distances.append(distance)
    return distances
            

        这里是计算了目标点target到数据集内所有点的距离,并保存在distances的列表中。

def sort_choose_k(distance,labels,k):
    index =distance.argsort()##选取从小到大排序的索引值
    class_count={}
    for i in range(k):
        vote =labels[index[i]]
        class_count[vote] =class_count.get(vote,0)+1##这里使用了get方法,利用键来获取值,然后get()方法两个参数,第一个为键,第二个为初值
    sorted_class_count = sorted(class_count.items(),key=operator.itemgetter(1),reverse=True)
    return sorted_class_count[0][0]
        

        这里是对距离集进行排序,并选择出前k个。这里得argsort()函数作用于array类型,效果是将数组类型的数据进行升序排序后的索引值进行返回。这里的get()函数适用于dict类型,其中第一个参数为输入的键,后面那个参数为给键的初值。这里的itemgetter()方法是operator运算符模块自带的方法,这里是按照第二个元素的次序对元祖进行排序。

        这样子就完成了K-NN算法建立,下面看一下例子。

        这里例子是通过k临近算法来改进约会网站的配对效果。

        (1)从文本文件中解析数据

        这里是从txt文件转换成numpy类型

def turn_to_numpy(file):
    returnmat=[]
    labels=[]
    with open(file=file) as f:
        for line in f.readlines():
            line=line.strip()
            line=line.split('	')
            returnmat.append(line[0:3])
            labels.append(line[-1])
    returnmat=np.array(returnmat)
    labels =np.array(labels)
    return returnmat,labels
returnmat=returnmat.astype('float')

        这里是通过readlines()方法读取每一行的数据,然后去除空格和左右两边的分隔符,存储在returnmat以及labels中。

        这里我们观看数据会发现数据的差异很大,这里需要使用归一化来使数据大小变得统一。其公式为frac{(target-min)}{max-min}。有了公式就方便我们用代码所实现。

def guiyihua(dataset,target):
    min_set =dataset.min(axis=0)
    max_set=dataset.max(axis=0)
    diff = max_set-min_set
    num = dataset.shape[0]
    diff_set =np.tile(diff,(num,1))
    min_num_set =np.tile(min_set,(num,1))
    norm_returnmat =(target-min_num_set)/diff
    return norm_returnmat,diff,min_num_set

        然后针对数据进行测试。

def datingclasstest():
    hoRadio=0.1
    datingDataMat,datingLabels =turn_to_numpy(file)
    datingDataMat =datingDataMat.astype('float')
    normmat,ranges,diff =guiyihua(datingDataMat,datingDataMat)
    m=normmat.shape[0]
    numtestvecs =int(m*hoRadio)
    errorCount=0.0
    for i in range(numtestvecs):
        classifierresult =sort_choose_k(np.array(distance(normmat[i,:],normmat[numtestvecs:m,:])),datingLabels[numtestvecs:m],3)
        print("the classifieer came back with {} ,the real answer is :{}".format(classifierresult,datingLabels[i]))
        if (classifierresult !=datingLabels[i]):
            errorCount+=1.0
        print("the total error rate is;{}".format(errorCount/float(numtestvecs)))

        这里显示错误率为0.05,其实还不错,然后我们用手写数据再来测试一下。

        数据的预处理

import numpy as np
def img2vector(filename):
    returnvect =np.zeros((1,1024))
    fr =open(filename)
    for i in range(32):
        linestr =fr.readline()
        for j in range(32):
            returnvect[0,32*i+j] =int(linestr[j])
    return returnvect

         这一步将32×32的数据转换为1×1024,这样子就可以让分类器进行处理。

        然后进行测试。

import os
import operator
def handwritingtest():
    hwlabels=[]
    trainingfilelist=os.listdir('trainingDigits')
    m=len(trainingfilelist)
    trainingmat=np.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(r'trainingDigits{}'.format(filenamestr))
    testfilelist =os.listdir('testDigits')
    errorCount=0.0
    mtest=len(testfilelist)
    for i in range(mtest):
        filenamestr=testfilelist[i]
        filestr=filenamestr.split('.')[0]
        classnumstr =int(filestr.split('_')[0])
        vectorundertest=img2vector(r'testDigits{}'.format(filenamestr))
        classifierresult=classify0(vectorundertest,trainingmat,hwlabels,3)
        print("the classifier came back with:{},the real answer is:{}".format(classifierresult,classnumstr))
        if(classifierresult!=classnumstr):
            errorCount+=1.0
    print("the total error rate is:{}".format(errorCount/float(mtest)))

        这样子就完成了K近邻算法的手写以及测试

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。