KNN邻近算法与python实践
来源:互联网 发布:用友数据库重装 编辑:程序博客网 时间:2024/06/05 16:56
k邻近算法(k-NearestNeighbor)又成为KNN,属于分类算法中的一种。KNN通过计算新数据与历史样本数据中不同类别数据点间的距离,从而对新数据进行分类。换句话说,就是通过新数据与最邻近的k个数据点,来对新数据进行分析和分类。
环境:mac + python3.6.3(另外需要的第三方库请自行下载)
python KNN算法原理demo代码如下:
from numpy import *from PIL import Imageimport operatorfrom os import listdirimport timeimport os# 图片处理# pillow# 将bmp格式的图片转化为只有0和1的txt文本,这样就有了训练数据了def transformAllBmp2Txt(): rootdir = "手写体素材" list = os.listdir(rootdir) # 列出文件夹下所有的目录与文件 time1 = time.time() for i in range(0, len(list)): path = os.path.join(rootdir, list[i]) if os.path.isdir(path): # 具体某个文件夹下的所有文件与目录 path_dir = os.listdir(path) for index in range(0, len(path_dir)): # 好吧,这里做一层保护 file = os.path.join(path, path_dir[index]) if os.path.isfile(file): bmp2txt(file) time2 = time.time() print("总共耗时:" + str(time2 - time1))def bmp2txt(file): im = Image.open(file) fileSplit = file.split("/") # dir = "transdata/" + fileSplit[1] + "/" dir = "transdata/" if os.path.exists(dir) == False: os.makedirs(dir) destination_file = dir + fileSplit[2].split(".")[0] + ".txt" fh = open(destination_file, "a") width = im.size[0] height = im.size[1] # print("图片的模式为:" + im.mode) # 此bmp模式为L,模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白 for i in range(0, width): for j in range(0, height): cl = im.getpixel((i, j)) if (cl == 0): # 黑色,由于选择的bmp背景色是黑色,所以默认的是黑色 fh.write("0") else: fh.write("1") fh.write("\n") fh.close() print(destination_file + "保存成功。。。")# 从列方向扩展# tile(a,(size,1))def knn(k, testdata, traindata, labels): # testdata:一维数组[0,0,1,……] # traindata:二维数组[[0,0,1……],[],] # labels:一维列表,跟traindata一一对应 # 以下shape取的是训练数据的第一维,即其行数,也就是训练数据的个数 traindatasize = traindata.shape[0] dif = tile(testdata, (traindatasize, 1)) - traindata # tile()的意思是给一维的测试数据转为与训练数据一样的行和列的格式 sqdif = dif ** 2 # axis=1-----》横向相加的意思 sumsqdif = sqdif.sum(axis=1) # sumsqdif在此时已经成为1维的了 distance = sumsqdif ** 0.5 sortdistance = distance.argsort() # sortdistance为测试数据到各个训练数据的距离按近到远排序之后的结果 count = {} for i in range(0, k): vote = labels[sortdistance[i]] # sortdistance[i]测试数据最近的K个训练数据的下标 # vote测试数据最近的K个训练数据的类别 count[vote] = count.get(vote, 0) + 1 sortcount = sorted(count.items(), key=operator.itemgetter(1), reverse=True) return sortcount[0][0]# 加载数据def datatoarray(fname): arr = [] fh = open(fname) # 28表示图片像素中的宽和高,比如我这里的图片是28*28的像素,转成txt文本就是28行*28列 for i in range(0, 28): thisline = fh.readline() for j in range(0, 28): arr.append(int(thisline[j])) return arr# 建立一个函数取文件名前缀,为了验证用def seplabel(fname): filestr = fname.split(".")[0] label = int(filestr.split("_")[0]) return label# 建立训练数据def traindata(): labels = [] trainfile = listdir("traindata") num = len(trainfile) print("文件的总数为:" + str(num)) # 长度784(列),每一行存储一个文件 # 用一个数组存储所有训练数据,行:文件总数,列:784 # 28*28=784 trainarr = zeros((num, 784)) for i in range(0, num): thisfname = trainfile[i] thislabel = seplabel(thisfname) labels.append(thislabel) trainarr[i, :] = datatoarray("traindata/" + thisfname) return trainarr, labels# 用测试数据调用KNN算法去测试,看是否能够准确识别def datatest(): n1 = 0 n2 = 0 time1 = time.time() trainarr, labels = traindata() testlist = listdir("testdata") tnum = len(testlist) # print(trainarr) for i in range(0, tnum): n1 += 1 thistestfile = testlist[i] testarr = datatoarray("testdata/" + thistestfile) thislabel = seplabel(thistestfile) rknn = knn(3, testarr, trainarr, labels) print(rknn) if (thislabel == rknn): n2 += 1 time2 = time.time() print("耗时:" + str(time2 - time1) + "秒") print("准确率:" + str(n2 / n1))# #抽某一个测试文件出来进行试验# trainarr,labels=traindata()# thistestfile="a.txt"# testarr=datatoarray("testdata/"+thistestfile)# #print(testarr)# rknn=knn(3,testarr,trainarr,labels)# print(rknn)datatest()# ------------------------------------------------------python算法原理结束-------------------------------------------------------
完整代码在python_study/w7-罗小辉-380226205/test_knn.py中,运行test_knn.py即可。
阅读全文