k-邻近算法

k-邻近算法是一种测量不同特征值之间距离来进行分类的一种算法。

該算法的优点是精度高,对异常的特征值不敏感,但是缺点也很明显,计算的复杂度高,计算空间复杂度也比较高。

 k邻近算法就是 通过计算 目标点的特征值 与样本点的特征值 前k个距离最小的样本点的类别中概率最大的一个就是目标点的类别。

如上图 若取前10个与C距离最小的点,那么这前10个点中属于集合A必定大于属于集合B的,那么就可以得出C的应该按集合A分类。

  该算法也存在缺陷,比如在样本数量不足的情况下。比如上图的集合A只有一个点,那么10个最近的点中有9个都会是属于集合B,

得出不可靠的结论,在一个缺点就是该算法需要将目标与大量样本计算比较才能得出前k个最近的样本,计算量大。

  接下来完成一个同个KNN算法实现识别数字的例子:

样本是类似如下图的32*32的数据,下面是0,4,5

 

下面通过一个dataPrepare函数来将上面形式的数据转换成1*1024的向量(32*32 = 1024), trainDataMat函数将目录下的样本全部转换为一个m*1024的矩阵

 1 def dataPrePare(filename):
 2     ReturnVect = zeros((1,1024))
 3     file = open(filename)
 4     for i in range(32):
 5         Rowdata = file.readline()
 6         for j in (32):
 7             ReturnVect[0, 32 * i + j] = Rowdata[j]
 8     return ReturnVect
 9 
10 
11 # 将目录下的样本数据转换为矩阵
12 def trainDataMat(filenamePath):
13     filenameList = listdir(filenamePath)
14     TrainMat = zeros((len(filenameList), 1024))
15     DataLabel = []
16     for i in range(len(filenameList)):
17         filename = filenameList.split('.')[0] # 样本文件的名称 例如 0_9.txt 表示 数字为0 的第9个样本
18         DataLabel.append(int(filename.split('_')[0]))
19 
20         TrainMat[i, :] = DataToMat(filenamePath + '\\' + filename)
21 
22     return TrainMat, DataLable

 分类函数 knnClassify

 1 #ClassifyTarget 待分类目标 TrainMatData 训练样本 LableMat 训练样本标签 K 前K个根据特征值计算出距离的最小距离样本
 2 def knnClassify(ClassifyTarget, TrainMatData, LableMat, k):
 3     RowCount_TrainDataMat = TrainMatData.shape[0] # 训练样本矩阵行数
 4     ClassifyTarget_Mat = tile(ClassifyTarget, (RowCount_TrainDataMat, 1))
 5     diffmat = ClassifyTarget_Mat - TrainMatData #带分类目标与训练样本作差
 6     sqdiff_mat = diffmat**2 #每行每个元素取平方
 7     sqdistance_mat = sqdiff_mat.sum(axis = 1)# 每行相加
 8     distance_mat = sqdistance_mat **0.5 #特征值 距离矩阵
 9     sortindex = distance_mat.argsort() #距离从小到达排列 返回其索引数组
10 
11     labelcount_dict = {}
12 
13     for i in range(k):
14         labelcount_dict[LableMat[sortindex[i]]] = labelcount_dict.get(LableMat[sortindex[i]], 0) + 1 # 各个标签计数
15 
16     Return_dict = sorted(labelcount_dict.items(), key=operator.itemgetter(1), reverse=True) #得到次数最多的标签
17     return Return_dict[0][0] #返回 分类值 

 完整代码

# _*_ coding=utf-8
from numpy import *
import operator

def dataPrePare(filename):
    returnVect = zeros((1,1024)) #初始化一个全为0的1*1024向量
    file = open(filename)
    for i in range(32):
        rowline = file.readline()
        for j in range(32):
            returnVect[0,32*i + j] = int(rowline[j])
    return returnVect

def trainDataMat(DataPath):
    trainlable = []
    trainfilelist = listdir(DataPath)
    DataCount = len(trainfilelist) #获取训练数据数量 在该路径下的文件都是训练数据
    trainMat = zeros((DataCount, 1024))
    for i in range(DataCount):
        filename = trainfilelist[i]
        filenamestr = filename.split('.')[0]
        ClassNumint = int(filenamestr.split('_')[0])
        trainlable.append(ClassNumint)
        trainMat[i, :] = dataPrePare(DataPath + '/%s'% filename)
    return trainMat, trainlable

#ClassifyTarget 待分类目标 TrainMatData 训练样本 LableMat 训练样本标签 K 前K个根据特征值计算出距离的最小距离样本
def knnClassify(ClassifyTarget, TrainMatData, LableMat, k):
    RowCount_TrainDataMat = TrainMatData.shape[0] # 训练样本矩阵行数
    ClassifyTarget_Mat = tile(ClassifyTarget, (RowCount_TrainDataMat, 1))
    diffmat = ClassifyTarget_Mat - TrainMatData #带分类目标与训练样本作差
    sqdiff_mat = diffmat**2 #每行每个元素取平方
    sqdistance_mat = sqdiff_mat.sum(axis = 1)# 每行相加
    distance_mat = sqdistance_mat **0.5 #特征值 距离矩阵
    sortindex = distance_mat.argsort() #距离从小到达排列 返回其索引数组
    labelcount_dict = {}
    for i in range(k):
        labelcount_dict[LableMat[sortindex[i]]] = labelcount_dict.get(LableMat[sortindex[i]], 0) + 1
        Return_dict = sorted(labelcount_dict.items(), key=operator.itemgetter(1), reverse=True)
    return Return_dict[0][0] #返回 分类值


if __name__ == '__main__':
    TargetMat = dataPrePare('XXXXXX.txt')#待分类目标路径
    TrainDataMat, TrainDataLabel = trainDataMat('xxxxx') #用于分类的样本路径
    ClassifyResult = knnClassify(TargetMat, TrainDataMat, TrainDataLabel, 10)
    print(ClassifyResult)
    pass

 

          总结:KNN是分类最简单的最有效的算法,但是 需要大量的样本,导致需要的存储空间大,耗时长

 

转载于:https://www.cnblogs.com/FMS-Shaw/p/8546263.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值