KNN手写体数字识别
思路:首先这是一个通过KNN分类来完成的数字识别,数据集的格式全部是经过处理后的32x32de1二进制数字矩阵,把一个样本(32x32)转化为1x1024的向量,即一行代表一个样本,然后把训练样本也转化为一个数字矩阵,每次输入一个测试集都与训练集的矩阵进行作差,然后平方和开根号,最后将每一个输入的测试集进行比较,和哪个差值最小(即形状最相似)即为哪一类(0~9)
'''KNN算法实现手写体数字识别'''
import numpy as np
from os import listdir
import operator
def img2vector(filename):
"""实现将图片转换为向量形式"""
return_vector = np.zeros((1, 1024))
fr = open(filename)
for i in range(32):
line = fr.readline()
for j in range(32):
return_vector[0, 32*i + j] = int(line[j])
return return_vector
# inX 用于分类的输入向量
# dataSet表示训练样本集
# 参数k表示选择最近邻居的数目
def classify0(inx, data_set, labels, k):
"""实现knn"""
diff_mat = inx - data_set # 各个属性特征做差
sq_diff_mat = diff_mat**2 # 各个差值求平方
sq_distances = sq_diff_mat.sum(axis=1) # 按行求和
distances = sq_distances**0.5 # 开方
sorted_dist_indicies = distances.argsort() # 按照从小到大排序,并输出相应的索引值
class_count = {} # 创建一个字典,存储k个距离中的不同标签的数量
for i in range(k):
vote_label = labels[sorted_dist_indicies[i]] # 求出第i个标签
# 访问字典中值为vote_label标签的数值再加1,
class_count[vote_label] = class_count.get(vote_label, 0)+1
# 将获取的k个近邻的标签类进行排序
# print(class_count)
sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
# 标签类最多的就是未知数据的类
return sorted_class_count[0][0]
def hand_writing_class_test():
hand_writing_labels = [] # 手写数字类别标签
training_file_list = listdir('G:\\YJS\\datatra\\KNN\\trainingDigits') # 获得文件中目录列表,训练数据集
m = len(training_file_list) # 求得文件中目录文件个数(训练数据集)
training_mat = np.zeros((m, 1024)) # 创建训练数据矩阵,特征属性矩阵
for i in range(m):
file_name_str = training_file_list[i] # 获取单个文件名
file_str = file_name_str.split(' ')[0] # 将文件名中的空字符去掉,这里的[0]是将文件名取出来
class_num_str = int(file_str.split('_')[0]) # 取出数字类别
hand_writing_labels.append(class_num_str) # 将数字类别添加到类别标签矩阵中
# 将图像格式转换为向量形式
training_mat[i, :] = img2vector('G:\\YJS\\datatra\\KNN\\trainingDigits\%s' % file_name_str)
test_file_list = listdir('G:\\YJS\\datatra\\KNN\\testDigits') # 获得文件中目录列表,测试数据集
error_count = 0 # 错误分类个数
m_test = len(test_file_list) # 测试数据集个数
for i in range(m_test):
file_name_str = test_file_list[i]
file_str = file_name_str.split('.')[0]
class_num_str = int(file_str.split('_')[0])
# 将图像格式转换为向量形式(测试数据集)
vector_under_test = img2vector('G:\\YJS\\datatra\\KNN\\testDigits\%s' % file_name_str)
# KNN分类,以测试数据集为未知数据,训练数据为训练数据
classifier_result = classify0(vector_under_test, training_mat, hand_writing_labels, 3)
# 输出分类结果和真实类别
print('分类结果: %d, 真实结果: %d' % (classifier_result, class_num_str))
# 计算错误分类个数
if classifier_result != class_num_str:
error_count += 1
# 输出错误分类个数和错误率
print("\n 错误分类个数 is: %d" % error_count)
print("\n 错误率: %f" % (error_count/float(m_test)))
# 调用手写识别
if __name__=='__main__':
hand_writing_class_test()
print("--end--")