kNN - 手写数字识别
识别手写的数字0-9,图像为32像素 × 32像素的黑白图像
1.将图像转换为向量
将32
×
32的二进制图像矩阵转换为1
×
1024的向量。
#将图像转化为向量
def imgVector(filename):
returnVect = zeros((1,1024))
fr = open(filename)
#读取文件的前32行
for i in range(32):
lineStr = fr.readline()
#存储每行的前32个字符值
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect
读入文件输出结果[0,32:63]部分:
2.使用kNN算法识别手写数字
(1) 导入包os.listdir
os.listdir(path)
- path:需要列出的目录路径
- 返回指定路径下的文件和文件夹列表
(2)分别读取训练数据集和测试数据集,使用分类器分类
#识别手写测试
def handwirtingClassTest():
hwLables = []
#读取训练数据集
trainingFileList = listdir('trainingDigits')
m = len(trainingFileList)
#构造初始的1*1024的全0向量
trainingMat = zeros((m,1024))
for i in range(m):
#从文件名中解析数字
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
#存入类标签
hwLables.append(classNumStr)
#分类器的dataSet
trainingMat[i,:] = imgVector('trainingDigits/%s'%fileNameStr)
#测试数据集
testFileList = listdir('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 = imgVector('testDigits/%s'%fileNameStr)
#使用分类器分类
classifierResult = classify(vectorUnderTest,trainingMat,hwLables,3)
print "the classifier came back with%d,the real answer is : %d"%(classifierResult,classNumStr)
if (classifierResult != classNumStr):
errorCount += 1.0
print "the total error rate is :%f:" % (errorCount / float(mTest))
输出结果:
错误率为1.16%。
3. kNN的优缺点:
优点:
- 算法简单
- 训练时间复杂度为O(n);
缺点:
- 所用存储空间较大,因为其需要保存全部的数据集
- 计算开销大,需要计算到数据集中每个数据的距离
- 无法给出数据的基础结构信息
- 样本不平衡时,预测偏差比较大。如:某一类的样本比较少,而其它类样本比较多。