前言
最近学习了K-近邻算法,而K-近邻算法非常实用于图形图像的分类问题,因此使用了sklearn中内置的的KNeighborsClassifier类完成了一个车牌号识别的小项目,记录一下遇到的问题以及收获。
算法思想
KNN(K- Nearest Neighbor)法即K最邻近法,最初由 Cover和Hart于1968年提出,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。K-近邻算法是指在一个样本空间中,寻找到距离最近的k个邻居,按照这些邻居的样本属性来划分当前样本属性,思路十分简单,其中也有许多优化的策略如使用KdTree、ballTree等数据结构来减少算法运行的时间,而KNeighborsClassifier类中的内置方法已经预先封装好了这些数据结构,可以直接使用,非常方便。
数据分析以及预处理
这次实验用到的数据是如下图所示的一个个图像文件,首先要将其读取出来,并抽象为numpy矩阵。
#读取图片label函数
def readFileIndex(filepath):
lables = dict()
filetype = '.jpg'
for i in range(0,65):#因为有0-64个类别
str1 = str(i)
filepath1 = os.path.join(filepath,str1)#读取文件夹
for root,dirs,files in os.walk(filepath1):
for j in files:
if filetype+' 'in j+' ':
str1 = str(i)+'/'+j
lables[str1] = i
return lables
labels字典中存储了的是文件名和文件所属类别一一对应的关系集合
#读取所有图片函数,返回两个列表
def readFileContent(lables,flag):
X = []
Y = []
for lableName in lables:#取出每一个路径进行读取
filename = lableName
if(flag == 1):#判断是训练集文件夹还是测试集文件夹
pict = readPict(filename)
else:
pict = readPict('./'+filename)
X.append(pict)
Y.append(lables[filename])
return X,Y
#图片文件读取函数,返回一个一维的数组
def readPict(path):
returanVec=np.zeros(400)
img = Image.open(path)
pixel = np.array(img)#此时为二维矩阵,将其转为一维,方便运行算法拟合
for i in range(20):
for j in range(20):
returanVec[i*20+j]=pixel[i][j]
return returanVec
此时要返回一个一维数组,使X的维度控制为2,因为已知图像的像素点为20*20,所以用一个简单的转换函数将其转为一维。
算法模型构建
from sklearn.neighbors import KNeighborsClassifier
neigh = KNeighborsClassifier(weights = 'distance')
neigh.fit(X_train,Y_train)
print(neigh.score(X_test,Y_test))
0.7016077170418007
此时利用sklearn中的KNN算法进行拟合,关键字weights是指利用距离和权重成反比的计算方式,可以去除一定的误判情况。
最后,附上K在5-10内(默认为5)的准确率走向图
下面是K在5-70内准确率走向图