基于knn的手写数字图像识别

k近邻原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前 𝑘 个最相似的数据,通常 𝑘 是不大于20的整数。最后,选择 𝑘 个最相似数据中出现次数最多的类别,作为新数据的分类。

L1,L2,L-lnf 距离

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于python的手写数字识别

将下载的MNIST数据集进行解压,保存为图片格式,存入data文件夹下,data下分别建立train和test文件夹,存入训练集和测试集
在这里插入图片描述
train文件夹下的数据集如下:0-9每个数字各有100张图像
在这里插入图片描述
test文件夹下的数据集如下:0-9每个数字各有若干张图像
在这里插入图片描述

自写代码如下:

import numpy as np
from os import listdir
import cv2
import operator


# 分类器采用欧式距离
def classify0(inX, dataSet, labels, k):
    """
    参数:
    - inX: 用于分类的输入向量
    - dataSet: 输入的训练样本集
    - labels: 样本数据的类标签向量
    - k: 用于选择最近邻居的数目
    """

    # 获取样本数据数量
    dataSetSize = dataSet.shape[0]
    # 矩阵运算,计算测试数据与每个样本数据对应数据项的差值
    # tile(a, (10, 1)) 表示构造了10行a这个向量
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet

    # sqDistances 上一步骤结果平方和
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)

    # 取平方根,得到距离向量
    distances = sqDistances ** 0.5

    # 按照距离从低到高排序
    sortedDistIndicies = distances.argsort()
    classCount = {}

    # 依次取出最近的样本数据
    for i in range(k):
        # 记录该样本数据所属的类别
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1

    # 对类别出现的频次进行排序,从高到低
    sortedClassCount = sorted(
        classCount.items(), key=operator.itemgetter(1), reverse=True)

    # 返回出现频次最高的类别
    return sortedClassCount[0][0]


def img2vector(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    returnVect = np.zeros((1, 784))    # 创建向量
    for i in range(28):
        for j in range(28):
            returnVect[0, 28 * i + j] = img[i][j]

    return returnVect


# 进行手写数字测试
def handwriteCalssTest():
    hwLabels = []  # 样本数据的标签
    trainingFileList = listdir('./data/train')  # 读取样本数据列表
    m = len(trainingFileList)  # 样本数据的实例数
    trainingMat = np.zeros((m, 784))  # 初始化样本数据矩阵, 模版图像: 28*28=784
    # 依次读取所有样本到数据矩阵中
    for i in range(m):
        # 提取文件名中的数字
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)

        # 将样本数据存入矩阵
        trainingMat[i, :] = img2vector('./data/train/%s' % fileNameStr)

    # 循环读取测试数据
    testFileList = listdir('./data/test')
    # 初始化错误率
    errorCount = 0.0
    mTest = len(testFileList)

    # 循环测试每个测试数据文件
    for i in range(mTest):
        # 提取文件名中的数字
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])

        # 提取数据向量
        vectorUnderTest = img2vector('./data/test/%s' % fileNameStr)
        # 对数据文件进行分类
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)

        # 打印 K 近邻算法分类结果和真实的分类
        print("测试样本 %d, 分类器预测: %d, 真实类别: %d" % (i + 1, classifierResult, classNumStr))

        # 判断K 近邻算法结果是否准确
        if (classifierResult != classNumStr):
            errorCount += 1.0

    # 打印错误率
    print("\n错误分类计数: %d" % errorCount)
    print("\n错误分类比例: %f" % (errorCount/float(mTest)))
    print('\n分类器准确率: %f' % (1 - (errorCount/float(mTest))))


if __name__ == '__main__':

    handwriteCalssTest()

使用机器学习库自带knn分类器,代码如下

"""
使用机器学习库自带的 knn分类器进行手写数字分类
"""

import numpy as np
from os import listdir
import cv2
import operator
from sklearn.neighbors import KNeighborsClassifier


def img2vector(filename):
    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    returnVect = np.zeros((1, 784))    # 创建向量
    for i in range(28):
        for j in range(28):
            returnVect[0, 28 * i + j] = img[i][j]

    return returnVect

hwLabels = []  # 样本数据的标签
trainingFileList = listdir('./data/train')  # 读取样本数据列表
m = len(trainingFileList)  # 样本数据的实例数
trainingMat = np.zeros((m, 784))  # 初始化样本数据矩阵

# 依次读取所有样本到数据矩阵中
for i in range(m):
    # 提取文件名中的数字
    fileNameStr = trainingFileList[i]
    fileStr = fileNameStr.split('.')[0]
    classNumStr = int(fileStr.split('_')[0])
    hwLabels.append(classNumStr)

    # 将样本数据存入矩阵
    trainingMat[i, :] = img2vector('./data/train/%s' % fileNameStr)


# 循环读取测试数据
testFileList = listdir('./data/test')
# 初始化错误率
testLabels = []
mTest = len(testFileList)
print(mTest)
vectorUnderTest = np.zeros((mTest, 784))  # 初始化样本数据矩阵
print(vectorUnderTest.shape)

# 循环测试每个测试数据文件
for i in range(mTest):
    # 提取文件名中的数字
    fileNameStr = testFileList[i]
    fileStr = fileNameStr.split('.')[0]
    classNumStr = int(fileStr.split('_')[0])
    testLabels.append(classNumStr)
    # 提取数据向量
    vectorUnderTest[i, :] = img2vector('./data/test/%s' % fileNameStr)


model = KNeighborsClassifier(n_neighbors=3)  # k=3
model = model.fit(trainingMat, hwLabels)    # 建立训练集向量
score = model.score(vectorUnderTest, testLabels)   # 对测试集进行测试
print(score)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值