机器学习(八)-基于KNN分类算法的手写识别系统

栏目: 编程工具 · 发布时间: 5年前

内容简介:基于k-近邻分类器(KNN)的手写识别系统, 这里构造的系统只能识别数字0到9。图像转换为文本格式

1 项目介绍

基于k-近邻分类器(KNN)的手写识别系统, 这里构造的系统只能识别数字0到9。

数据集和项目源代码

  • 难点: 图形信息如何处理?

图像转换为文本格式

2 准备数据

将图像转换为测试向量

  • 训练集:

    • 目录trainingDigits
    • 大约2000个例子
    • 每个数字大约有200个样本;
  • 测试集

    • 目录testDigits
    • 大约900个测试数据。

将图像格式化处理为一个向量。我们将把一个32×32的二进制图像矩阵转换为1×1024的向量, 如下图所示,

机器学习(八)-基于KNN分类算法的手写识别系统

import numpy as np
def img2vector(filename):
    """
    # 将图像数据转换为(1,1024)向量
    :param filename: 
    :return: (1,1024)向量
    """
    # 生成一个1*1024且值全为0的向量;
    returnVect = np.zeros((1, 1024))
    # 读取要转换的信息;
    file = open(filename)
    # 依次填充
    # 读取每一行数据;
    for i in range(32):
        lineStr = file.readline()
        # 读取每一列数据;
        for j in range(32):
            returnVect[0, 32 * i + j] = int(lineStr[j])
    return returnVect

3 实施 KNN 算法

对未知类别属性的数据集中的每个点依次执行以下操作, 与上一个案例代码相同:

(1) 计算已知类别数据集中的点与当前点之间的距离;

(2) 按照距离递增次序排序;

(3) 选取与当前点距离最小的k个点;

(4) 确定前k个点所在类别的出现频率;

(5) 返回前k个点出现频率最高的类别作为当前点的预测分类。

def classify(inX, dataSet, labels, k):
    """
    :param inX: 要预测的数据
    :param dataSet: 我们要传入的已知数据集
    :param labels:  我们要传入的标签
    :param k: KNN里的k, 也就是说我们要选几个近邻
    :return: 排序的结果
    """
    dataSetSize = dataSet.shape[0]  # (6,2) 6
    # tile会重复inX, 把他重复成(datasetsize, 1)型的矩阵
    # print(inX)
    # (x1 - y1), (x2- y2)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # 平方
    sqDiffMat = diffMat ** 2
    # 相加, axis=1 行相加
    sqDistance = sqDiffMat.sum(axis=1)
    # 开根号
    distances = sqDistance ** 0.5
    # print(distances)
    # 排序 输出的是序列号index,并不是值
    sortedDistIndicies = distances.argsort()
    # print(sortedDistIndicies)

    classCount = {}
    for i in range(k):
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
        # print(classCount)
    sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True)
    return sortedClassCount[0]

4 测试算法

使用 k-近邻算法识别手写数字

  • 测试集里面的信息;

机器学习(八)-基于KNN分类算法的手写识别系统

def handWritingClassTest(k):
    """
    # 测试手写数字识别错误率的代码
    :param k:
    :return:
    """
    hwLabels = []
    import os
    # 读取所有的训练集文件;
    trainingFileList = os.listdir('data/knn-digits/trainingDigits')
    # 获取训练集个数;
    m = len(trainingFileList)
    # 生成m行1024列全为0的矩阵;
    trainingMat = np.zeros((m, 1024))
    # 填充训练集矩阵;
    for i in range(m):
        fileNameStr = trainingFileList[i]    # fileNameStr: 0_0.txt
        fileStr = fileNameStr.split('.')[0]  # fileStr: 0_0
        classNumStr = int(fileStr.split('_')[0])    # (数字分类的结果)classNumStr: 0
        # 填写真实的数字结果;
        hwLabels.append(classNumStr)
        # 图形的数据: (1,1024)向量
        trainingMat[i, :] = img2vector("data/knn-digits/trainingDigits/%s" % fileNameStr)

    # 填充测试集矩阵;
    testFileList = os.listdir('data/knn-digits/testDigits')
    # 默认错误率为0;
    errorCount = 0.0
    # 测试集的总数;
    mTest = len(testFileList)
    # 填充测试集矩阵;
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        vectorTest = img2vector("data/knn-digits/testDigits/%s" % fileNameStr)

        # 判断预测结果与真实结果是否一致?
        result = classify(vectorTest, trainingMat, hwLabels, k)

        if result != classNumStr:
            # 如果不一致,则统计出来, 计算错误率;
            errorCount += 1.0
            print("[预测失误]:分类结果是:%d, 真实结果是:%d" % (result, classNumStr))
    print("错误总数:%d" % errorCount)
    print("错误率:%f" % (errorCount / mTest))
    print("模型准确率:%f" %(1-errorCount / mTest))
    return errorCount


print(handWritingClassTest(2))
  • 效果展示

机器学习(八)-基于KNN分类算法的手写识别系统

5 KNN算法手写识别的缺点

算法的执行效率并不高。

  • 每个测试向量做2000次距离计算,每个距离计算包括了1024个维度浮点运算,总计要执行900次;
  • 需要为测试向量准备2MB的存储空间

有没有更好的方法?

  • k决策树就是k-近邻算法的优化版,可以节省大量的计算开销。

以上所述就是小编给大家介绍的《机器学习(八)-基于KNN分类算法的手写识别系统》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Realm of Racket

Realm of Racket

Matthias Felleisen、Conrad Barski M.D.、David Van Horn、Eight Students Northeastern University of / No Starch Press / 2013-6-25 / USD 39.95

Racket is the noble descendant of Lisp, a programming language renowned for its elegance and power. But while Racket retains the functional goodness of Lisp that makes programming purists drool, it wa......一起来看看 《Realm of Racket》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试