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

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

kNN

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

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

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

  这就是kNN的基本思想。

手写体识别数据准备

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

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

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

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

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

手写体识别算法运行流程

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

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

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

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

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

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

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

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

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

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

 1 #手写识别的测试代码
 2 def handwritingClassTest():
 3     hwLabels = []
 4     trainingFileList = listdir(path=‘trainingDigits‘)  #获取目录内容
 5     m = len(trainingFileList)
 6     trainingMat = zeros((m,1024))
 7     for i in range(m):
 8         #一下三行,从文件名解析分类数字
 9         fileNameStr = trainingFileList[i]
10         fileStr = fileNameStr.split(‘.‘)[0]
11         classNumStr = int(fileStr.split(‘_‘)[0])
12
13         hwLabels.append(classNumStr)
14         trainingMat[i,:] = img2vector(‘trainingDigits/%s‘%fileNameStr)
15     testFileList = listdir(path=‘testDigits‘)
16
17     errorCount = 0.0  #错误个数计数器
18     mTest = len(testFileList)
19
20     #从测试数据中提取数据
21     for i in range(mTest):
22         fileNameStr = testFileList[i]
23         fileStr = fileNameStr.split(‘.‘)[0]
24
25         classNumStr = int(fileStr.split(‘_‘)[0])
26         vectorUnderTest = img2vector(‘testDigits/%s‘% fileNameStr)
27         classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
28
29         print("the classifier came back with:%d,the real answer is:%d"%(classifierResult,classNumStr))
30         if(classifierResult != classNumStr):
31             errorCount += 1.0
32    #输出结果
33     print("\nthe total number of errors is:%d"%errorCount)
34     print("\nthe total error rate is: %f"%(errorCount/float(mTest)))

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

  测试结果如下:

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

后记

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

    

 

时间: 2024-10-25 21:13:41

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

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

我想大部分程序员的第一个程序应该都是"hello world",在深度学习领域,这个"hello world"程序就是手写字体识别程序. 这次我们详细的分析下手写字体识别程序,从而可以对深度学习建立一个基本的概念. 1.初始化权重和偏置矩阵,构建神经网络的架构 import numpy as np class network(): def __init__(self, sizes): self.num_layers = len(sizes) self.sizes =

【OpenCV】opencv3.0中的SVM训练 mnist 手写字体识别

前言: SVM(支持向量机)一种训练分类器的学习方法 mnist 是一个手写字体图像数据库,训练样本有60000个,测试样本有10000个 LibSVM 一个常用的SVM框架 OpenCV3.0 中的ml包含了很多的ML框架接口,就试试了. 详细的OpenCV文档:http://docs.opencv.org/3.0-beta/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html mnist数据下载:http://yann.l

pytorch深度学习神经网络实现手写字体识别

利用平pytorch搭建简单的神经网络实现minist手写字体的识别,采用三层线性函数迭代运算,使得其具备一定的非线性转化与运算能力,其数学原理如下: 其具体实现代码如下所示:import torchimport matplotlib.pyplot as pltdef plot_curve(data): #曲线输出函数构建 fig=plt.figure() plt.plot(range(len(data)),data,color="blue") plt.legend(["va

机器学习(二)-kNN手写数字识别

一.kNN算法 1.kNN算法是机器学习的入门算法,其中不涉及训练,主要思想是计算待测点和参照点的距离,选取距离较近的参照点的类别作为待测点的的类别. 2,距离可以是欧式距离,夹角余弦距离等等. 3,k值不能选择太大或太小,k值含义,是最后选取距离最近的前k个参照点的类标,统计次数最多的记为待测点类标. 4,欧式距离公式: 二.关于kNN实现手写数字识别 1,手写数字训练集测试集的数据格式,本篇文章说明的是<机器学习实战>书提供的文件,将所有数字已经转化成32*32灰度矩阵. 三.代码结构构成

第6章 识别手写字体

前言 神经网络是一种很特别的解决问题的方法.本书将用最简单易懂的方式与读者一起从最简单开始,一步一步深入了解神经网络的基础算法.本书将尽量避开让人望而生畏的名词和数学概念,通过构造可以运行的Java程序来实践相关算法. 关注微信号"javaresearcher"来获取本书的更多信息. 这一章节我们将会解决一个真正的问题:手写字体识别.我们将识别像下面图中这样的手写数字. 在开始之前,我们先要准备好相应的测试数据.我们不能像前边那样简单的产生手写字体,毕竟我们自己还不知道如何写出一个产生

手把手教你搭建caffe及手写数字识别(全程命令提示、纯小白教程)

手把手教你搭建caffe及手写数字识别 作者:七月在线课程助教团队,骁哲.小蔡.李伟.July时间:二零一六年十一月九日交流:深度学习实战交流Q群 472899334,有问题可以加此群共同交流.另探究实验背后原理,请参看此课程:11月深度学习班. 一.前言 在前面的教程中,我们搭建了tensorflow.torch,教程发布后,大家的问题少了非常多.但另一大框架caffe的问题则也不少,加之caffe也是11月深度学习班要讲的三大框架之一,因此,我们再把caffe的搭建完整走一遍,手把手且全程命

机器学习实战笔记——基于KNN算法的手写识别系统

本文主要利用k-近邻分类器实现手写识别系统,训练数据集大约2000个样本,每个数字大约有200个样本,每个样本保存在一个txt文件中,手写体图像本身是32X32的二值图像,如下图所示: 首先,我们需要将图像格式化处理为一个向量,把一个32X32的二进制图像矩阵通过img2vector()函数转换为1X1024的向量: def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i in range(

Kaggle竞赛丨入门手写数字识别之KNN、CNN、降维

引言 这段时间来,看了西瓜书.蓝皮书,各种机器学习算法都有所了解,但在实践方面却缺乏相应的锻炼.于是我决定通过Kaggle这个平台来提升一下自己的应用能力,培养自己的数据分析能力. 我个人的计划是先从简单的数据集入手如手写数字识别.泰坦尼克号.房价预测,这些目前已经有丰富且成熟的方案可以参考,之后关注未来就业的方向如计算广告.点击率预测,有合适的时机,再与小伙伴一同参加线上比赛. 数据集 介绍 MNIST ("Modified National Institute of Standards an

Python 手写数字识别-knn算法应用

在上一篇博文中,我们对KNN算法思想及流程有了初步的了解,KNN是采用测量不同特征值之间的距离方法进行分类,也就是说对于每个样本数据,需要和训练集中的所有数据进行欧氏距离计算.这里简述KNN算法的特点: 优点:精度高,对异常值不敏感,无数据输入假定 缺点:计算复杂度高,空间复杂度高 适用数据范围:数值型和标称型(具有有穷多个不同值,值之间无序)    knn算法代码: #-*- coding: utf-8 -*- from numpy import * import operatorimport