k近邻法没有显示的学习过程,无模型
找到K个最近点后,使用多数表决(即投票)的方式确定预测点的类别
距离度量:
预测过程中直接遍历预测点与所有点的距离,并找到最近的K个点即可。找到K个最近点后,使用多数表决(即投票)的方式确定预测点的类别。
K近邻算法缺点:
1、在预测样本类别时,待预测样本需要与训练集中所有样本计算距离,当训练集数量过高时(例如Mnsit训练集有60000个样本),每预测一个样本都要计算60000个距离,计算代价过高,尤其当测试集数目也较大时(Mnist测试集有10000个)。
KD树:
查找最近领点方法优化
''' 数据集:Mnist 训练集数量:60000 测试集数量:实际使用:100 ------------------------------ 运行结果:(邻近k数量:25) 向量距离使用算法——欧式距离 正确率:0.98 运行时长:108.94 ''' import numpy as np import time from tqdm import tqdm def loadData(fileName): ''' 加载Mnist数据集 :param fileName:要加载的数据集路径 :return: list形式的数据集及标记 ''' print('start to read data') data = [] label = [] fr = open(fileName, 'r') for line in fr.readlines(): curLine = line.strip().split(',') # if int(curLine[0]) >= 5: # label.append(1) # else: # label.append(-1) label.append(int(curLine[0])) data.append([int(num)/255 for num in curLine[1:]]) return data, label # 向量之间的欧式距离 def calcDist(x1, x2): return np.sqrt(np.sum(np.square(x1 - x2))) def getClosest(trainDataMat, trainLabelMat, x, topK): ''' :param trainDataMat:训练集数据集 :param trainLabelMat:训练集标签集 :param x:要预测的样本x :param topK:选择参考最邻近样本的数目(样本数目的选择关系到正确率,详看3.2.3 K值的选择) :return:预测的标记 ''' distList = [0] * len(trainLabelMat) for i in range(len(trainDataMat)): x1 = trainDataMat[i] curDist = calcDist(x1, x) distList[i] = curDist topKList = np.argsort(np.array(distList))[:topK] #升序排序 labelList = [0] * 10 for index in topKList: labelList[int(trainLabelMat[index])] += 1 return labelList.index(max(labelList)) def test(trainDataArr, trainLabelArr, testDataArr, testLabelArr, topK): ''' 测试正确率 :param trainDataArr:训练集数据集 :param trainLabelArr: 训练集标记 :param testDataArr: 测试集数据集 :param testLabelArr: 测试集标记 :param topK: 选择多少个邻近点参考 :return: 正确率 ''' print('start test') #将所有列表转换为矩阵形式,方便运算 trainDataMat = np.mat(trainDataArr); trainLabelMat = np.mat(trainLabelArr).T testDataMat = np.mat(testDataArr); # 10000,784 testLabelMat = np.mat(testLabelArr).T # 10000,1 #错误值技术 errorCnt = 0 #测试100个样本点,时间比较长,没有实现kd树 for i in tqdm(range(100)): x = testDataMat[i] y = getClosest(trainDataMat, trainLabelMat, x, topK) if y != testLabelMat[i]: errorCnt += 1 # print("y: {}, testLabelMat[i]{}".format(y, testLabelMat[i])) return 1 - (errorCnt / 100) if __name__ == "__main__": start = time.time() #获取训练集 trainDataArr, trainLabelArr = loadData('../Mnist/mnist_train.csv') #获取测试集 testDataArr, testLabelArr = loadData('../Mnist/mnist_test.csv') #计算测试集正确率 accur = test(trainDataArr, trainLabelArr, testDataArr, testLabelArr, 25) #打印正确率 print('accur is:%d'%(accur * 100), '%') end = time.time() #显示花费时间 print('time span:', end - start)