Realización de reconocimiento de dígitos escritos a mano basado en matlab utilizando el algoritmo KNN

Realización de reconocimiento de dígitos escritos a mano basado en matlab utilizando el algoritmo KNN

I. Introducción

  • El nombre completo de KNN es K-Vecinos más cercanos, K-Vecinos más cercanos. En pocas palabras, K es el número de vecinos, seleccione los vecinos que sean más similares a la muestra de prueba (aquí están los K vecinos con la distancia geométrica euclidiana más corta), luego, ¿cuál es el vecino de la muestra y cuál es la muestra? (en K vecinos, si la etiqueta del vecino es el número 1, entonces pensamos que es probable que la etiqueta de la muestra sea el número 1)
  • El principio y el código de KNN para realizar el reconocimiento de escritura a mano son relativamente simples, pero no hay muchos artículos relacionados en Internet. Este artículo solo escribe mi propia comprensión como una práctica de aprendizaje de matlab. Hay muchas omisiones, por favor avise

En segundo lugar, el proceso de realización

  1. Procesar el conjunto de datos MNIST

    • Descargue el conjunto de datos de MNIST , descargue un total de cuatro archivos: conjunto de prueba, etiqueta de prueba, muestra de entrenamiento y etiqueta de entrenamiento
    • El conjunto de datos descargado está en formato de archivo IDX, así que use Python para convertir a una imagen PNG de 50 × 50, el código está en la parte posterior
    • Elija un número apropiado de conjuntos de prueba y conjuntos de entrenamiento, el número de muestras de entrenamiento para cada número en el conjunto de entrenamiento debe ser el mismo
  2. Pasos de implementación de Matlab (con una resolución de imagen de 50 × 50 ejemplo)

  • Binarizar todas las imágenes: tome 1 si hay un valor, tome 0 si no hay ningún valor

  • Las muestras de entrenamiento de números del 0 al 9 se matriculan y cada imagen digital es una matriz unidimensional. Tomando una imagen de resolución 50 × 50 como ejemplo, se obtiene una matriz unidimensional de 1 × 2500; por cada número de 860 imágenes, obtenemos una matriz de 8600 × 2500, que se utiliza como matriz de entrenamiento.

  • Agregue una columna de etiqueta a la matriz de entrenamiento para determinar a qué número se refiere una fila

  • Para que cada imagen digital sea reconocida, también se convierte en una matriz unidimensional de 1 × 2500, que se denomina matriz de prueba.

  • Calcule la distancia geométrica euclidiana de cada dimensión de la matriz de prueba y la matriz de entrenamiento, y también agregue el vector de columna a la matriz de entrenamiento, y organice la matriz de entrenamiento por filas en orden ascendente de distancia.

  • Encuentre la moda de la etiqueta para los primeros K vectores de fila, y la etiqueta resultante es el resultado de reconocimiento más probable obtenido por el algoritmo KNN


Tres, implementación de código

  1. Procesando el código Python del conjunto de datos MINIST gracias a los artículos de name_s_Jimmy que usan Python, los conjuntos de datos MNIST se convertirán en imágenes

    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 de 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
    

Cuarto, el resultado

  • El algoritmo KNN (vecino más cercano) se utiliza para realizar el reconocimiento de dígitos escritos a mano. Después de la prueba, la precisión general es superior a 0.9 bajo la condición de K = 5 y la muestra de entrenamiento es 8600. El reconocimiento de números individuales como 8 es solo alrededor de 0,8.
  • El algoritmo KNN es simple, pero las deficiencias también son obvias, el tiempo de ejecución es largo, es fácil de converger al valor local y la precisión no es alta.
  • Aumentar la cantidad de muestras de entrenamiento, ajustar el valor de K y realizar el procesamiento de imagen preliminar antes de ejecutar el algoritmo puede tener un mejor rendimiento

Supongo que te gusta

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