基于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)
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个示例代码,但需要先明确一些前置条件: 1. 数据集的格式需要是 .csv 或 .txt 文件,并且以逗号或空格分隔。 2. 数据集需要包含标签列,即最后一列为分类标签。 3. PyCharm需要安装以下库:numpy、pandas、matplotlib、scikit-learn。 代码如下: ```python import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClassifier from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler # 读取数据集 data = pd.read_csv('dataset.csv') # 分离特征和标签 X = data.iloc[:, :-1].values y = data.iloc[:, -1].values # 特征标准化 scaler = StandardScaler() X = scaler.fit_transform(X) # PCA降维 pca = PCA(n_components=2) X = pca.fit_transform(X) # 可视化降维后的数据 plt.scatter(X[:, 0], X[:, 1], c=y) plt.xlabel('Principal Component 1') plt.ylabel('Principal Component 2') plt.show() # 分割训练集和测试集 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 构建KNN分类器 classifier = KNeighborsClassifier(n_neighbors=5) classifier.fit(X_train, y_train) # 预测测试集结果 y_pred = classifier.predict(X_test) # 计算准确率 from sklearn.metrics import accuracy_score accuracy = accuracy_score(y_test, y_pred) print('Accuracy:', accuracy) ``` 其中,`dataset.csv` 是您要使用的数据集文件名,`n_components` 是PCA降维后的维度数,`n_neighbors` 是KNN分类器中的邻居数。 您可以根据自己的需求修改代码中的参数。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值