700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > KNN——简单手写体识别

KNN——简单手写体识别

时间:2022-01-23 18:41:39

相关推荐

KNN——简单手写体识别

用到的库及函数解释

1.numpy:

NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

numpy.zeros(shape, dtype = float, order = 'C')

创建指定大小的数组,数组元素以 0 来填充

ndarray.shape

表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。

a = np.array([[1,2,3],[4,5,6]]) print (a.shape)#输出为(2,3) 是一个列表,即二行三列#a.shape[0]为2,表示2行#a.shape[1]为3,表示3列

numpy.tile(A,(m,n))

将数组A作为元素构造m行n列的数组

array.sum(axis=1)按行累加,axis=0为按列累加

argsort():

得到矩阵中每个元素的排序序号,A=array.argsort() A[0]表示排序后 排在第一个的那个数在原来数组中的下标

x=np.array([1,4,3,-1,6,9])

x.argsort()

输出定义为y=array([3,0,2,1,4,5])。

我们发现argsort()函数是将x中的元素从小到大排列提取其对应的index(索引),然后输出到y

2.OS

os模块提供了非常丰富的方法用来处理文件和目录

os.listdir(path)

os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表(包括文件后缀名txt等)。这个列表以字母顺序排序

3.数组切片[:,i] [i:j:k] [:-i] [i,j,:k]

逗号“,”分隔各个维度,“:”表示各个维度内的切片,只有:表示取这个维度的全部值

一维数组:略

二维数组:

X[:,0] 取所有行的第0个数据,第二维下标位0的所有数据,第0列(从0开始,实际是第一列)

X[:,1] 所有行,第1列(实际是第二列)

X[:,1:]第一维全部取,即所有行,列上从第一列开始取,不要第0列

X[1,:] 取第一行,所有列

X[:2,1:]第一维取下标2之前的,即第2行之前(0,1两行),列上从第一列开始取,不要第0列

4.字典中的方法

dict.get(key, default=None)

1. 先定义字典

>>>dict = {'A':1, 'B':2}

2. 当key值存在于dict.keys()中时,调用get()方法,返回的是对应的value值

>>>print(dict.get('A')) #输出为1

3. 当key值不存在于dict.keys()中时,调用get()方法,返回的是None

>>>print(dict.get('C')) #返回值为None

4. 当default = x时,若key值存在于dict.keys()时,返回dict[key];若不存在于dict.keys()中时,返回x

>>>print(dict.get('A', 0))>>>1>>>print(dict.get('C', 0))>>>0

注意:dict.get(key,0)可用于计数,并将键值保存在词典中。

F:\KNN\classify0_9.py

import numpy as npimport operatorimport osdef img2vec(filename):'''将32*32的样本图片转化为1*1024(1行1024列)的特征向量filename指图片的文件名,如3_3.txt'''return_vec = np.zeros((1, 1024)) ## 创建1*1024的0填充向量矩阵fl = open(filename)for i in range(32): # 读取文件的前32行,前32列省略开头,即i从0到32line_str = fl.readline() #每次读一行的值for j in range(32): #二层循环将32*32的值放入return_vec数组中return_vec[0, 32*i+j] = int(line_str[j])return return_vec # 返回每个图像的向量def handwriting_class():'''训练集有10*10个图片,每个图片32*32将训练集图片合并到100*1024的大矩阵每行对应一个图片'''handwriting_labels = [] #存储手写体类别training_list = os.listdir('trainingDigits') ## 获取目录内容,返回训练集文件名列表m = len(training_list)training_vec = np.zeros((m, 1024)) #创建训练集矩阵,每行数据存储一个图像#将训练集图片合并到矩阵中for i in range(m):file = training_list[i] #命名格式:1_3.txtfilename = file.split('.')[0] #以.切割后得到1_3class_label = int(filename.split('_')[0]) #以_切割得到1,即标签(类别)handwriting_labels.append(class_label)training_vec[i, :] = img2vec('trainingDigits/'+file) ## 调用函数,每遍历一个文件就处理为二维数组中的一行#逐一读取测试图片,并将其分类test_list = os.listdir('testDigits') #创建存放测试集图片的列表error_count = 0.0 # 错误个数m_test = len(test_list)for i in range(m_test):file = test_list[i]filename = file.split('.')[0]class_label = int(filename.split('_')[0])#测试图片转化为矩阵test_vec = img2vec('testDigits/'+file)classify_result = classify(test_vec, training_vec, handwriting_labels, 3)print('\n真实值:' + str(class_label) + '预测结果为:'+ str(classify_result))if classify_result != class_label:error_count += 1.0print('\n出现错误个数:' + str(error_count))print('\n错误率为:' + str(error_count/float(m_test)))def classify(test_data, train_data, labels, k):"""对未知类别属性的数据集中的每个点依次执行一下操作:(1)计算已知类别数据集中的点与当前点之间的距离 (2)按照距离递增次序排序 (3)选取与当前点距离最小的k个点 (4)确定前k个点所在类别的出现频数 (5)返回当前k个点出现频数最高的类别作为当前点的预测分类"""# shape[0]得到训练集的行数,即样本个数train_data_num = train_data.shape[0]'''以下为距离计算 '''"""tile函数:tile(A,(m,n))将数组A作为元素构造m行n列的数组将输入向量变成和训练数据一样的形状例如:输入向量为[1.2, 1],训练数据为:[[1.0, 1.1],[1.0, 1.0],[ 0, 0],[ 0, 0.1]]变换后为:[[1.2, 1],[1.2, 1],[1.2, 1],[1.2, 1]]"""diff_vec = np.tile(test_data,(train_data_num, 1)) - train_datasqdiss_vec = diff_vec**2sq_distances = sqdiss_vec.sum(axis = 1) # array.sum(axis=1)按行累加求和,axis=0为按列累加distances = sq_distances**0.5'''计算完所有点之间的距离后,可以对数据按照从小到大的次序排序。然后,确定前k个距离最小元素所在的主要分类 ,输入k总是正整数;最后,将classCount字典分解为元组列表,然后使用程序第二行导入运算符模块的itemgetter方法,按照第二个元素的次序对元组进行排序 。此处的排序为逆序,即按照从最大到最小次序排序,最后返回发生频率最高的元素标签。'''# 计算完所有点之间的距离后,可以对数据按照从小到大的次序排序,得到在原数组中的下标列表sorted_dist_indicies = distances.argsort() # 返回数组值从小到大的索引class_count = {} # 创建一个字典,用于记录每个实例对应的频数#确定前k个距离最小元素所在的主要分类for i in range(k):vote_lable = labels[sorted_dist_indicies[i]] # 选择k个距离最小的点,对应标签类别#计算类别vote_lable对应出现的次数# dict.get(key,x) python中字典的方法,get(key,0)从字典中获取key对应的value,字典中没有key的话返回0class_count[vote_lable] = class_count.get(vote_lable, 0) + 1# 以字典中的第二个元素(即value,此处为某类别出现的次数)逆序排序(即按照从最大到最小次序排序)sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)#返回出现次数最高的类别return sorted_class_count[0][0]handwriting_class()

代码参考:/u012162613/article/details/41768407

自己手写的图片转化为01文件,识别错误率较大

F:\KNN\imagetotxt.py

from PIL import Imagedef ImageToTxt(image_filename,txt_filename):'''将32*32像素的图片转化为只含01的txt文件'''image = Image.open(image_filename)# 显示图片#im.show()width, height = image.sizefh = open(txt_filename, 'w')for i in range(height):for j in range(width):# 获取像素点颜色color = image.getpixel((j, i))#RGBcolorsum = color[0] + color[1] + color[2]#黑色RGB为0,0,0if colorsum == 0:fh.write('1')else:fh.write('0')fh.write('\n')fh.close()#存储画图手写的数字,识别错误率较大for i in range(10):ImageToTxt('F:\KNN\\'+str(i)+'_0.png', 'F:\\KNN\\testDigits\\'+str(i)+'_0.txt')print('存储了数字'+str(i)+'的txt文件')

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。