1.常见的分类算法:
(1).KNN算法
(2).贝叶斯算法
(3).决策树算法
(4)人工神经网络算法
(5)支持向量机(SVM)算法
2.今天我们用KNN算法解决手写体数字的识别问题(包括验证码识别,二维码识别等都可以归属为同一类问题)
KNN算法又名K-近邻算法,总体思想是:通过把现实中的数据映射到坐标系,然后通过计算"点"之间的距离(欧几里得公式)sqr[(x1-xm)**2+(y1-ym)**2]
可以翻译成如下步骤:
(1).计算欧式距离
(2).按照递增顺序排位
(3).选取与当前距离最小的K个点
(4).确定前K个点所在的类的出现频率
(5)返回前K个点出现频率最高的类别作为当前点的预测分类
3.算法实现步骤:
(1)处理数据
(2)数据向量化
(3)计算欧几里得距离
(4)根据距离分类
4.KNN算法优点:
(1).简单、易实现、易理解,无需参数估计及训练
(2).适用于多分类问题
(3).总的思想是:"物以类聚"
KNN算法模块:
#KNN算法模块:
def knn(k,testdata,traindata,labels):
#k代表分类数,测试数据,训练数据,所得到的测试结果属于哪一类(labels)
traindata.shape[0]
#shape返回两个参数(数组),shape[0]得到训练集行数
dif=np.tile(testdata,(traindata,1))-traindata
#利用numpy中的tile扩展维数后,才能进行计算,列数确定一直,扩展行(行扩展一直,列不变)
sqdif=dif**2
#对差值的每个元素取平方
sumsqdif=sqdif.sum(axis=1)
#按行进行计算,得到列向量组,axis=0则得到的是行向量
distance=sumsqdif**0.5
sortdistance=distance.argsort()
#按照升序去排
count={} #建立一个空字典
for i in range(0,k):
vote=labels[sortdistance[i]]
count[vote]=count.get(vote,0)+1
#get(5,0)+1,意思是在count字典中出现一次vote值,则对应加1{5:1,,,},多次循环累加
sortcount=sorted(count.items(),key=operator.itemgetter(1),reverse=True)
#排序依据字典中的第一个词去排序,默认是升序(False)
#key指定依据哪个区排,operator.itemgeter(1)指定第一个元素去排
return sortcount[0][0]
手写体字体的识别(数字、图片、二维码、验证码(1-26个字母)等与此类似):
手写体--->拍照--->标准化(设定长和宽的像素大小)--->转文本--->加载数据--->训练数据---用测试数据调用KNN算法去测试,看是否能够清晰识别。
1.首先将手字体字体拍照保存为图片,并将其标准化处理(长和宽设定固定高度比如32*32等)
2.转化为文本数据
3.读取每个像素
处理图像模块:
#处理图像模块
from PIL import Image
from os import listdir
#import numpy as np
im=Image.open("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie.jpg")
fh=open("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie.txt","a")
#im.save("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie2.png")
width=im.size[0] #im.size 获得宽和高的像素,返回两个参数,第一个为width(宽)(行对应宽),,第二个像素为height
height=im.size[1]
#获取图片像素的颜色
#k=im.getpixel((1,9))
#print(k)
for i in range(0,width):
for j in range(0,height):
cl=im.getpixel((i,j))
c1all=cl[0]+cl[1]+cl[2]
if(c1all==0):
#黑色
fh.write("1")
else:
fh.write("0")
fh.write("\n")
fh.close()
加载数据模块:
#加载数据(traindata)模块,定义一个加载函数
def datatoarray(fname):
arr=[]
fh=open(fname)
for i in range(0,32):
thisline=fh.readline()
for j in range(0,32):
arr.append(int(thisline[j]))
return arr
arr1=datatoarray("C:/Users/Administrator/Desktop/pandashesuanfa/0_8.txt")
'''建立一个seplabel函数取文件名前缀'''
def seplabel(fname):
filestr=fname.split(".")[0] #通过"."作为分隔符,并取第一个元素
label=int(filestr.split("_")[0]) #再通过"_"下划线分割,得到第一个元素
return label
测试训练数据模块:
#测试训练数据模块
def traindata():
labels=[]
trainfile=listdir("D:/shujufenxi/traindata") #listdir函数读取当前文件夹下所有的文件名,得到的是一个列表
num=len(trainfile)
'''#c长度为1024(列),每一行存储一个文件
#用一个数组存储所有训练数据,行:文件总数,列:1024'''
trainarr=np.zeros((num,1024))
for i in range(0,num):
thisfname=trainfile[i] #此时得到的是一个文件
#需要取文件的前缀(163.txt),建立seplabel函数
thislabel=seplabel(thisfname)
labels.append(thislabel)
trainarr[i,:]=datatoarray("traindata/"+thisfname) #调用datatoarray函数读取当前所有文件
return trainarr,labels
#建立测试函数,用测试数据调用KNN算法去测试,看能否准确识别
def datatest():
trainarr,labels=traindata() #调用函数,加载训练集
testlist=listdir("tesdata") #得到测试集数据
tnum=len(testlist)
'''批量识别'''
for i in range(0,tnum):
thistestfile=testlist[i]
testarr=datatoarray("testdata/"+thistestfile)
rknn=knn(3,testarr,trainarr,labels)
print(rknn)
datatest()
'''抽取某一个测试文件出来进行试验'''
'''
thistestfile=testlist[i]
testarr="3_58.txt"
rknn=knn(3,testarr,trainarr,labels)
print(rknn)
'''
完整代码如下:
# -*- coding: utf-8 -*-
#KNN手写体数字的识别
#C:/Users/Administrator/Desktop/pandashesuanfa/shouxie.jpg
#KNN算法及手写体字体的识别
'''
算法实现步骤:
1.处理数据
2.数据向量化
3.计算欧几里得距离
4.根据距离分类
'''
import numpy as np
import operator
def knn(k,testdata,traindata,labels): #k代表分类数,测试数据,训练数据,所得到的测试结果属于哪一类(labels)
traindata.shape[0] #shape返回两个参数(数组),shape[0]得到训练集行数
dif=np.tile(testdata,(traindata,1))-traindata #利用numpy中的tile扩展维数后,才能进行计算,列数确定一直,扩展行(行扩展一直,列不变)
sqdif=dif**2 #对差值的每个元素取平方
sumsqdif=sqdif.sum(axis=1) #按行进行计算,得到列向量组,axis=0则得到的是行向量
distance=sumsqdif**0.5
sortdistance=distance.argsort() #按照升序去排
count={} #建立一个空字典
for i in range(0,k):
vote=labels[sortdistance[i]]
count[vote]=count.get(vote,0)+1 #get(5,0)+1,意思是在count字典中出现一次vote值,则对应加1{5:1,,,},多次循环累加
sortcount=sorted(count.items(),key=operator.itemgetter(1),reverse=True) #排序依据字典中的第一个词去排序,默认是升序(False)
#key指定依据哪个区排,operator.itemgeter(1)指定第一个元素去排
return sortcount[0][0]
'''
手写字体数字识别思路
1.首先将手字体字体拍照保存为图片,并将其标准化处理(长和宽设定固定高度比如32*32等)
2.转化为文本数据
3.读取每个像素
'''
#处理图像模块
from PIL import Image
from os import listdir
#import numpy as np
im=Image.open("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie.jpg")
fh=open("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie.txt","a")
#im.save("C:/Users/Administrator/Desktop/pandashesuanfa/shouxie2.png")
width=im.size[0] #im.size 获得宽和高的像素,返回两个参数,第一个为width(宽)(行对应宽),,第二个像素为height
height=im.size[1]
#获取图片像素的颜色
#k=im.getpixel((1,9))
#print(k)
for i in range(0,width):
for j in range(0,height):
cl=im.getpixel((i,j))
c1all=cl[0]+cl[1]+cl[2]
if(c1all==0):
#黑色
fh.write("1")
else:
fh.write("0")
fh.write("\n")
fh.close()
"""加载数据(traindata),定义一个函数"""
def datatoarray(fname):
arr=[]
fh=open(fname)
for i in range(0,32):
thisline=fh.readline()
for j in range(0,32):
arr.append(int(thisline[j]))
return arr
arr1=datatoarray("C:/Users/Administrator/Desktop/pandashesuanfa/0_8.txt")
'''建立一个seplabel函数取文件名前缀'''
def seplabel(fname):
filestr=fname.split(".")[0] #通过"."作为分隔符,并取第一个元素
label=int(filestr.split("_")[0]) #再通过"_"下划线分割,得到第一个元素
return label
'''建立训练数据'''
def traindata():
labels=[]
trainfile=listdir("D:/shujufenxi/traindata") #listdir函数读取当前文件夹下所有的文件名,得到的是一个列表
num=len(trainfile)
'''#c长度为1024(列),每一行存储一个文件
#用一个数组存储所有训练数据,行:文件总数,列:1024'''
trainarr=np.zeros((num,1024))
for i in range(0,num):
thisfname=trainfile[i] #此时得到的是一个文件
#需要取文件的前缀(163.txt),建立seplabel函数
thislabel=seplabel(thisfname)
labels.append(thislabel)
trainarr[i,:]=datatoarray("traindata/"+thisfname) #调用datatoarray函数读取当前所有文件
return trainarr,labels
#建立测试函数,用测试数据调用KNN算法去测试,看能否准确识别
def datatest():
trainarr,labels=traindata() #调用函数,加载训练集
testlist=listdir("tesdata") #得到测试集数据
tnum=len(testlist)
'''批量识别'''
for i in range(0,tnum):
thistestfile=testlist[i]
testarr=datatoarray("testdata/"+thistestfile)
rknn=knn(3,testarr,trainarr,labels)
print(rknn)
datatest()
'''抽取某一个测试文件出来进行试验'''
'''
thistestfile=testlist[i]
testarr="3_58.txt"
rknn=knn(3,testarr,trainarr,labels)
print(rknn)
'''
关注思路,以及KNN算法的应用是重点