二 python-knn

knn 的学习

1 概述

knn算法采用测量不同特征值之间的距离进行分类
它的过程如下:
(1)确定采用的距离公式,如欧式距离Lp距离等
(2)计算训练集样本和当前样本的距离
(3)确定k值,挑选距离最近的k个数据样本
(4)确定这k个样本的类别,出现频率最高的类别作为预测样本的类别(投票)

2 分类过程实现

def classify0( inX, dataSet , labels , k):
    dataSetSize=dataSet.shape[0] #确定训练集数量

    #欧式距离计算
    diffMat=tile(inX,(dataSetSize,1))-dataSet #将输入样本构造为对应行数的矩阵
    sq=diffMat**2 
    sqsum=sq.sum(axis=1) 
    distances=sqsum**0.5 


    sortDistances=distances.argsort()  #从小到大 元素 的索引 列表
    classCount={}
    for i in range(k): #提取k个最近样本对应的类别
        label=labels[sortDistances[i]] 
        classCount[label]=classCount.get(label,0)+1
    #print(classCount.items())
    sortClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #找到投票最多的类别
    return sortClassCount[0][0]

3 数据归一化

有时候计算距离时,由于特征的量级不同,对距离大小的影响不同,为了让影响程度相同,需要对每个训练集的每个特征进行归一化,将他们转化到统一量级

这里实现最大最小值的数据归一化:

#各特征重要性相同
#特征归一化
def autoNorm(group):
    minvals=group.min(0)
    maxvals=group.max(0)
    newgroup=zeros(group.shape)
    numrow=group.shape[0]
    newgroup=group-tile(minvals,(numrow,1))
    ranges=maxvals-minvals
    newgroup=newgroup/tile(ranges,(numrow,1))
    return newgroup,ranges,minvals

4 knn实现手写数字数据的分类

准备好手写数字数据集trainingDigits,testDigits

from knn import *
from os import listdir
from numpy import *
#确定训练集的目录
mydir=listdir('trainingDigits')

#将网格的图像数据变换为 1*1024 矩阵形式
def fig2num(filename):
    f=open(filename)
    filelist=zeros((1,1024))
    line=f.readlines()
    for i in range(len(line)):
        for j in range(32):
            filelist[0,i*32+j]=int(line[i][j])
    return filelist

#输入所有训练数据
num=len(mydir)
dataset=zeros((num,1024))
labels=[]
for i in range(num):
    filelist=fig2num('trainingDigits/%s' %(mydir[i]))
    labels.append(int(mydir[i].split('_')[0])) #根据文件名确定数字类别
    dataset[i,:]=filelist[:]

#输入测试数据
testdir=listdir('testDigits')
testnum=len(testdir)
testset=zeros((testnum,1024))
reallabels=[]
for i in range(testnum):
    filelist=fig2num('testDigits/%s' %(testdir[i]))
    reallabels.append(int(testdir[i].split('_')[0]))
    testset[i,:]=filelist[:]

errorcount=0
#对每个训练数据进行分类  此时 K 的值为3
for i in range(testnum):
    result=classify0(testset[i,:],dataset,labels,3) 
    if result !=reallabels[i]:
        errorcount+=1
        print(testdir[i],'real class: ',reallabels[i],'come back with:',result,'False') 
    else:
        print(testdir[i],'real class: ',reallabels[i],'come back with:',result)

print('error number:',errorcount)
print('error rate:',errorcount/float(testnum))

对k进行分析,采用不同的k值,发现错误率的变化

for k in range(1,5):
    errorcount=0
    for i in range(testnum):
        result=classify0(testset[i,:],dataset,labels,k) 
        if result !=reallabels[i]:
            errorcount+=1
    print('k=',k,'error number:',errorcount)
    print('k=',k,'error rate:',errorcount/float(testnum))
k= 1 error number: 13
k= 1 error rate: 0.013742071881606765
k= 2 error number: 13
k= 2 error rate: 0.013742071881606765
k= 3 error number: 10
k= 3 error rate: 0.010570824524312896
k= 4 error number: 11
k= 4 error rate: 0.011627906976744186

其中k=3时,错误率最低,因此knn采取k=3对手写数字数据进行分类

5 优缺点

优点:
(1)当k值取合适的值时,精度比较高
(2)因为是分析最近的k个数据,因此对异常点不敏感
缺点:
(1)计算时间复杂度和空间复杂度都很高,

猜你喜欢

转载自blog.csdn.net/qq_35282560/article/details/79535672