Realização de reconhecimento de dígitos manuscritos com base em matlab usando o algoritmo KNN

Realização de reconhecimento de dígitos manuscritos com base em matlab usando o algoritmo KNN

I. Introdução

  • O nome completo de KNN é K-Nearest Neighbors, K-Nearest Neighbors. Simplificando, K é o número de vizinhos, selecione os vizinhos que são mais semelhantes à amostra de teste (aqui estão os K vizinhos com a distância geométrica euclidiana mais curta), então qual é o vizinho da amostra e qual é a amostra (em K vizinhos, se o rótulo do vizinho for o número 1, então pensamos que o rótulo da amostra provavelmente será o número 1)
  • O princípio e o código do KNN para realizar o reconhecimento de escrita são relativamente simples, mas não existem muitos artigos relacionados na Internet. Este artigo apenas descreve meu próprio entendimento como uma prática de aprendizado de matlab. Há muitas omissões, por favor, avise

Em segundo lugar, o processo de realização

  1. Processe o conjunto de dados MNIST

    • Baixe o conjunto de dados MNIST , baixe um total de quatro arquivos: conjunto de teste, rótulo de teste, amostra de treinamento e rótulo de treinamento
    • O conjunto de dados baixado está no formato de arquivo IDX, então use Python para converter para uma imagem PNG 50 × 50, o código está na parte de trás
    • Escolha um número apropriado de conjuntos de teste e conjuntos de treinamento, o número de amostras de treinamento para cada número no conjunto de treinamento deve ser o mesmo
  2. Etapas de implementação do Matlab (com uma resolução de imagem de exemplo 50 × 50)

  • Binarizar todas as fotos: tire 1 se houver um valor, tire 0 se não houver valor

  • As amostras de treinamento de 0-9 números são matriculadas e cada imagem digital é uma matriz unidimensional. Tomando uma imagem de resolução de 50 × 50 como exemplo, uma matriz unidimensional de 1 × 2500 é obtida; para cada número de 860 imagens, obtemos uma matriz de 8600 × 2500, que é usada como a matriz de treinamento

  • Adicione uma coluna de rótulo à matriz de treinamento para determinar a qual número uma linha se refere

  • Para cada imagem digital a ser reconhecida, ela também é convertida em uma matriz unidimensional 1 × 2500, que é chamada de matriz de teste

  • Calcule a distância geométrica euclidiana de cada dimensão da matriz de teste e da matriz de treinamento, e também adicione o vetor coluna à matriz de treinamento e organize a matriz de treinamento por linhas em ordem crescente de distância

  • Encontre o modo do rótulo para os primeiros K vetores de linha, e o rótulo resultante é o resultado de reconhecimento mais provável obtido pelo algoritmo KNN


Três, implementação de código

  1. Processando o código Python do conjunto de dados MINIST, graças aos artigos name_s_Jimmy usando Python, os conjuntos de dados MNIST em imagens

    import numpy as np
    import struct
     
    from PIL import Image
    import os
     
    data_file =  #需要修改的路径,测试或训练样本图像,如t10k-images.idx3-ubyte或train-images.idx3-ubyte
    # It's 47040016B, but we should set to 47040000B
    data_file_size = 47040016
    data_file_size = str(data_file_size - 16) + 'B'
     
    data_buf = open(data_file, 'rb').read()
     
    magic, numImages, numRows, numColumns = struct.unpack_from(
        '>IIII', data_buf, 0)
    datas = struct.unpack_from(
        '>' + data_file_size, data_buf, struct.calcsize('>IIII'))
    datas = np.array(datas).astype(np.uint8).reshape(
        numImages, 1, numRows, numColumns)
     
    label_file =  #需要修改的路径,测试或训练样本标签,如t10k-labels.idx1-ubyte或train-labels.idx1-ubyte
     
    # It's 60008B, but we should set to 60000B
    label_file_size = 60008
    label_file_size = str(label_file_size - 8) + 'B'
     
    label_buf = open(label_file, 'rb').read()
     
    magic, numLabels = struct.unpack_from('>II', label_buf, 0)
    labels = struct.unpack_from(
        '>' + label_file_size, label_buf, struct.calcsize('>II'))
    labels = np.array(labels).astype(np.int64)
     
    datas_root = r'C:\Users\TITAN\Desktop\KNN\test' #需要修改的路径
    if not os.path.exists(datas_root):
        os.mkdir(datas_root)
     
    for i in range(10):
        file_name = datas_root + os.sep + str(i)
        if not os.path.exists(file_name):
            os.mkdir(file_name)
     
    for ii in range(10000):# 生成10000张测试或训练样本
        img = Image.fromarray(datas[ii, 0, 0:50, 0:50])
        label = labels[ii]
        file_name = datas_root + os.sep + str(label) + os.sep + \
            'mnist_train_' + str(ii) + '.png'
        img.save(file_name)
    
    print('Finished!')
    

  1. Código Matlab

    clc;
    clear;
    
    matrix = [];% 训练矩阵
    for delta = 0:9%构建训练区样本的矩阵
      label_path = strcat('C:\Users\ABC\Desktop\KNN\trian\',int2str(delta),'\');
      disp(length(dir([label_path '*.png'])));
      for i = 1:length(dir([label_path '*.png']))
            im = imread(strcat(label_path,'\',int2str(delta),'_',int2str(i-1),'.png'));
            %imshow(im);
            im = imbinarize(im);%图像二值化
            temp = [];
            for j = 1:size(im,1)% 训练图像行向量化
                temp = [temp,im(j,:)];
            end
            matrix = [matrix;temp];
      end
    end
    
    label = [];%在标签矩阵后添加标签列向量
     for i = 0:9
        tem = ones(length(dir([label_path '*.png'])),1) * i;
        label = [label;tem];
    end
    matrix = horzcat(matrix,label);%带标签列的训练矩阵
    
    %测试对象向量
    for delta = 0:9%构建测试图像的向量
        test_path = strcat('C:\Users\ABC\Desktop\KNN\test\',int2str(delta),'\');
        len = (length(dir([test_path '*.png'])));
        disp(len);
        p = 0;% 识别结果计数
        for i = 1:len
            vec = []; % 测试样本行向量化       
            test_im = imread(strcat('test2\',int2str(delta),'\',int2str(delta),'_',int2str(i-1),'.png'));
            imshow(test_im);
            test_im = imbinarize(test_im);
            for j = 1:size(test_im,1)
                vec = [vec,test_im(j,:)];
            end
    
            dis = [];
            for count = 1:length(dir([label_path '*.png'])) * 10
                row = matrix(count,1:end-1);% 不带标签的训练矩阵每一行向量
                distance = norm(row(1,:)-vec(1,:));% 求欧氏几何距离
                dis = [dis;distance(1,1)];% 距离列向量
            end
            test_matrix = horzcat(matrix,dis);% 加入表示距离的列向量
    
    
            %排序
            test_matrix = sortrows(test_matrix,size(test_matrix,2));
            %输入K值,前K个行向量标签的众数作为结果输出
            K = 5;
            result = mode(test_matrix(1:K,end-1));
            disp(strcat('图像',int2str(delta),'_',int2str(i),'.png','的识别结果是:',int2str(result)));
    
            if(delta == result)
                p = p + 1;
            end
            
            
        end
        pi = p/len;
        disp(strcat('识别精度为:',num2str(pi)));
        disp('Finished!'); 
    end
    

Quarto, o resultado

  • O algoritmo KNN (Vizinho Mais Próximo) é usado para realizar o reconhecimento de dígitos escritos à mão. Após o teste, a precisão geral é acima de 0,9 sob a condição de K = 5 e a amostra de treinamento é 8600. O reconhecimento de números individuais, como 8, é apenas cerca de 0,8.
  • O algoritmo KNN é simples, mas as deficiências também são óbvias, o tempo de execução é longo, é fácil convergir para o valor local e a precisão não é alta.
  • Aumentar o número de amostras de treinamento, ajustar o valor K e realizar o processamento preliminar da imagem antes de executar o algoritmo pode ter um melhor desempenho

Acho que você gosta

Origin blog.csdn.net/Taplus/article/details/112996077
Recomendado
Clasificación