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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java 怎样卸载一个类_Java 动态卸载类[通俗易懂]

    java 怎样卸载一个类_Java 动态卸载类[通俗易懂]通过反射,我们可以动态的将类加载到方法区中,但是卸载这个类,却有着比较严苛的条件1.该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例。2.加载该类的ClassLoader已经被GC。3.该类的java.lang.Class对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法.publicstaticvoidmain(String[]args)th…

    2022年5月18日
    45
  • hive like与rlike的区别

    hive like与rlike的区别like与rlike的区别:like不是正则,而是通配符。这个通配符可以看一下SQL的标准,例如%代表任意多个字符。rlike是正则,正则的写法与java一样。’\’需要使用’\\’,例如’\w’需要使用’\\w’hive>select”aaaaa”like”%aaa%”fromtest_structlimit10;Totaljobs=1…OK

    2022年7月26日
    9
  • 思科交换机 flow control 交换机流控[通俗易懂]

    思科交换机 flow control 交换机流控[通俗易懂]配置IEEE802.3X流控制流控制在直连的以太端口上启用,在拥塞期间允许另一端拥塞的节点暂停链路运作来控制流量速率。如果一个端口发生拥塞并且不能接收任何更多的流量,他将通知对端端口停止发送直到这种拥塞情况消失。当本地设备在他本地检测到了任何拥塞,他能够发送一个暂停帧通知链路伙伴或者远程设备已发生拥塞。紧随收到暂停帧之后,远程设备停止发送任何…

    2022年6月5日
    92
  • redis的五种数据类型

    redis的五种数据类型一、百度百科1、简介(1)Redis(RemoteDictionaryServer远程字段服务)是一个开源的使用ANSIC语言编写、支持网络、科技与内存亦可持久化的日志型、key-value数据库,并提供多种语言的API。(2)Redis是一个key-value存储系统,它支持存储的value类型相对更多,包括string、list、set、zset(sortedset–有序集合)和hash。这些数据结构都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,

    2022年6月17日
    21
  • 感觉自己不会的东西太多了,不知道如何下手?

    感觉自己不会的东西太多了,不知道如何下手?GitHub8.8kStar的Java工程师成神之路,不来了解一下吗?GitHub8.8kStar的Java工程师成神之路,真的不来了解一下吗?GitHub8.8kStar的Java工程师成神之路,真的确定不来了解一下吗?如果让我统计下,粉丝问我做多的问题是什么,这个问题肯定可以排前5,问出这个问题的朋友们遍布各个年龄段。实话说,这个问题同样也困扰过我,大概就是我刚…

    2022年7月7日
    19
  • 新版卡盟官网源码_汇想卡盟官网

    新版卡盟官网源码_汇想卡盟官网最近,很多小伙伴们都在想搭建一个卡盟的主站,但是鉴于很多人都不太懂编程,也不知道如何找到源码。所以现在小编就为大家带来搭建卡盟主站教程,而且还把源码也一起送来了,想要搭建卡盟主站的话就记得一定要下载哦!搭建卡盟主站教程介绍1,完整无误经过校验的卡盟平台源码2,基于Ecshop内核的卡盟平台,游戏点卡销售的首选平台PHP+MYSQL3,前台模板已做深层SEO优化便于搜索引擎收录寻找卡盟源码1网…

    2022年8月13日
    11

发表回复

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

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