前言

本文将继续讲解K-近邻算法的项目实例 - 手写识别系统。

该系统在获取用户的手写输入后,判断用户写的是什么。

为了突出核心,简化细节,本示例系统中的输入为32x32矩阵,分类结果也均为数字。但对于汉字或者别的分类情形原理都是一样的。

有了前面学习的基础,下面直接进入项目开发步骤。

第一步:收集并准备数据

在用户主目录的trainingDigits子目录中,存放的是2000个样本数据。

每个样本一个文件,其中一部分如下所示:

文件命名格式为:

分类标签_标签内序号

如 0_20.txt 就表示该样本是分类标签为0的第20个特征集。20就是个序号以区分标签内不同文件而已,没其他意义。

样本数据都是32x32矩阵:

对于这样的二维数据,如何判断样本和目标对象的距离呢?首先想到的是可以将二维降到一维。

当然也可以考虑去找找二维的距离求解方法。

下面给出降维函数:

 # ==============================================
# 输入:
# 训练集文件名(含路径)
# 输出:
# 降维后的样本数据(这里一个文件一份样本数据)
# ==============================================
def img2vector(filename):
'将32x32的矩阵转换为1024一维向量' # 初始化返回向量
returnVect = numpy.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临近的分类函数代码在之前的文章K-近邻分类算法原理分析与代码实现中给出了,这里直接调用:

# =================================================
# 输入:
# 空
# 输出:
# 对指定的测试集文件,指定的训练集数据进行K近邻分类
# 并打印结果信息
# =================================================
def handwritingClassTest():
'手写数字识别系统测试代码' # 分类列表
hwLabels = [] # 获取所有训练集文件名
trainingFileList = os.listdir('/home/fangmeng/trainingDigits') # 定义训练集结构体
m = len(trainingFileList)
trainingMat = numpy.zeros((m, 1024)) for i in range(m):
# 当前训练集文件名
filenameStr = trainingFileList[i]
# 文件名(filenameStr去掉.txt后缀)
fileStr = filenameStr.split('.')[0]
# 分类标签
classNumStr = int(fileStr.split('_')[0])
# 将分类标签加入分类列表
hwLabels.append(classNumStr)
# 将当前训练集文件降维后加入到训练集结构体
trainingMat[i] = img2vector('/home/fangmeng/trainingDigits/%s' % filenameStr) # 获取所有测试集文件名
testFileList = os.listdir('/home/fangmeng/testDigits')
# 错误分类记数
errorCount = 0
# 测试集文件个数
mTest = len(testFileList) print "错误的分类结果如下:"
for i in range(mTest):
# 当前测试集文件名
fileNameStr = testFileList[i]
# 文件名(filenameStr去掉.txt后缀)
fileStr = fileNameStr.split('.')[0]
# 分类标签
classNumStr = int(fileStr.split('_')[0])
# 将当前测试集文件降维
vectorUnderTest = img2vector('/home/fangmeng/testDigits/%s' % fileNameStr)
# 对当前测试文件进行分类
classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3) if (classifierResult != classNumStr):
print "分类结果: %d, 实际结果: %d" % (classifierResult, classNumStr)
errorCount += 1.0 print "\n总错误数: %d" % errorCount
print "\n总错误数: %f" % (errorCount/float(mTest))

运行结果:

小结

1. K-邻近算法的本质是用来分类的,要从分类的思想去思考这个算法的运用。

2. 再强调一次K-邻近算法是没有训练过程的,这点和以后学习的其他分类方法,比如决策树对比后就更清楚了。

3. K-邻近算法的效率很低,不论是从时间还是空间上看(单就这个简单项目都跑得很慢)。因此需要学习更多更优化的算法。

4. 有兴趣有时间可以考虑在hadoop/spark集群下实现这个项目或使用该算法的其他类似项目,定能大幅度提升性能。

第三篇:基于K-近邻分类算法的手写识别系统的更多相关文章

  1. 【Machine Learning in Action --2】K-近邻算法构造手写识别系统

    为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素的黑白图像.尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理 ...

  2. 《机器学习实战》之k-近邻算法(手写识别系统)

    这个玩意和改进约会网站的那个差不多,它是提前把所有数字转换成了32*32像素大小的黑白图,然后转换成字符图(用0,1表示),将所有1024个像素点用一维矩阵保存下来,这样就可以通过knn计算欧几里得距 ...

  3. 基于OpenCV的KNN算法实现手写数字识别

    基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...

  4. KNN分类算法实现手写数字识别

    需求: 利用一个手写数字“先验数据”集,使用knn算法来实现对手写数字的自动识别: 先验数据(训练数据)集: ♦数据维度比较大,样本数比较多. ♦ 数据集包括数字0-9的手写体. ♦每个数字大约有20 ...

  5. K近邻分类算法实现 in Python

    K近邻(KNN):分类算法 * KNN是non-parametric分类器(不做分布形式的假设,直接从数据估计概率密度),是memory-based learning. * KNN不适用于高维数据(c ...

  6. 查看neighbors大小对K近邻分类算法预测准确度和泛化能力的影响

    代码: # -*- coding: utf-8 -*- """ Created on Thu Jul 12 09:36:49 2018 @author: zhen &qu ...

  7. k-近邻算法-手写识别系统

    手写数字是32x32的黑白图像.为了能使用KNN分类器,我们需要把32x32的二进制图像转换为1x1024 1. 将图像转化为向量 from numpy import * # 导入科学计算包numpy ...

  8. 第二篇:基于K-近邻分类算法的约会对象智能匹配系统

    前言 假如你想到某个在线约会网站寻找约会对象,那么你很可能将该约会网站的所有用户归为三类: 1. 不喜欢的 2. 有点魅力的 3. 很有魅力的 你如何决定某个用户属于上述的哪一类呢?想必你会分析用户的 ...

  9. 机器学习经典算法具体解释及Python实现--K近邻(KNN)算法

    (一)KNN依旧是一种监督学习算法 KNN(K Nearest Neighbors,K近邻 )算法是机器学习全部算法中理论最简单.最好理解的.KNN是一种基于实例的学习,通过计算新数据与训练数据特征值 ...

随机推荐

  1. org.apache.commons

    Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.我选了一些比较常用的项目做简单介绍. 一.Commons BeanUtils http://jakar ...

  2. c#简单写售票系统

    原理: 先生成一个9行4列的数组,然后用一个输入的值(坐标)去替换掉座位 代码: using System; using System.Collections.Generic; using Syste ...

  3. JavaScript 深入理解作用域链

    第一步. 定义后:每个已定义函数,都有一个内在属性[scope],其对应一个对象的列表,列表中的对象仅能内部访问. 例如:建立一个全局函数A,那么A的[Scope]内部属性中只包含一个全局对象(Glo ...

  4. 路由表及route使用

    路由表 linux下通过route可以查看本地路由表: Kernel IP routing table Destination     Gateway         Genmask         ...

  5. win7、vs2013编译webkit总结

    在windows7.vs2013环境下编译webkit,本人测试成功 1.解压cygwin到C盘下(建议放在C盘更目录下,否则编译期间会有部分文件找不到) 启动命令:C:\cygwin\bin\min ...

  6. 单片机小白学步系列(二十) IO口原理

    IO口操作是单片机实践中最基本最重要的一个知识,本篇花了比較长的篇幅介绍IO口的原理. 也是查阅了不少资料,确保内容正确无误,花了非常长时间写的. IO口原理原本须要涉及非常多深入的知识,而这里尽最大 ...

  7. find 命令一个命令多参数如何使用,????,perm

    [root@ob2 mytmp]# find -mtime -7 -type f \( -name "*.html" -o -name "*.tar.gz" \ ...

  8. Error -27780: Connection reset by peer: socket write error

    Problem Description: Error: "-27780: read to host failed: [10054] Connection reset by peer" ...

  9. Event Listener's Adapter Classes

    摘自: http://www.ntu.edu.sg/home/ehchua/programming/java/J4a_GUI.html Refer to the WindowEventDemo, a ...

  10. Netstat命令(windows下)

    功能: 一般用于检验本机各端口的网络连接情况. 例子:检查本机3389远程连接端口是否可用 netstat -nao|find  "3389" 查看某进程使用的端口号: netst ...