1、KNN思想
KNN就是K最近邻,是一种分类算法,意思是选k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。在k个样本中,比重最大的那一类即可把目标归为这一类。
优点:不用训练
缺点:该算法在分类时有个主要的不足是,当样本不平衡时,K临近占比概率影响结果、计算量大
2、KNN如何实现手写字体的识别
①数据处理(图片处理为数字文本)
②待测图片与训练集每一张图片的向量做欧氏距离
③排序,选取最优K,使得结果最好
3、数据处理
①01文本转换图像
#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文本
#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().
#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计算错误率。
def selectK():
x = list()
y = list()
for i in range(1, 5):
x.append(int(i))
y.append(错误数)
plt.plot(x, y)
plt.show()
源码+数据下载