knn算法实现手写数字识别的背景_knn手写数字识别60000训练集

knn算法实现手写数字识别的背景_knn手写数字识别60000训练集KNN最邻近分类算法:(近邻取样)邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是机器学习分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。属于监督学习,有类别标记,且KNN是惰性学习。叫做Memory-basedlearning、也叫instance-basedlearning.他…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

KNN 最邻近分类算法:

(近邻取样)
邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是机器学习分类技术中最简单的方法之一。
所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。

属于监督学习,有类别标记,且KNN是惰性学习。叫做Memory-based learning、也叫instance-based learning. 他没有明显的前期训练过程,在程序运行之后,把数据加载到内存后,不需要进行训练就可以分类。

算法实现:
1、计算出每一个样本点与测试点的距离
2、选取距离最近的K个样本,并获取他们的标签 label
3、然后找出K个样本中数量最多的标签,返回该标签

KNN的本质是基于一种数据统计的方法。

下面的是KNN案例的应用:手写数字识别。
我这里的案例是文本格式。没有图片转换的步骤。
素材模型:(源码+素材最后会贴上githup的链接)

在这里插入图片描述

KNN 手写数字识别

实现思路:

  • 将测试数据转换成只有一列的0-1矩阵形式 将所有(L个)训练数据也都用上方法转换成只有一列的0-1矩阵形式

  • 把L个单列数据存入新矩阵A中——矩阵A每一列存储一个字的所有信息

  • 用测试数据与矩阵A中的每一列求距离,求得的L个距离存入距离数组中

  • 从距离数组中取出最小的K个距离所对应的训练集的索引 拥有最多索引的值就是预测值

第一步:
导入模块:

import os,time,operator             #导入os内置库来读取文件名     导入time来测试效率
import pandas as pd                 #导入数据处理库pandas        安装方法pip install pandas
import numpy as np                  #导入科学计算库numpy         安装方法pip install numpy
import matplotlib.pyplot as plt     #导入绘图库matplotlib        安装方法pip install matplotlib

第二步:
引入文件,定义一个读取数据的转换数据的函数

## print(len(tarining))      #1934个训练集                     ## print(len(test))   #945个测试集
trainingDigits =r'D:\work\日常任务6机器学习\day2手写数字识别\trainingDigits'
testDigits = r'D:\work\日常任务6机器学习\day2手写数字识别\testDigits'
                                                      ## ↑数据路径
tarining = (os.listdir(trainingDigits))                 ## 读取训练集
test = (os.listdir(testDigits))                        ## 读取测试集
def read_file(doc_name):                             ## 定义一个把32x32格式转为1行的函数
    data=np.zeros((1,1024))                         ## 创建1个zero数组
    f=open(doc_name)                               ## 打开文件
    for i in range(32):                          ## 已知每个文件中有32行32列
        hang=f.readline()                       ## 取行
        for j in range(32):                   ## 取每行中的每一列
            data[0,32*i+j]=int(hang[j])      ## 给data值
    # print(pd.DataFrame(data))             ## 不要在这里转换成DataFrame。
    return data                           ## 否则测试集效率会降低7倍
                                         ## 读取训练集效率会降低12倍

第三步:
定义一个字段转列表的函数,后面会用。
因为我为了提高效率没有使用pandas里面的Dataframe来操作数据。

def dict_list(dic:dict):               ## 定义函数将字典转化为列表
    keys = dic.keys()                 ## dic.keys()就是字典的k
    values = dic.values()            ## dic.values()就是字典的V
    lst = [(key,val) for  key,val in zip(keys, values)] ## for k,v in zip(k,v)
    return lst                        ## zip是一个可迭代对象
                                        ## 返回一个列表

第四步:
定义相似度函数:

def xiangsidu(tests,xunlians,labels,k):    ## tests:测试集 # xulians:训练样本集 # labels:标签 # k: 邻近的个数
    data_hang=xunlians.shape[0]              ## 获取训练集的行数data_hang
    zu=np.tile(tests,(data_hang,1))-xunlians   ## 用tile把测试集tests重构成一个 data_hang行、1列的1维数组
    q=np.sqrt((zu**2).sum(axis=1)).argsort()     ## 计算完距离后从低到高排序,argsort返回的是索引
    my_dict = {}                                   ## 设置一个dict
    for i in range(k):                              ## 根据我们的k来统计出现频率,样本类别
        votelabel=labels[q[i]]                         ## q[i]是索引值,通过labels来获取对应标签
        my_dict[votelabel] = my_dict.get(votelabel,0)+1   ## 统计每个标签的次数
    sortclasscount=sorted(dict_list(my_dict),key=operator.itemgetter(1),reverse=True)
                                                         ## 获取votelabel键对应的值,无返回默认
    return sortclasscount[0][0]                        ## 返回出现频次最高的类别

第五步:
编写识别函数:

def shibie():                                        ## 定义一个识别手写数字的函数
    label_list = []                                    ## 将训练集存储到一个矩阵并存储他的标签
    train_length = len(tarining)                        ## 直接一次获取训练集长度
    train_zero = np.zeros((train_length,1024))           ## 创建(训练集长度,1024)维度的zeros数组
    for i in range(train_length):                         ## 通过遍历训练集长度
        doc_name = tarining[i]                              ## 获取所有的文件名
        file_label = int(doc_name[0])                         ## 取文件名第一位文件的标签
        label_list.append(file_label)                           ## 将标签添加至handlabel中
        train_zero[i,:] = read_file(r'%s\%s'%(trainingDigits,doc_name))## 转成1024的数组
                                                                    ## 下面是测试集
    errornum = 0                                                  ## 记录error的初值
    testnum = len(test)                                         ## 同上 获取测试集的长度
    errfile = []                                              ## 定义一个空列表
    for i in range(testnum):                               ## 将每一个测试样本放入训练集中使用KNN进行测试
        testdoc_name = test[i]                           ## 通过i当作下标来获取测试集里面的文件
        test_label = int(testdoc_name[0])              ## 拿到测试文件的名字 拿到我们的数字标签
        testdataor = read_file(r'%s\%s' %(testDigits,testdoc_name)) ## 调用read_file操作测试集
        result = xiangsidu(testdataor, train_zero, label_list, 3)  ## 调用xiangsidu返回了result
        print("正在测试 %d, 内容是 %d" % (test_label,result))    ## 输出result和标签
        if (result != test_label):                               ## 判断标签是否等于测试名
            errornum += 1                                       ## 不是则+1 记录次数
            errfile.append(testdoc_name)                       ## 并把错误的文件名加入错误列表
    print("错误数量有 :%d" % errornum)                       ## 输出错误的数量
    print("错误的有 :%s"%[i for i in errfile])             ## 输出错误的列表中的名字
    print("准确率 %.2f%%" % ((1 - (errornum / float(testnum))) * 100)) ## 计算准确率

最后调用:

if __name__ == '__main__':                                        ## 声明主函数
    a = time.time()                                              ## 设置起始时间
    shibie()                                                   ## 调用测试函数
    b= time.time() - a                                       ## 计算运行时间
    print("运行时间:",b)                                   ## 输出运行时间

没啥太多好说的,为了改进效率在中间进行了很多技巧性的操作,虽然还是一堆for循环。
但是每个步骤的注释都写的很清楚,相信大家是可以看懂的,如有不懂请留言。

Github完整链接: https://github.com/lixi5338619/KNN_Distinguish/tree/master
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194026.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月13日 下午10:43
下一篇 2025年11月13日 下午11:22


相关推荐

  • 自组织网络(Ad hoc)

    自组织网络(Ad hoc)自组织网络 AdHoc 是一种移动通信和计算机网络相结合的网络 是移动计算机网络的一种 用户终端可以在网内随意移动而保持通信 作为一种多跳的临时性自治系统 在军事 民用 商用等许多重要领域都具有独特优势 随着移动技术的不断发展和人们日益增长的自由通信需求 AdHoc 网络会受到更多的关注 得到更快速的发展和普及 nbsp 现将收集的有关 adhoc 基础知识及信息整理如下 摘自百度百科 略有删

    2026年3月20日
    2
  • jQuery的Ajax实例(附完整代码)

    jQuery的Ajax实例(附完整代码)目录写在前边什么是AjaxAjax基本结构实例实例1实例2小结写在前边作为一个前端刚入门没多久的小白,想在这里分享一下我的学习内容,就算是学习笔记了。因为前端的大部分学习都是通过网站上的教程,所以遇到不懂得问题,也只有求助于网络,通过度娘,了解到了一些论坛、博客。在发现了众多技术大牛的同时,我也发现,一些像我这样的小白,由于能力有限,在查找相关资料的时候,对于大佬的一些操作理解困难,虽说能照猫…

    2022年7月26日
    11
  • pycharm运行python程序没有解释器怎么办

    pycharm运行python程序没有解释器怎么办1 选择设置 2 打开解释器选项 3 打开之后是这个样子 你的会和我的不太一样 我这个是装了解释器之后的 你的装了之后也是这个样子 4 添加解释器程序 5 在这里添加解释程序路径 然后点击 ok 就可以了 6 成功了的话 在这里会出现许多包名和属性

    2026年3月27日
    2
  • c# 字符串转时间的方式

    c# 字符串转时间的方式**第一种方法**stringtimeStr=”2019-08-28″;DateTimetime=Convert.ToDateTime(timeStr);**第二种:**DateTimeFormatInfotimeForInfo=newDateTimeFormatInfo();timeForInfo.ShortDatePattern=”yyyy/MM/dd”;stringtimeStr1=”2018-09-08″;vartime=Convert.

    2022年5月5日
    46
  • 微信小程序轮播图点击跳转页面

    微信小程序轮播图点击跳转页面index wmxl 代码 轮播图 viewclass swiperBanner swiperindica dots indicatorDot autoplay autoplay interval interval duration duration circular circular swiperindica dots indicatorDot autoplay autoplay interval interval duration duration circular circular viewclass swiperBanner

    2026年3月18日
    2
  • Obsidian 接入 DeepSeek API 完全指南:Copilot 插件配置教程

    Obsidian 接入 DeepSeek API 完全指南:Copilot 插件配置教程

    2026年3月13日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号