找回密码
 立即注册
搜索

机器学习(三):k-近邻算法应用举例——手写识别系统

手写识别系统







环境及资源说明

编程语言:Python
机器环境:Windows
参考书籍:《机器学习实战》
可参考学习视频:
吴恩达机器学习视频:
https://study.163.com/course/courseMain.htm?courseId=1004570029
电子书、代码、笔记获取:
https://github.com/wakemeuphzk/study/tree/master/Machine%20Learning/Machine%20Learning%20in%20Action



上节讲了k-近邻算法的原理与优缺点,本节通过实例来讲kNN的运用。




示例说明

目的

识别数字0~9
训练集与测试集
需要识别的数字已经使用图形处理软件,处理成宽高是32像素 x 32像素的黑白图像。用0与1表示,存储成文本格式。如下所示

github上的kNN/data中有相应的训练集与测试集,大家可以自行下载。
在目录trainingDigits中有大约2000个样本,其中每个数字约200个样本,作为训练集,用来训练分类器;目录testDigits中有大约950个测试数据,作为测试集,用来测试分类器的效果。两组数据无重叠。
输入与输出

输入测试集中的每个数据,输出对应的数字0~9
目的是否需要归一化处理

由于每个样本都是由0与1组成的图形矩阵,故不需要归一化处理
                                             
工程结构




如上,建立一个机器学习(ML)的工程,k-近邻相关代码与数据放入kNN目录下,kNN的核心代码在kNN.py中,data中是相关数据,testDigits目录下是测试集,traningDigits目录下是训练集,testHandWriting.py用于执行手写识别系统的程序。


编码

[color=rgba(0, 0, 0, 0.85)]核心:kNN算法实现
def classify0(inX, dataSet, labels, k):
   dataSetSize = dataSet.shape[0]
   diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
   sqDiffMat = diffMat ** 2
   sqDistances = sqDiffMat.sum(axis=1)
   distances = sqDistances ** 0.5
   sortedDistIndicies = distances.argsort()
   classCount = {}
   for i in range(k):
       voteIlabel = labels[sortedDistIndicies]
       classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
   sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
   return sortedClassCount[0][0]

参数说明:用于分类的输入向量inX,训练样本集dataSet,标签向量labels(即每个样本的结果输出y),k表示最近邻居的数目。此代码片段计算的是欧氏距离。
代码思路:

  • 计算数据集中的点与当前点的距离
  • 选取与当前点距离最小的k个点
  • 统计这k个点所在类别的概率,取概率最高的类型


测试算法

def handwritingClassTest():
   hwLabels = []
   trainingFileList = listdir('kNN/data/trainingDigits')  # load the training set
   m = len(trainingFileList)
   trainingMat = np.zeros((m, 1024))
   for i in range(m):
       fileNameStr = trainingFileList
       fileStr = fileNameStr.split('.')[0]  # take off .txt
       classNumStr = int(fileStr.split('_')[0])
       hwLabels.append(classNumStr)
       trainingMat[i, :] = img2vector('kNN/data/trainingDigits/%s' % fileNameStr)
   testFileList = listdir('kNN/data/testDigits')  # iterate through the test set
   errorCount = 0.0
   mTest = len(testFileList)
   for i in range(mTest):
       fileNameStr = testFileList
       fileStr = fileNameStr.split('.')[0]  # take off .txt
       classNumStr = int(fileStr.split('_')[0])
       vectorUnderTest = img2vector('kNN/data/testDigits/%s' % fileNameStr)
       classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels,
10)
       print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))
       if (classifierResult != classNumStr): errorCount += 1.0
   print("the total number of errors is: %d" % errorCount)
   print("the total error rate is: %f" % (errorCount / float(mTest)))

我们将trainingDigits目录中的文件内容存储在列表trainingFileList中,并将其个数存储在m中。接着,代码创建一个m行1024列的矩阵存储一个图像。下一步,我们对testDigits目录进行相似的操作,并用Classify()进行分类测试。


输出

执行测试代码(testHandWriting.py)

import sys
sys.path.append("kNN")
import kNN

kNN.handwritingClassTest()

输出



如上,当k=10时,kNN预测的错误率是2%,可以修改k的值,查看对错误率的影响。
由上可以看出,kNN需要保存所有数据集,对每个数据计算距离值,对于训练集很大的数据,需要大量的存储空间,同时也很耗时。而且kNN不像其他算法,有一个训练的过程,无法给出任何数据的基础结构信息,无法知晓实例样本和典型实例样本具有什么特征。


下期 机器学习(四):逻辑回归




机器学习系列:

家明将与大家一起学习机器学习,借助于网上的教程与书籍指导,家明总结,与大家一起进步,共同应对AI时代。












本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies