基于kNN的手写字体识别——《机器学习实战》笔记

时间:2022-09-10 13:26:16

看完一节《机器学习实战》,算是踏入ML的大门了吧!这里就详细讲一下一个demo:使用kNN算法实现手写字体的简单识别

kNN

 先简单介绍一下kNN,就是所谓的K-近邻算法:

  【作用原理】:存在一个样本数据集合、每个样本数据都存在标签。输入没有标签的新数据后,将新数据的每个特征与样本集数据的对应特征进行比较,然后算法提取样本集中最相似的分类标签。一般说来,我们只选择样本数据集中前k个最相似的数据,最后,选择这k个相似数据中出现次数最多的分类,作为新数据的分类。

  通俗的说,举例说明:有一群明确国籍的人(样本集合,比如1000个):中国人、韩国人、日本人、美国人、埃及人,现在有一个不知国籍的人,想要通过比较特征来猜测他的国籍(当然,特征具有可比较性和有效性),通过比较特征,得出特征与该人最相近的样本集中的9个人(k),其中,1个是韩国人、2个是日本人,6个是中国人,那么这个人是中国人的可能性就很大。

  这就是kNN的基本思想。

手写体识别数据准备

  kNN输入需要特征矩阵,一般是固定大小的二值图像,这里我们使用书上提供的数据集:这个数据集使用32X32文本文件存储数值图像。例如下图的'9'

基于kNN的手写字体识别——《机器学习实战》笔记

  这里每个文本文件存储一个手写体数据,并且文件名写成"number_num.txt"这样的形式,例如9_1.txt,方便后期提取标签

  我们将样本数据放在trainingDigits文件夹中,测试样例存储在testDigits文件夹中

基于kNN的手写字体识别——《机器学习实战》笔记

  我们在处理时将每个手写体数据(32x32)转换成1X1024维的向量。

  另外,kNN涉及到相似度计算。这里我们使用的是欧氏距离,由于手写体数据向量是规则的二值数据,因此不需要进行归一化。

手写体识别算法运行流程

  (一)读取手写体txt文件,转化为1X1024向量

    我们创建一个kNN.py,添加模块img2vector

 #识别手写字体模块-图像转向量32x32 to 1x1024
def img2vector(filename):
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect

    我们的样本数据和测试数据都需要用到该函数

  (二)比较测试数据和样本数据集的距离,返回k近邻中最相似的标签

    在kNN.py中添加classify0模块,附上代码注释  

 #---------------------------------------------
#分类模块
#@params
# inX:输入向量、手写体识别的测试向量
# dataSet:训练集样本、手写体识别的训练集向量
# labels:训练集对应的标签向量
# k:最近邻居数目、本实验为3
#---------------------------------------------
def classifiy0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0] #手写体样本集容量
#(以下三行)距离计算
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5 #欧氏距离开平方
sortedDistIndicies = distances.argsort() #距离排序的索引排序
classCount = {}
#(以下两行)选择距离最小的k个点
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.items(),
#排序
key = operator.itemgetter(1), reverse = True)
return sortedClassCount[0][0]

    注意,这里使用了numpy的接口,在kNN.py的开头要加上:from numpy import* 

  (三)比较标签与测试结果,计算正确率

    同样,在kNN.py中添加handwritingClassTest模块,综合以上的两个模块,获得识别正确率

 #手写识别的测试代码
def handwritingClassTest():
hwLabels = []
trainingFileList = listdir(path='trainingDigits') #获取目录内容
m = len(trainingFileList)
trainingMat = zeros((m,1024))
for i in range(m):
#一下三行,从文件名解析分类数字
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0]) hwLabels.append(classNumStr)
trainingMat[i,:] = img2vector('trainingDigits/%s'%fileNameStr)
testFileList = listdir(path='testDigits') errorCount = 0.0 #错误个数计数器
mTest = len(testFileList) #从测试数据中提取数据
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0] classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector('testDigits/%s'% fileNameStr)
classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3) print("the classifier came back with:%d,the real answer is:%d"%(classifierResult,classNumStr))
if(classifierResult != classNumStr):
errorCount += 1.0
  #输出结果
print("\nthe total number of errors is:%d"%errorCount)
print("\nthe total error rate is: %f"%(errorCount/float(mTest)))

    注意,这里使用到了os模块listdir,在kNN开头加入:from numpy import listdir

  测试结果如下:

基于kNN的手写字体识别——《机器学习实战》笔记

  错误率为1.16%,可以看到,识别效果挺不错。

后记

  通过实验我们可以看到,使用kNN要将训练样本一次性加载入内存、如果训练集的规模很大,势必对机器有很大的要求。另外,kNN不需要训练算法、对异常值不敏感、在后期使用的时候要慎重选择吧

    

 

基于kNN的手写字体识别——《机器学习实战》笔记的更多相关文章

  1. 深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识

    深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识 在tf第一个例子的时候需要很多预备知识. tf基本知识 香农熵 交叉熵代价函数cross-entropy 卷积神经网络 s ...

  2. 基于MATLAB的手写公式识别(6)

    基于MATLAB的手写公式识别 2021-03-29 10:24:51 走通了程序,可以识别"心脑血管这几个字",还有很多不懂的地方. 2021-03-29 12:20:01 tw ...

  3. KNN实现手写数字识别

    KNN实现手写数字识别 博客上显示这个没有Jupyter的好看,想看Jupyter Notebook的请戳KNN实现手写数字识别.ipynb 1 - 导入模块 import numpy as np i ...

  4. 深度学习---手写字体识别程序分析(python)

    我想大部分程序员的第一个程序应该都是“hello world”,在深度学习领域,这个“hello world”程序就是手写字体识别程序. 这次我们详细的分析下手写字体识别程序,从而可以对深度学习建立一 ...

  5. 深度学习-tensorflow学习笔记(2)-MNIST手写字体识别

    深度学习-tensorflow学习笔记(2)-MNIST手写字体识别超级详细版 这是tf入门的第一个例子.minst应该是内置的数据集. 前置知识在学习笔记(1)里面讲过了 这里直接上代码 # -*- ...

  6. 基于MATLAB的手写公式识别(9)

    基于MATLAB的手写公式识别(9) 1.2图像的二值化 close all; clear all; Img=imread('drink.jpg'); %灰度化 Img_Gray=rgb2gray(I ...

  7. 基于MATLAB的手写公式识别(5)

    基于MATLAB的手写公式识别 总结一下昨天一天的工作成果: 获得了大致的识别过程. 一个图像从生肉到可以被处理需要经过预处理(灰质化.增加对比度.中值过滤.膨胀或腐蚀.闭环运算). 掌握了相关函数的 ...

  8. 基于MATLAB的手写公式识别(3)

    基于MATLAB的手写公式识别 图像的膨胀化,获取边缘(思考是否需要做这种处理,初始参考样本相对简单) %膨胀 imdilate(dilate=膨胀/扩大) clc clear A1=imread(' ...

  9. 基于MATLAB的手写公式识别(2)

    基于MATLAB的手写公式识别 图像的预处理(除去噪声.得到后续定位分割所需的信息.) 预处理其本质就是去除不需要的噪声信息,得到后续定位分割所需要的图像信息.图像信息在采集的过程中由于天气环境的影响 ...

随机推荐

  1. 使用LotusScript操作Lotus Notes RTF域

    Lotus Notes RTF域的功能也非常强大,除了支持普通的文本以外,还支持图片.表格.嵌入对象.Http 链接.Notes 链接.附件等等众多的类型.本文将介绍如何使用这些类来灵活操作富文本域. ...

  2. HDU 4292 Food

    Food Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. python邮件收发SAMPLE

    #!/usr/bin/env python # -*- encoding: utf-8 -*- import os, socket from time import localtime, strfti ...

  4. MySQL数据库建立外键失败的原因总结

    在MySQL数据库创建外键时,经常会发生一些错误,这是一件很令人头疼的事.一个典型的错误就是:Can’t create table... 的错误.在很多实例中,这种错误的发生都是因为mysql一直以来 ...

  5. 兼容IE6,IE7和firefox可以使用的一些css hack:

    .一些问题是浏览器自身的问题,遇到问题发生无法避免的情况下,那就要考虑使用一些css hack了,以下是针对IE6,IE7和firefox可以使用的一些css hack:(1) a: 针对区别IE6 ...

  6. 为什么做java开发的公司需要那么多程序员?

    注:文章转载自知乎 透过现象看本质. Java是企业应用市场的王者,如果一家非互联网公司用Java,那么十有八九是做企业应用的. 所以,这个问题本质上是:为什么做企业应用的公司需要那么多Java程序员 ...

  7. sparkStreaming序列化问题

    执行sparkSTreaming+kafka 报错如下: org.apache.spark.SparkException: Task not serializable ...... Caused by ...

  8. mybatis11--多对多关联查询

    多对多关联! 其实就是两个一对多的关联! 比如说 一个学生可以有多个老师!一个老师可以有多个学生! 那么 学生和老师之间的关系  可以理解为 多对多的关联关系! 关键是怎么建立数据库中两个表之间的关系 ...

  9. TStrings与Memo.Lines赋值的问题

    //想实现在函数中生成Memo1的内容,而后赋给Memo.Lines //方法1: var s: TStrings; begin s := TStringList.Create; AddMemoDat ...

  10. 2018/04/07 每日一个Linux命令 之 logrotate

    简介 日志的存在一直是 Linux 里面一个比较重要内容. 但是随着服务器运行的时间越来越长,日志越来越大.我见过一个线上项目 TP3.2 log文件有260+G的...... logrotate 也 ...