[PYTHON] Créez une application Web qui reconnaît les nombres avec un réseau neuronal

TL;DR Vous pouvez l'essayer sur cette page. http://handwritten-classifier.app.ginrou.com/ Le code source est ici. https://github.com/ginrou/handwritten_classifier

スクリーンショット 2014-12-01 23.18.43.png C'est comme ça.

Composition globale

Il s'agit d'une application qui applique l'image d'entrée à un réseau neuronal et indique le numéro qui a été entré. Le code source est basé sur cela. handwritten_classifier

Cela peut être utile pour ceux qui souhaitent voir le code source du réseau neuronal et qui souhaitent l'utiliser rapidement à partir d'une application Web.

Implémentation d'un réseau de neurones

Il s'agit d'un perceptron général à 3 couches constitué d'une couche d'entrée cachée couche-sortie couche. Nous ne gérons pas l'apprentissage en profondeur. La fonction sigmoïde est utilisée comme fonction d'activation.

Ce qui suit sera utile pour les détails de l'algorithme.

Le plan est comme suit. neuralnetwork.png

De (0,0) à (W, H) de l'image est transformé en un vecteur unidimensionnel, et un terme constant est ajouté pour créer le signal d'entrée $ {\ bf x} $.

Multipliez $ {\ bf x} $ par le poids $ w ^ 1_ {i, j} $ pour obtenir l'entrée $ z_ {in, i} $ dans la couche cachée. La sortie de la couche cachée est obtenue en multipliant cela par la fonction sigmoïde.

z_{in,i} = \sum_{j=0}^{N} w^1_{i,j} x_j \\
z_{out,i} = sigmoid(z_{in,i})

De plus, la sortie $ z_ {out, i} $ de la couche cachée multipliée par le poids $ w ^ 2_ {i, j} $ devient l'entrée $ y_ {in, i} $ à la couche de sortie, et la fonction sigmoïde est appliquée. Le résultat final est $ y_ {out, i} $.

y_{in,i} = \sum_{j=0}^{N} w^2_{i,j} z_{out,j} \\
y_{out,i} = sigmoid(y_{in,i})

La sortie {\ bf y} est un vecteur à 10 dimensions. Celui avec la plus grande valeur de sortie est le résultat de l'estimation.

Les variables de réseau neuronal ont des poids $ {\ bf w ^ 1}, {\ bf w ^ 2} $. Apprenez sa valeur. Il se résume comme suit. L'écriture / lecture des paramètres appris est également ajoutée.

https://github.com/ginrou/handwritten_classifier/blob/master/NeuralNetwork.py

NeuralNetwork.py




#!/usr/bin/env python

from math import exp
import numpy

def sigmoid(x):
    return 1.0 / (1.0 + exp(-x))

def sigmoid_a(array):
    return numpy.vectorize(sigmoid)(array)

class NeuralNetwork:
    def __init__(self, in_size, hidden_size, out_size):
        self.hidden_weight = 0.1 * (numpy.random.random_sample((hidden_size, in_size+1)) - 0.5)
        self.output_weight = 0.1 * (numpy.random.random_sample((out_size, hidden_size+1)) - 0.5)

    def fit(self, x, t, update_ratio = 0.1):
        z, y = self.fire(x)
        dy = ( y - t ) *y * ( 1 - y )
        dz = (self.output_weight.T.dot(dy))[1:] * z * ( 1- z )

        output_input = numpy.r_[ numpy.array([1]), z ]
        self.output_weight -= update_ratio * dy.reshape(-1,1) * output_input

        hidden_input = numpy.r_[ numpy.array([1]), x ]
        self.hidden_weight -= update_ratio * dz.reshape(-1,1) * hidden_input

    def fire(self, x):
        z = sigmoid_a(self.hidden_weight.dot(numpy.r_[ numpy.array([1]), x ]))
        y = sigmoid_a(self.output_weight.dot(numpy.r_[ numpy.array([1]), z ]))
        return (z, y)

    def predicate(self, x):
        z, y = self.fire(x)
        return numpy.array(y).argmax()

    def save(self, filepath):
        numpy.savez(filepath, hidden = self.hidden_weight, output = self.output_weight)

    def load(self, filepath):
        npzfiles = numpy.load(filepath)
        self.hidden_weight = npzfiles['hidden']
        self.output_weight = npzfiles['output']

Apprentissage

Nous formerons ce réseau neuronal.

Pour l'ensemble de données, j'ai utilisé MNIST Data Set. Une partie de http://deeplearning.net/tutorial/gettingstarted.html est au format Pickle car l'analyse de l'ensemble de données brutes est fastidieuse. Alors j'ai utilisé ça.

Étant donné que la taille de l'image d'entrée de cet ensemble de données est de 28 x 28, la taille de la couche d'entrée est de 784 dimensions, la couche de sortie reconnaît les nombres de 0 à 9, donc il s'agit de 10 dimensions et la couche intermédiaire est correctement définie sur 300 dimensions.

Exécutez avec handwritten_classifier.py inclus dans Repository Je peux le faire.

Il a fallu environ 2-3 minutes pour former 50 000 points de l'ensemble de données MNIST, et la précision était de 92,52%.

Utilisation depuis une application Web

Utilisez le système de reconnaissance numérique en utilisant ce réseau neuronal à partir du navigateur. L'idée est

C'est un mécanisme. handwritten_classifier utilise Flask pour créer un frontal Web.

C'est comme ça pour obtenir la valeur de luminosité de l'image à partir du canevas avec JS et l'envoyer.

var estimate = function(context) {
   var img_buf = getImageBuffer(context, 28, 28);
    $.ajax({
        type:"post",
        url:"/estimate",
        data: JSON.stringify({"input": img_buf}),
        contentType: 'application/json',
        success: function(result) {
            $("#estimated").text("Estimated = " + result.estimated);
        }
    });
};

var getImageBuffer = function(context, width, height) {
    var tmpCanvas = $('<canvas>').get(0);
    tmpCanvas.width = width;
    tmpCanvas.height = height;
    var tmpContext = tmpCanvas.getContext('2d');
    tmpContext.drawImage(context.canvas, 0, 0, width, height);
    var image = tmpContext.getImageData(0,0,width,height);
    var buffer = []
    for( var i = 0; i < image.data.length; i += 4 ) {
        var sum = image.data[i+0] + image.data[i+1] + image.data[i+2] + image.data[i+3];
        buffer.push(Math.min(sum,255));
    }
    return buffer;
};

Si la taille de la toile est de 28 x 28, elle est trop petite, alors dessinez sur une grande toile sur le navigateur et Puis rétrécissez.

Le json envoyé est

{"input":[0,0,255,255,,,,255]}

Comme ça.

C'est ce que vous obtenez chez Flask

@app.route("/estimate", methods = ["POST"])
def estimate():
    try:
        x = numpy.array(request.json["input"]) / 255.0
        y = int(nn.predicate(x))
        return jsonify({"estimated":y})
    except Exception as e:
        print(e)
        return jsonify({"error":e})

Dans le référentiel précédent

$ python app.py

Vous pouvez l'essayer sur http: // localhost: 5000.

Docker Parce qu'il prend en charge Docker avec de la colle https://registry.hub.docker.com/u/ginrou/handwritten-classifier/ Peut être utilisé avec. Si vous voulez l'essayer rapidement, vous pouvez le déployer sur heroku.

Sentiments divers

L'écriture en Python le rend si court! Application Web, précision de reconnaissance étonnamment médiocre

Recommended Posts

Créez une application Web qui reconnaît les nombres avec un réseau neuronal
Créer une application Web avec Django
Tornado - Créons une API Web qui renvoie facilement JSON avec JSON
Créez une API Web capable de fournir des images avec Django
Composez avec un réseau neuronal! Run Magenta
[Python] Une application web rapide avec Bottle!
Créez une application Web simple avec Flask
Exécutez une application Web Python avec Docker
Créer un service Web avec Docker + Flask
J'ai fait une application WEB avec Django
Créez une application Web qui peut être facilement visualisée avec Plotly Dash
Expérimentez avec divers algorithmes d'optimisation sur le réseau neuronal
Créer une page qui se charge indéfiniment avec python
Créez un tableau de bord pour les appareils réseau avec Django!
Créez une application Hello World avec un seul fichier avec django
Facile à créer une application console Python avec Click
[kotlin] Créez une application qui reconnaît les photos prises avec un appareil photo sur Android
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
Je souhaite créer une application WEB en utilisant les données de League of Legends ①
Créez une application qui reconnaît les images en écrivant des chiffres à l'écran sur Android (PyTorch Mobile) [création de réseau CNN]
(Remarque) Une application Web qui utilise TensorFlow pour déduire les noms de morceaux recommandés [Créer un environnement d'exécution avec docker-compose]
Entraînez les données MNIST avec PyTorch en utilisant un réseau neuronal
environnement en ligne de serveur de code (2) Créer un réseau virtuel avec Boto3
Créez un chatbot prenant en charge la saisie gratuite avec Word2Vec
Lancer une application Web Python sur Nginx + Gunicorn avec Docker
Création d'une application Web qui mappe les informations sur les événements informatiques avec Vue et Flask
Implémenter un réseau neuronal à 3 couches
Créez une PythonBox qui sort avec Random après l'entrée PEPPER
Essayez de créer un réseau de neurones / d'apprentissage en profondeur avec scratch
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
Réseau de neurones avec Python (scikit-learn)
3. Distribution normale avec un réseau neuronal!
Créons un script qui s'enregistre avec Ideone.com en Python.
Créez un jeu de vie mis à jour manuellement avec tkinter
Développement d'applications Web avec Flask
Créer une page d'accueil avec django
Créer une application Web avec Django
Réseau de neurones commençant par Chainer
4. Entourez les paramètres avec un réseau neuronal!
Application Web avec Python + Flask ② ③
Créer un répertoire avec python
Construction d'un réseau neuronal qui reproduit XOR par Z3
[Golang] Un programme qui détermine le tour avec des nombres aléatoires
J'ai fait un générateur de réseau neuronal qui fonctionne sur FPGA
Application Web avec Python + Flask ④
Une histoire que j'ai eu du mal en essayant de créer une "application qui convertit des images comme des peintures" avec la première application Web
Notez que j'étais accro à accéder à la base de données avec mysql.connector de Python en utilisant une application Web
Créez rapidement un environnement d'exécution d'application Web Python3.4 + Nginx + uWSGI + Flask en utilisant pyenv sur Ubuntu 12.04
Créez un programme qui peut générer votre image préférée avec Selenium
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 1
Créer une application Web de type Flask / Bottle sur AWS Lambda avec Chalice
[Python / Django] Créer une API Web qui répond au format JSON
Pratique de développement d'applications Web: Créez une page de création d'équipe avec Django! (Page de création de décalage)
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 2
J'ai essayé de créer une liste de nombres premiers avec python
[LINE Messaging API] Créez un BOT qui se connecte à quelqu'un avec Python
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 3
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 4