写的很粗糙,以后实现了具体的算法再改进内容
———————————————————————————————————————————————
k近邻算法:
概述:
优点:
1、精度高,对异常值不敏感,无数据输入假定
缺点:计算复杂高,空间复杂高
适用数据范围:数值型与标称型
原理:存在一个样本数据集合,并且样本集中每个数据都存在标签
对于输入没有标签的新数据,把新数据的每个特征与样本集中数据对应的特征进行比较
算法提取样本集中特征最相似 的数据(最近邻)分类标签
always 只选择k个最相似数据中出现次数最多的分类,作为新数据的分类
k近邻算法的一般流程:
1、收集数据:any way
2、准备数据:距离计算所需要的数值,最好是结构化的数据格式
3、分析数据:any way
4、测试算法:计算错误率
5、使用算法:首先需要输入样本数据和结构化输出结果,然后运行k近邻算法判定输入数据分别属于哪个类,最后应用对计算出的分类执行后续处理
算法思路:
对未知类别属性数据集:
1、计算已知类别数据集中的点和当前点之间的距离
2、按照距离递增次序排序
3、选取与当前距离最小的k个点
4、确定前k个点所在类别的出现频率
5、返回前k个点出现频率最高的类别作为当前点的预测分类
分类器的测试:
错误率,用于评估分类器在某个数据集上的执行效果
需要了解数据的真实含义,一般会采用图形化的方式直观展示数据
2.2.2 分析数据:使用matplotlib创建散点图
可以变色:更好的辨识数据
2.2.3
准备数据:进行数值的归一化
是为了减少个体数值数字差值大对属性计算结果影响大的问题;
2.2.4
测试算法:作为完整程序验证分类器
————————————————————————————————————————————-
总步骤:
读取数据,进行特征值归一化
计算测试向量的数量,将两部分数据输入到原始knn分类器函数中
最后计算错误率实现结果输出。
————————————————————————————————————————————
数据集量很大,必须使用大量的存储空间
必须对数据集中每个数据计算距离值,使用时候很耗时间
无法知晓平均实例样本和典型实例样本特征
下面是简单实例:k近邻算法实现手写数字验证
数据集来自http://archive.ics.uci.edu/ml手写识别的数据(手写数字数据集的光学识别)
数据集和代码传到gitHub上去了!下载数据集点我
实现步骤:
1、处理图像数据,转化为向量(img2vector)
2、对数据进行提取,通过文件名提取数据向量对应的数字标签,获得一个“训练集”
3、对于“测试集”里的每一条向量,获得对应的数字标签 然后调用classify0函数使用knn算法进行向量距离的计算→通过排序获得前k个最小的结果→统计最小结果集里数字出现的概率→返回概率最高的结果作为分类答案
4、计算错误率
具体实现代码如下:
import numpy import matplotlib from os import listdir import numpy as np import operator #将图片转换为向量 def img2vector(filename): returnVect=np.zeros((1,1024)) #生成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 #单条数据(测试数据),“训练”数据集,对应训练数据集的数字标签,选前k个参数 def classify0(testData,dataSet,labels,k): dataSetSize = dataSet.shape[0] diffMat = np.tile(testData,(dataSetSize ,1))-dataSet #使用欧氏距离公式计算距离 sqDiffMat = diffMat**2 sqDistances = sqDiffMat.sum(axis = 1) #axis=1:按行计算(计算和) distances=sqDistances**0.5 sortedDistIndicies = distances.argsort() #argsort()将distances中的数据从小到大排列,然后返回其对应由下标组成的list classCount = {} #选择距离最小的k个点,这里k=3 for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] #找到差值对应下标 在labels中对应的数据标签是多少 classCount[voteIlabel]=classCount.get(voteIlabel,0) +1 #通过hash的方式统计结论标签出现的次数 #排序 print(classCount) sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse = True) return sortedClassCount[0][0] def handwritingClassTest(): hwLabels = [] #获取目录的内容 trainingFileList = listdir('trainingDigits') m_len = len(trainingFileList) trainingMat = np.zeros((m_len,1024)) for i in range(m_len): fileNameStr=trainingFileList[i] #通过文件名获得数据 对应的数字 fileStr = fileNameStr.split('.')[0] classNumStr = int(fileStr.split('_')[0]) hwLabels.append(classNumStr) trainingMat[i,:] = img2vector('trainingDigits/%s' %fileNameStr) # print(trainingMat[i][0:32]) # print(hwLabels) # print(trainingMat.size) testFileList = listdir('testDigits') errorCount =0.0 mTest_len = len(testFileList) for i in range(mTest_len): fileNameStr = testFileList[i] #获取数据集文件名字 fileStr = fileNameStr.split('.')[0] classNumStr = int(fileStr.split('_')[0]) #找到其对应是什么数据 vectorUnderTest = img2vector('testDigits/%s'%fileNameStr) classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3) print("判断的数字是%d,而其真实数字是%d"%(classifierResult,classNumStr)) if(classifierResult!=classNumStr):errorCount += 1.0 print("判断错误的实例有%d个" % errorCount) print("错误率是%f" % (errorCount / float(mTest_len))) def main(): handwritingClassTest() if __name__ == '__main__': main()