1、KNN思想
KNN就是K最近邻,是一种分类算法,意思是选k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。在k个样本中,比重最大的那一类即可把目标归为这一类。
优点:不用训练
缺点:该算法在分类时有个主要的不足是,当样本不平衡时,K临近占比概率影响结果、计算量大
2、KNN如何实现手写字体的识别
①数据处理(图片处理为数字文本)
②待测图片与训练集每一张图片的向量做欧氏距离
③排序,选取最优K,使得结果最好
3、数据处理
①01文本转换图像
[python]
- #coding:utf-8
- import os
- from PIL import Image
- '''''
- ①两个文件夹,一个存储数字文件、一个存储图像文件
- ②读取src文件夹下的文件名,统计个数
- ③src+文件名=每个数字txt的路径,读取其内容
- ④写入图片,保存图片
- 注意:
- ①目标文件夹只能是最后一层不存在,才能创建
- ②python于java/c的区别,路径分割/刚好相反
- ③数字文件为01序列
- ④putpixel((列,行))
- '''
- def fun(src,dst):
- #判断源文件夹是否存在,不存在结束
- if not os.path.exists(src):
- return
- # 判断目标文件夹是否存在,不存在创建一个
- if not os.path.exists(dst):
- os.mkdir(dst)
- #读取src文件中的文件名
- list=os.listdir(src)
- length=len(list)
- for i in range(length):
- #文件路径
- path=src+"/"+list[i];
- #读取文件内容
- read=open(path)
- #保存路径
- SavePath=dst+"/"+list[i][:-4]+".png"
- #写入图片,并保存,图片是32*32
- image =Image.new("L",(32,32))
- for j in range(32):
- line=read.readline()
- for k in range(32):
- bit=int(line[k])
- if bit ==1:
- bit=255
- image.putpixel((k,j),bit)
- image.save(SavePath)
- srcPath="C:/Users/Administrator/Desktop/src"
- dstPath="C:/Users/Administrator/Desktop/dst"
- fun(srcPath,dstPath)
②图片转换成01文本
[python]
- #coding:utf-8
- import os
- from PIL import Image
- import numpy as np
- '''''
- Python图像处理库PIL的基本概念介绍”,我们知道PIL中有九种不同模式。
- 分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。
- 模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白
- 模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
- 模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。
- '''
- def fun(src,dst):
- if not os.path.exists(src):
- return
- if not os.path.exists(dst):
- os.mkdir(dst)
- list=os.listdir(src)
- length=len(list)
- for i in range(length):
- path=src+'/'+list[i]
- SavePath=dst+'/'+list[i][:-4]+".txt"
- read=Image.open(path).convert("1")
- arr=np.asarray(read)
- np.savetxt(SavePath,arr,fmt="%d",delimiter='') #保存格式为整数,没有间隔
- #np.savetxt(SavePath, arr,fmt="%d")
- src="C:/Users/Administrator/Desktop/src"
- dst="C:/Users/Administrator/Desktop/dst"
- fun(src,dst)
4、具体实现
数据已经由图片处理为文本,且文本中像素点之间没有间隔。把每张图片处理为一个向量,32*32=1024。计算欧氏距离的时候也有技巧,不用遍历训练集一个一个与待测图片计算,可以利用np.title(),复制待测图片达到和训练集个数,直接矩阵相减。排序也有技巧,为了是每张图片和标签一一对应,排序的时候使用argsort(),统计众数的时候使用了字典,排序时候用sorted().
[python]
- #coding:utf-8
- import os
- import numpy as np
- import operator
- '''''
- ①难点:计算欧氏距离并排序,确定k值,这里k=3最优
- ②图片都处理为数字文本,文本中没有空格
- ③字典排序,排序后变为[(),()]形式
- '''
- #价值数据
- def Load(src):
- if not os.path.exists(src):
- return
- list=os.listdir(src)
- length=len(list)
- label=[]
- train=[]
- for i in range(length):
- path=src+"/"+list[i]
- read=open(path)
- temp = []
- for j in range(32):
- line=read.readline()
- for k in range(32):
- bit=int(line[k])
- temp.append(bit)
- train.append(temp)
- label.append(int(list[i][0]))
- train=np.array(train)
- return train,label
- def Classifier(train,laber,testPath,KK):
- list=os.listdir(testPath)
- length=len(list)
- errorCount=0
- for i in range(length):
- #数据处理
- path=testPath+"/"+list[i]
- #实际值
- ok=int(list[i][0])
- read=open(path)
- test=[]
- for j in range(32):
- line=read.readline()
- for k in range(32):
- bit=int(line[k])
- test.append(bit)
- #计算欧氏距离,不需要遍历,技巧
- m=train.shape[0]
- test=np.tile(test,(m,1))
- sum=train-test #对应相减
- sum=sum**2 #平方
- sum=np.sum(sum,axis=1) #行求和
- sum=sum**0.5 #开方
- # 排序,返回下标
- sum=np.argsort(sum)
- #前k个,取最大类
- ans={}
- for j in range(KK):
- lab=label[sum[j]] #下标对应的标签
- if lab in ans.keys():
- ans[lab]=ans[lab]+1
- else:
- ans[lab] = 1
- ans=sorted(ans.items(),key=operator.itemgetter(1),reverse=True)
- print ("实际值=",ok,"预测值=",ans[0][0])
- if ok != ans[0][0]:
- errorCount += 1.0
- print("错误总数:%d" % errorCount)
- print("错误率:%f" % (errorCount / length))
- trainPath="C:/Users/Administrator/Desktop/src"
- testPath="C:/Users/Administrator/Desktop/dst"
- #训练集处理
- train,label=Load(trainPath)
- #测试集处理
- Classifier(train,label,testPath,3)
总结:
①文件夹判断是否存在?文件夹创建?文件夹下所有文件名的读取?文本读取?
②图像的创建?图像像素点的填充?图像的保存?图像读取?文本的写入?
③欧氏距离的计算?title()的使用?argsort()的使用?字典的排序sorted()?
④如何确定最优K?遍历K,针对每个k计算错误率。
[python]
- def selectK():
- x = list()
- y = list()
- for i in range(1, 5):
- x.append(int(i))
- y.append(错误数)
- plt.plot(x, y)
- plt.show()
登录 | 立即注册