手写识别系统
环境及资源说明
编程语言: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时代。
|