机器学习 KNN 算法之手写数字识别
1.算法简介
手写数字识别是KNN算法一个特别经典的实例 , 其数据源获取方式有两种 , 一种是来自MNIST数据集 , 另一种是从UCI欧文大学机器学习存储库中下载 , 本文基于后者讲解该例 。 基本思想就是利用KNN算法推断出如下图一个32x32的二进制矩阵代表的数字是处于0-9之间哪一个数字 。
文章插图
数据集包括两部分 , 一部分是训练数据集 , 共有1934个数据;另一部分是测试数据集 , 共有946个数据 。 两个数据集中所有数据命名格式都是统一的 , 例如数字5的第56个样本—> 5_56.txt, 这样做为了方便提取出样本的真实标签 。
文章插图
数据的格式也有两种 , 一种是像上图一样由0、1组成的文本文件;另一种则是手写数字图片 , 需要对图片做一些处理 , 转化成像上图一样的文本格式 , 下文皆有介绍 。
2.算法步骤
- 收集数据:公开数据源
- 分析数据 , 构思如何处理数据
- 导入训练数据 , 转化为结构化的数据格式
- 计算距离(欧式距离)
- 导入测试数据 , 计算模型准确率
- 手写数字 , 实际应用模型
3.算法实现处理数据
在计算两个样本之间的距离时 , 每一个属性是一一对应的 , 所以这里将32x32的数字矩阵转化成1x1024数字矩阵 , 方便计算样本之间距离 。
#处理文本文件def img_deal(file):#创建一个1*1024的一维零矩阵the_matrix = np.zeros((1,1024))fb = open(file)for i in range(32):#逐行读取lineStr = fb.readline()for j in range(32):#将32*32=1024个元素赋值给一维零矩阵the_matrix[0,32*i+j] = int(lineStr[j])return the_matrix
计算欧式距离numpy 有一个 tile 方法 , 可以将一个一维矩阵横向复制若干次 , 纵向复制若干次 , 所以将一个测试数据经过 tile 方法处理后再减去训练数据 , 得到新矩阵后 , 再将该矩阵中每一条数据(横向)平方加和并开根号后即可得到测试数据与每一条训练数据之间的距离 。
下一步将所有距离升序排列 , 取到前K个 , 并在这个范围里 , 每个数字类别的个数 , 并返回出现次数较多那个数字类别的标签 。
def classify(test_data,train_data,label,k):Size = train_data.shape[0]#将测试数据每一行复制Size次减去训练数据 , 横向复制Size次 , 纵向复制1次the_matrix = np.tile(test_data,(Size,1)) - train_data#将相减得到的结果平方sq_the_matrix = the_matrix ** 2#平方加和 , axis = 1 代表横向all_the_matrix = sq_the_matrix.sum(axis = 1)#结果开根号得到最终距离distance = all_the_matrix ** 0.5#将距离由小到大排序 , 给出结果为索引sort_distance = distance.argsort()dis_Dict = {}#取到前k个for i in range(k):#获取前K个标签the_label = label[sort_distance[i]]#将标签的key和value传入字典dis_Dict[the_label] = dis_Dict.get(the_label,0)+1#将字典按value值的大小排序 , 由大到小 , 即在K范围内 , 筛选出现次数最多几个标签sort_Count = sorted(dis_Dict.items(), key=operator.itemgetter(1), reverse=True)#返回出现次数最多的标签return sort_Count[0][0]
测试数据集应用首先要对训练数据集处理 ,listdir 方法是返回一个文件夹下所有的文件 , 随后生成一个行数为文件个数 , 列数为1024的训练数据矩阵 , 并且将训练数据集中每条数据的真实标签切割提取存入至 labels 列表中 , 即计算距离 classify 函数中需要传入的 label。
labels = []#listdir方法是返回一个文件夹中包含的文件train_data = http://kandian.youth.cn/index/listdir('trainingDigits')#获取该文件夹中文件的个数m_train=len(train_data)#生成一个列数为train_matrix , 行为1024的零矩阵train_matrix = np.zeros((m_train,1024))for i in range(m_train):file_name_str = train_data[i]file_str = file_name_str.split('.')[0]#切割出训练集中每个数据的真实标签file_num = int(file_str.split('_')[0])labels.append(file_num)#将所有训练数据集中的数据都传入到train_matrix中train_matrix[i,:] = img_deal('trainingDigits/%s'%file_name_str)
然后对测试训练数据集做与上述一样的处理 , 并将 测试数据矩阵TestClassify 、 训练数据矩阵train_matrix 、 训练数据真实标签labels 、 K 共4个参数传入计算距离 classify 函数中 , 最后计算出模型准确率并输出预测错误的数据 。error = [] test_matrix = listdir('testDigits')correct = 0.0m_test = len(test_matrix)for i in range(m_test):file_name_str = test_matrix[i]file_str = file_name_str.split('.')[0]#测试数据集每个数据的真实结果file_num = int(file_str.split('_')[0])TestClassify = img_deal('testDigits/%s'%file_name_str)classify_result = classify(TestClassify,train_matrix,labels,3)print('预测结果:%s\t真实结果:%s'%(classify_result,file_num))if classify_result == file_num:correct += 1.0else:error.append((file_name_str,classify_result))print("正确率:{:.2f}%".format(correct / float(m_test) * 100))print(error)print(len(error))
- 机器人|网络里面的假消息忽悠了非常多的小喷子和小机器人
- 跑腿|机器人“小北”上岗 让办事群众少跑腿
- 计算机学科|机器视觉系统是什么
- 机器人|外骨骼康复训练机器人助力下肢运动功能障碍患者康复训练
- 教学|机器人教学的目标方案
- 体验|VR\/AR体验、3D打印、机器人“对决”……松江这所中学人工智能创新实验室真的赞
- 输送|新时达:“用于机器人码垛的输送系统”获发明专利
- 操作|[LIVE On]黄敏贤和郑多彬充满心碎的下午:机器操作每次都不能通过测试
- 用于|用于半监督学习的图随机神经网络
- 顶级|内地高校凭磁性球体机器人首获机器人顶级会议最佳论文奖