python3机器学习实战 kNN识别手写数字

本文介绍了一个简单的手写数字识别系统实现方法。系统首先从文本文件中读取手写数字图像数据,并将其转换为向量形式。然后使用k近邻算法进行分类识别。文章详细展示了数据读取、图像向量化及分类器实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import numpy as np
import os
import operator

def img2vector(filename):
    """想不通为什么要用文本形式存数字,真是zz"""
    ret_val = np.zeros((1,1024))
    with open(filename,'r') as f:
        lines = f.readlines()
    for i1,line in enumerate(lines):
        for i2,c in enumerate(line.strip()):
            ret_val[0,i1*32+i2] = int(c)
    return ret_val

def handwriting_class_test():
    labels = []
    # 返回该文件夹下文件或文件夹名字,升序
    trainling_file_list = os.listdir('./trainingDigits')
    # 初始化一个空的训练矩阵,放一个个数据
    training_mat = np.zeros((len(trainling_file_list),1024))
    # 把文件一个个提取
    for i,item in enumerate(trainling_file_list):
        # 某一个文件
        file_name_str = item
        # 文件去后缀
        file_str = file_name_str.split('.')[0]
        # 这个文件代表数字几
        class_num_str = int(file_str.split('_')[0])
        # 把数字标签放进去
        labels.append(class_num_str)
        # 把文件变成向量并填到矩阵的一行
        training_mat[i,:] = img2vector('./trainingDigits/%s' % file_name_str)
    # 大部分和上面类似
    test_file_list = os.listdir('./testDigits')
    error = 0.
    for i,item in enumerate(test_file_list):
        file_name_str = item
        file_str = file_name_str.split('.')[0]
        class_num_str = int(file_str.split('_')[0])
        vector_under_test = img2vector('./testDigits/%s' % file_name_str)
        # 进行测试,k取3,在海量训练集中找最近的三个
        result = classify0(vector_under_test,training_mat,labels,3)
        # 想看匹配情况去掉注释
        # print("the classifier came back with: %d, the real answer is: %d"\
        #       % (result,class_num_str))
        # 分错了就计个数
        if(result != class_num_str) : error += 1.0
    # 显而易见
    print("the total number of errors is: %d" % error)
    print("the accuracy rate is: %f" % (1 - error/float(len(test_file_list))))

def classify0(in_x,dataset,labels,k):
    """简单分类器1"""
    # 行,也即点的个数,每个点一行表示,提取几行就几个点
    dataset_size = dataset.shape[0]
    # 纵向拓展一下输入的x,让它可以和原来的所有向量批量求差
    diff_mat = np.tile(in_x,(dataset_size,1)) - dataset

    # 求差的平方和
    sq_diff_mat = diff_mat**2
    # 在计算距离的时候,如果有个维度的数值很大,那么将直接影响计算的结果
    # 简单归一化new_value = (old_value - min)/(max-min)
    distance = (sq_diff_mat.sum(axis=1))**0.5 # 求与每一个点的距离平方,是列向量

    # 返回数组从小到大的索引,ndarray
    sorted_distance_indices = distance.argsort()
    # 弄个空的
    class_count = {}

    for i in range(k):
        # 把刚距离由小到大的label放进去
        vote_label = labels[sorted_distance_indices[i]]
        # 对每个label进行计数
        # dict.get前面是key,不存在赋0,存在返回原有的值
        class_count[vote_label] = class_count.get(vote_label,0)+1
    # 定义一个排序,排的是计数的所有内容,第二个域(第二维变量)
    # 改成operator.itemgetter(1,0)就会参造第二维先,再考虑第一维
    sorted_class_count = sorted(class_count.items(),
    key = operator.itemgetter(1),reverse=True)
    # 这里得到的B是[('B', 2), ('A', 1)]

    # 这个对应的就是标签号了
    return sorted_class_count[0][0]

def save_to_img(arr):
    # 随便把某个向量化后的数字放进来就能保存成图片
    import scipy.misc
    scipy.misc.imsave('outfile.jpg', arr)

def main():
    # arr = img2vector('./testDigits/5_13.txt')
    # arr = np.reshape(arr,(32,32))
    # save_to_img(arr)
    handwriting_class_test()

if __name__ == '__main__':
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值