python实现kNN算法识别手写体数字的示例代码
作者:诺坎普奇迹 发布时间:2021-07-14 12:35:03
标签:python,kNN,手写体数字
1。总体概要
kNN算法已经在上一篇博客中说明。对于要处理手写体数字,需要处理的点主要包括:
(1)图片的预处理:将png,jpg等格式的图片转换成文本数据,本博客的思想是,利用图片的rgb16进制编码(255,255,255)为白色,(0,0,0)为黑色,获取图片大小后,逐个像素进行判断分析,当此像素为空白时,在文本数据中使用0来替换,反之使用1来替换。
from PIL import Image
'''将图片转换成文档,使用0,1分别替代空白和数字'''
pic = Image.open('/Users/wangxingfan/Desktop/1.png')
path = open('/Users/wangxingfan/Desktop/1.txt','a')
width = pic.size[0]
height = pic.size[1]
for i in range(0,width):
for j in range(0,height):
c_RGB = pic.getpixel((i,j))#获取该像素所对应的RGB值
if c_RGB[0]+c_RGB[1]+c_RGB[2]>0:#白色
path.write('0')
elif c_RGB[0]+c_RGB[1]+c_RGB[2]==0:#黑色
path.write('1')
else:
pass
path.write('\n')
path.close()
(2)训练集的构建。首先想到的是将(1)中图片处理后的文本数据构建成list形式,所以训练集将是二维数组,形如[[1,0,1,1,0,,,,,0,1],[0,1,1,1,10,,,,],[0,0,1,0,,,],,,,,]
所以我们构建函数处理训练集数据。
2。代码
简单的总结这个算法,就是将测试数据向量化,逐个和同样向量化的训练数据进行kNN运算,求的最短距离出现最多的分类就是我们要的分类。建立训练集的过程就是将文件数据向量化的过程。
#!/user/bin/env python
#-*- coding:utf-8 -*-
from os import listdir#获取文件目录下所有文件
'''
from PIL import Image
#将图片转换成文档,使用0,1分别替代空白和数字
pic = Image.open('/Users/wangxingfan/Desktop/1.png')
path = open('/Users/wangxingfan/Desktop/1.txt','a')
width = pic.size[0]
height = pic.size[1]
for i in range(0,width):
for j in range(0,height):
c_RGB = pic.getpixel((i,j))#获取该像素所对应的RGB值
if c_RGB[0]+c_RGB[1]+c_RGB[2]>0:#白色
path.write('0')
elif c_RGB[0]+c_RGB[1]+c_RGB[2]==0:#黑色
path.write('1')
else:
pass
path.write('\n')
path.close()
'''
import numpy as np
import operator as opt
def kNN(dataSet, labels, testData, k):
'''首先明确列表不能想加减,dataSet是数组形式,而对于下面的test函数,testData只是一列,相当于列表,所以在进行加减时,需要将其转换为数组,我们使用np下的tile函数来实现'''
testDatasize = dataSet.shape[0]#获取dataSet的总行数
dataSet = dataSet.astype('float64')#不进行转换则报错
testData1 = np.tile(testData,(testDatasize,1))#使用tile函数返回多个重复构成的数组
testData1 = testData1.astype('float64')
distSquareMat = (dataSet - testData1) ** 2 # 计算差值的平方
distSquareSums = distSquareMat.sum(axis=1) # 求每一行的差值平方和,axis=0则按列计算
distances = distSquareSums ** 0.5 # 开根号,得出每个样本到测试点的距离
sortedIndices = distances.argsort() # 排序,得到排序后的下标
indices = sortedIndices[:k] # 取最小的k个
labelCount = {} # 存储每个label的出现次数,出现次数最多的就是我们要选择的类别
for i in indices:
label = labels[i]
labelCount[label] = labelCount.get(label, 0) + 1 # 次数加一,使用字典的get方法,第一次出现时默认值是0
sortedCount = sorted(labelCount.items(), key=opt.itemgetter(1), reverse=True) # 对label出现的次数从大到小进行排序
return sortedCount[0][0] # 返回出现次数最大的label
#定义函数读取某个文件,返回该文件组成的数组
def file_data(fname):
arr = []
path = open(fname)
for i in range(0,32):
line = path.readline()
for j in range(0,32):
arr.append(line[j])
return arr
#建立训练数据集
def train_data():
lables = []
file_list = listdir('/学习/视频课程/源码/第7周/testandtraindata/traindata/')
trainarr = np.zeros((len(file_list),1024))
for i in range(0,len(file_list)):
file = '/学习/视频课程/源码/第7周/testandtraindata/traindata/'+file_list[i]
lables.append(file_list[i].split('_')[0])#获取对应的文件类别
trainarr[i,:] = file_data(file)#取所有列的第一个数据
return trainarr,lables
#测试函数
def test():
j = 0
k = 0
trainarr,lables = train_data()
testdata_list = listdir('/学习/视频课程/源码/第7周/testandtraindata/testdata/')
for i in range(0,len(testdata_list)):#逐个去测试
testfile = '/学习/视频课程/源码/第7周/testandtraindata/testdata/'+testdata_list[i]
testdata1 = file_data(testfile)
result = kNN(trainarr,lables,testdata1,k=3)
print(result+',real_number:'+testdata_list[i].split('_')[0])
if result == testdata_list[i].split('_')[0]:
j +=1
else:
k +=1
print('辨识成功率:'+j/(k+j))
test()
输出结果为:
3。几个知识点代码说明
(1)numpy.tile
p = np.array([0,0,0])
np.tile(p,(3,1))#表示columns方向重复三次,index方向不变
Out[12]:
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
np.tile(p,(1,3))#表示index方向重复三次,行还是一行
Out[13]: array([[0, 0, 0, 0, 0, 0, 0, 0, 0]])
(2)array[1,:]
表示取所有列的第【索引1】个数据(也就是第二行数据)
a = np.array([[1,1,1],[2,2,2],[3,3,3],[4,4,4]])
a[1,:]
Out[21]: array([2, 2, 2])
a[:,1]#所有行的第二列数据
Out[22]: array([1, 2, 3, 4])
(3)list并不能进行加减计算,需要使用numpy将数据转换为数组形式,且在使用例如:arr1+arr2时,需要两个数组的维度相同,在某个纬度上的数据长度也相同。
(4)使用os模块下的listdir,可以显示所有该文件夹下的文件,以列表的形式返回。
来源:https://blog.csdn.net/wangxingfan316/article/details/79436246


猜你喜欢
- 三遍记忆,让你记住海量素材的准确位置和用途,提高其可用性.这仅仅是一个示意图.在以往的日子里,我做到了只要脑袋里冒出一个想法,立刻就能知道我
- 如何用Cookie进行登录验证?很简单,看看这两个文件:login.htm请注册登录随风起舞<FORM ACTION=&qu
- 前言:今天带大家使用JavaScript定制一款网页时钟一、效果展示二、使用的技术主要使用了js的日期对象,实现的时候先创建一个日期对象,并
- 最近在学习Vue这个框架,发现新的版本中,官网的文档里面说的过渡效果,如果直接粘贴官方的例子中的代码,发现并没有过渡的效果,经过反复测试之后
- 如 现有字符串 "[]aseabcd[12345]ddxabcdsx[]",要截取"abcd[" 和
- 导读:SQL Server数据迁移的知识之前已经为大家介绍了很多,比如SQL Server数据库迁移方法,接下来就为大家详细介绍SQL Se
- 我使用的是anaconda安装的环境,其中有一个是h5py,自动安装的是2.7.0的版本,这个版本会导致保存模型时python奔溃。cond
- IronPython是一种在 .NET及 Mono上的 Python实现,由微软的 Jim Hugunin所发起,是一个开源的项目,基于微软
- /** * 对数据进行编码转换 * @param array/string $data  
- Python 截取字符串使用 变量[头下标:尾下标],就可以截取相应的字符串,其中下标是从0开始算起,可以是正数或负数,下标可以为空表示取到
- 背景堆是一种非常常用的数据结构,它能够支持在O(1)的时间复杂度获取到最大值(或最小值),因此我们经常在需要求最值的场景使用它。然而普通堆它
- 写在前面:从昨晚的梦里回忆起数据管理的作业:实现一个自己的选题----毕业生信息管理系统,实现学生个人信息基本的增删改查,我想了想前段时间刚
- 1.使用SQL*PLUS停止数据库$ sqlplus /nologSQL> connect / as sysdbaSQL> sh
- 创建一个SpringBoot项目其他不赘叙了,引入MyBaties、MySql依赖创建mysql表CREATE TABLE sp_users
- 长话短说:本人下载 matplotlib 花了大概三个半小时屡屡碰壁,险些暴走。为了不让新来的小伙伴走我的弯路,特意创作本片文章指明方向。1
- numpy中的ndarray转化成pytorch中的tensor : torch.from_numpy()pytorch中的tensor转化
- python 使用第三方库requests-toolbelt 上传文件流,内容如下所示:# pip install requests-too
- 上一篇内容,已经学会了使用简单的语句对网页进行抓取。接下来,详细看下urlopen的两个重要参数url和data,学习如何发送数据data一
- 一、匹配版本基于Camunda 7.16.0 + Springboot 2.5.8首先我们去官网找到camunda7.16对应的spring
- deque 是 double-ended queue的缩写,类似于 list,不过提供了在两端插入和删除的操作。appendleft 在列表