前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用KNN识别MNIST手写数据集(手写,不使用KNeighborsClassifier)

使用KNN识别MNIST手写数据集(手写,不使用KNeighborsClassifier)

作者头像
全栈程序员站长
发布2022-07-22 13:38:18
2670
发布2022-07-22 13:38:18
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

数据集 提取码:mrfr

浏览本文前请先搞懂K近邻的基本原理:最简单的分类算法之一:KNN(原理解析+代码实现)

算法实现步骤:

  1. 数据处理。每一个数字都是一个32X32维的数据,如下所示:

knn中邻居一词指的就是距离相近。我们要想计算两个样本之间的距离,就必须将每一个数字变成一个向量。具体做法就是将32X32的数据每一行接在一起,形成一个1X1024的数据,这样我们就可以计算欧式距离。

  1. 计算测试数据到所有训练数据的距离,并按照从小到大排序,选出前K个
  2. 根据距离计算前K个样本的权重
  3. 将相同的训练样本的权重加起来,返回权重最大样本的标签

代码实现:

代码语言:javascript
复制
import os

def load_data(path):
    check = [i for i in range(10)]
    final_data = []
    
    for i in range(10):
        final_data.append([])
        
    files = os.listdir(path)    #文件夹
    for file in files:
        data = open(path + "/" + file)
        str = ""      #将所有数据接在一起
        temp = []
        for line in data.readlines():
            str = str + line[:-1]   #去掉回车,一行接一行
        for i in str:
            temp.append(int(i))   #变成数字
        final_data[check.index(int(file[0]))].append(temp)   #根据标签放在列表相应的位置

    return final_data, len(files)

def knn_mnist(K,test_data):
    train_data, length = load_data('manifold/digits/trainingDigits')
    distance = []     #存储测试数据到所有训练数据的距离
    
    for i in range(len(train_data)):
        for j in range(len(train_data[i])):
            res = 0
            for k in range(len(test_data)):
                res += (test_data[k]-train_data[i][j][k]) ** 2   #欧氏距离
            distance.append([res ** 0.5, i])   #距离+训练集数据标签

    distance = sorted(distance, key=(lambda x: x[0]))  #按距离从小到大排序
    weight = []   #权重与序号
    sum_distance = 0.0
    for i in range(K):
        sum_distance += distance[i][0]   #计算前K个距离的和
    for i in range(K):
        weight.append([1 - distance[i][0] / sum_distance, distance[i][1]])  #权重+序号
        
    #将相同序号的加起来
    num = []   #统计有哪些序号
    for i in range(K):
        num.append(weight[i][1])
    num = list(set(num))   #去重
    
    final_res = []
    for i in range(len(num)):
        res = 0.0
        for j in range(len(weight)):
            if weight[j][1] == num[i]:   #前K个标签一样的样本权值加起来
                res += weight[j][0]
        final_res.append([res, num[i]])

    final_res = sorted(final_res, key=(lambda x: x[0]),reverse=True)  # 按照权重从大到小排序

    return final_res[0][1]   #最终返回最大权值对应的标签

def test():
    K = 5
    test_data, length = load_data('manifold/digits/testDigits')
    #测试
    for i in range(len(test_data)):
        for j in range(len(test_data[i])):
            print(knn_mnist(K, test_data[i][j]))

if __name__ == '__main__':
    test()

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月6,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档