[Apprentissage automatique] Ecrivez vous-même la méthode k-plus proche voisin en python et reconnaissez les nombres manuscrits.

La dernière fois a utilisé la méthode de correspondance des modèles pour identifier les nombres manuscrits, mais cette fois nous avons changé la méthode et la méthode du k-plus proche voisin. ) Sera utilisé.

k Aperçu de la méthode du plus proche voisin

Tout d'abord, les grandes lignes de la méthode sont les suivantes. Si les points noirs sont utilisés comme données cibles d'identification, comme indiqué dans la figure ci-dessous, k données d'enseignants proches les unes des autres sont recherchées et l'étiquette avec le plus grand nombre de décisions à la majorité est sélectionnée comme valeur estimée. Dans le cas de cet exemple, il y a 3 "5" et 2 "8", donc "5" sera adopté comme valeur estimée. Les caractéristiques sont qu'il s'agit d'une analyse supervisée et que toutes les données sont utilisées pour le calcul, ce qui consomme la taille de la mémoire et la quantité de calcul. Il existe plusieurs concepts de «proche» tels que la distance ordinaire (distance euclidienne) et la distance de Maharanobis (en utilisant la dispersion), mais cette fois nous utiliserons la distance ordinaire.

plot4.png

Mettre en place##

Je vais l'écrire en Python à la fois. Tout d'abord, importez les bibliothèques nécessaires. Je n'utiliserai pas la bibliothèque d'apprentissage automatique telle que sklearn cette fois. (Parce que je suis seul)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from collections import defaultdict

Définissez une classe appelée TrainDataSet. Puisqu'il s'agit de données d'enseignant, il contient l'étiquette de résultat (numéro manuscrit) et les données de pixels afin que vous puissiez facilement récupérer les données nécessaires, telles que l'extraction d'éléments spécifiques.

class TrainDataSet():
    def __init__(self, data):
        data = np.array(data)
        
        self.labels = data[:,0]
        self.data_set = data[:,1:]
        
    def __repr__(self):
        ret  = repr(self.labels) + "\n"
        ret += repr(self.data_set)
        return ret
        
    def get_data_num(self):
        return self.labels.size
        
    def get_labels(self, *args):
        if args is None:
            return self.labels
        else:
            return self.labels[args[0]]
    def get_data_set(self):
        return self.data_set
        
    def get_data_set_partial(self, *args):
        if args is None:
            return self.data_set
        else:
            return self.data_set[args[0]]
    def get_label(self, i):
        return self.labels[i]
    def get_data(self, i):
        return self.data_set[i,:]
    def get_data(self,i, j):
        return self.data_set[i][j]

Chargez ensuite les données. Si vous souhaitez l'essayer, vous pouvez télécharger les données à partir de ce qui suit. train.csv ... Données des enseignants (42000) test_small.csv ... Données cibles d'identification (200 pièces)

size = 28
master_data= np.loadtxt('train_master.csv',delimiter=',',skiprows=1)
test_data= np.loadtxt('test_small.csv',delimiter=',',skiprows=1)

train_data_set = TrainDataSet(master_data)

Il définit également une fonction qui agrège les résultats de k voisins et génère une liste du nombre de données disponibles pour chaque étiquette numérique.

def get_list_sorted_by_val(k_result, k_dist):
    result_dict = defaultdict(int)
    distance_dict = defaultdict(float)
    
    #Agréger par étiquette de numéro
    for i in k_result:
        result_dict[i] += 1
    
    #Distance totale agrégée pour chaque étiquette numérique
    for i in range(len(k_dist)):
        distance_dict[k_result[i]] += k_dist[i]
    
    #Conversion du type de dictionnaire en liste (pour le tri)
    result_list = []
    order = 0
    for key, val in result_dict.items():
        order += 1
        result_list.append([key, val, distance_dict[key]])
    
    #Convertir en type ndarray
    result_list = np.array(result_list) 

    return result_list

Maintenant que toutes les préparations sont terminées, le processus d'identification commence ici. Cette fois, sélectionnez k = 5 données comme voisinage.

k = 5
predicted_list = []    #Valeur prédite de l'étiquette numérique
k_result_list  = []    #k liste des quartiers
k_distances_list = []  #Liste des distances entre les nombres k et les données à identifier

# execute k-nearest neighbor method
for i in range(len(test_data)):
  
    #Faites la différence entre les données cibles d'identification et les données de l'enseignant
    diff_data = np.tile(test_data[i], (train_data_set.get_data_num(),1)) - train_data_set.get_data_set()
    
    sq_data   = diff_data ** 2       #Équerre chaque élément et effacer le signe
    sum_data  = sq_data.sum(axis=1)  #Additionnez chaque élément vectoriel
    distances = sum_data ** 0.5      #Prenez la route et utilisez-la comme distance
    ind = distances.argsort()        #Trier par ordre croissant de distance et extraire l'indice
    k_result = train_data_set.get_labels(ind[0:k]) #Retirez k pièces de la plus proche
    k_dist   = distances[ind[0:k]]   #Extraire les informations de distance k
    
    k_distances_list.append(k_dist)
    k_result_list.append(k_result)
    
    #Agrégé à partir de k données avec des étiquettes numériques,(Étiquette de numéro,Quantité,distance)Générer une liste de
    result_list = get_list_sorted_by_val(k_result, k_dist)
    candidate = result_list[result_list[:,1].argsort()[::-1]]

    counter = 0
    min = 0
    label_top = 0
    
    #S'il existe plusieurs étiquettes numériques avec le plus grand nombre, sélectionnez celle avec la distance totale la plus petite.
    result_dict = {}
    for d in candidate:
        if d[1] in result_dict:
            result_dict[d[1]] += [(d[0], d[2])]
        else:
            result_dict[d[1]] =  [(d[0], d[2])]

    for d in result_dict[np.max(result_dict.keys())]:
        if counter == 0:
            label_top = d[0]
            min = d[1]
        else:
            if d[1] < min:
                label_top = d[0]
                min = d[1]
        counter += 1
                
    #Mettez les résultats dans une liste
    predicted_list.append(label_top)

Affichez le résultat.

# disp calc result
print "[Predicted Data List]"
for i in range(len(predicted_list)):
    print ("%d" % i) + "\t" + str(predicted_list[i])

print "[Detail Predicted Data List]"
print "index k units of neighbors, distances for every k units"
for i in range(len(k_result_list)):
    print ("%d" % i) + "\t" + str(k_result_list[i]) + "\t" + str(k_distances_list[i])

Le fichier de résultat de sortie est ici, et le résultat de la comparaison de la valeur prédite identifiée comme la bonne réponse est [ici](https: //gist.github. Il est situé à l'adresse com / matsuken92 / 7ca89520ff4e9d2242b0). Cette fois, j'ai essayé d'identifier 200 pièces en utilisant la méthode du k plus proche voisin, mais le taux d'identification a considérablement augmenté à 97% (194/200)! Je pense que ce sera pratique si l'identification est si bonne. Dernière fois Dans le cas de la mise en correspondance de modèles effectuée, il était de 80%, donc c'est assez bon comparé à cela.

Analyse des données d'échec

Les 6 données suivantes ont échoué, mais cela semble gênant même visuellement. La première donnée de la rangée inférieure est même visuelle de 6 ou 4. On peut dire que la plupart des nombres manuscrits peuvent être identifiés par la méthode du k plus proche voisin, sauf pour les plus subtils.


counter = 0
for d, num in zip(test_data, [3,76,128,132,147,165]):
    counter += 1
    X, Y = np.meshgrid(range(size),range(size))
    Z = test_data[num].reshape(size,size)
    Z = Z[::-1,:]
    flat_Z = Z.flatten()
    plot_digits(X, Y, Z, 2, 3, counter, "pred=%d" % predicted_list[num])

knn_fault.png

** détails des données d'échec **

index label pred k-nearest digits remarks
3 0 9 [ 0. 9. 9. 9. 2.] Le quartier le plus proche est 0, mais ... c'est délicieux.
76 9 8 [ 8. 8. 9. 8. 3.] Il y a aussi un 9 mais ...
128 7 1 [ 8. 1. 7. 8. 1.] Ne mettez pas de lignes supplémentaires dans 7 ...
132 4??? 6 [ 6. 6. 6. 6. 6.] C'est 4 ou 6 ou même visuellement subtile
147 4 7 [ 7. 7. 7. 7. 7.] Je me demande si c'est 7
165 3 2 [ 3. 2. 2. 2. 3.] 3 était aussi une bonne ligne, mais ...

Recommended Posts

[Apprentissage automatique] Ecrivez vous-même la méthode k-plus proche voisin en python et reconnaissez les nombres manuscrits.
Méthode de voisinage #k d'apprentissage automatique et sa mise en œuvre et divers
Mémo d'apprentissage Python pour l'apprentissage automatique par Chainer chapitres 1 et 2
Implémentation de la méthode k-voisinage en python à partir de scikit learn
[Apprentissage automatique] "Détection d'anomalies et détection de changement" Dessinons la figure du chapitre 1 en Python.
2. Analyse multivariée expliquée dans Python 8-1. Méthode de voisinage k (scikit-learn)
Une implémentation Python simple de la méthode k-voisinage (k-NN)
Le résultat de l'apprentissage automatique des ingénieurs Java avec Python www
Une méthode concrète pour prédire les courses de chevaux et simuler le taux de récupération par apprentissage automatique
Apprentissage automatique ④ Résumé du K-plus proche voisin
2. Analyse multivariée énoncée dans Python 8-3. Méthode de voisinage K [vérification d'intersection]
Effectuer une analyse morphologique dans l'environnement d'apprentissage automatique lancé par GCE
Classification et régression dans l'apprentissage automatique
Python: prétraitement dans l'apprentissage automatique: présentation
Notez que je comprends l'algorithme du classificateur Naive Bayes. Et je l'ai écrit en Python.
2. Analyse multivariée expliquée dans Python 8-2. Méthode de voisinage k [méthode de pondération] [modèle de retour]
Procédure d'apprentissage automatique de base: ③ Comparez et examinez la méthode de sélection de la quantité de caractéristiques
Mémo d'apprentissage Python pour l'apprentissage automatique par Chainer jusqu'à la fin du chapitre 2
Python: prétraitement en machine learning: gestion des données manquantes / aberrantes / déséquilibrées
[Python] [scikit-learn] k-Introduction au mémo de la méthode du voisin le plus proche
Ecrire le test dans la docstring python
[python] Techniques souvent utilisées dans l'apprentissage automatique
Ecrire le fichier O_SYNC en C et Python
Python: prétraitement en machine learning: acquisition de données
Lisez le fichier ligne par ligne avec Python
Lire et écrire des fichiers JSON avec Python
Créer un environnement pour Python et l'apprentissage automatique (macOS)
Python: prétraitement dans l'apprentissage automatique: conversion de données
Mémo d'étude Python & Machine Learning ④: Machine Learning par rétro-propagation
Algorithme d'alignement par méthode d'insertion en Python
[Python] Précautions lors de l'acquisition de données en grattant et en les mettant dans la liste
Défis d'apprentissage automatique de Coursera en Python: ex3 (reconnaissance de nombres manuscrits avec récursivité logistique)
Divise la chaîne de caractères par le nombre de caractères spécifié. En Ruby et Python.
Liste des principales distributions de probabilité utilisées en apprentissage automatique et statistiques et code en python
Conversion de Fourier du fichier wav lu par Python, conversion inverse et réécriture
J'ai essayé de prédire l'évolution de la quantité de neige pendant 2 ans par apprentissage automatique
Machine Learning avec docker (40) avec anaconda (40) "Hands-On Data Science and Python Machine Learning" Par Frank Kane
Obtenez le dernier élément du tableau en fractionnant les chaînes en Python et PHP
Apprenez le modèle de conception "Méthode de modèle" en Python
J'ai essayé la méthode des moindres carrés en Python
Pour remplacer dynamiquement la méthode suivante en python
Apprenez le modèle de conception "Méthode d'usine" en Python
À propos de la différence entre "==" et "is" en python
Conseils pour rédiger un aplatissement concis en python
Touchons une partie de l'apprentissage automatique avec Python
Essayez d'implémenter la méthode Monte Carlo en Python
Suivi d'objets à l'aide d'OpenCV3 et de Python3 (suivi des points caractéristiques spécifiés par la souris à l'aide de la méthode Lucas-Kanade)