[PYTHON] Create a web application that recognizes numbers with a neural network

TL;DR You can try it on this page. http://handwritten-classifier.app.ginrou.com/ The source code is here. https://github.com/ginrou/handwritten_classifier

スクリーンショット 2014-12-01 23.18.43.png It is like this.

Overall composition

It is an application that applies the input image to a neural network and outputs which number was input. The source code is based on this. handwritten_classifier

It may be helpful for those who want to see the source code of neural networks and want to use it quickly from a web application.

Neural network implementation

It is a general 3-layer perceptron consisting of an input layer-hidden layer-output layer. We do not handle deep learning. The sigmoid function is used as the activation function.

The following will be helpful for details of the algorithm.

The outline is as follows. neuralnetwork.png

The image from (0,0) to (W, H) is made into a one-dimensional vector, and a constant term is added to make the input signal $ {\ bf x} $.

Multiply $ {\ bf x} $ by the weight $ w ^ 1_ {i, j} $ to get the input $ z_ {in, i} $ to the hidden layer. The output of the hidden layer is obtained by multiplying this by the sigmoid function.

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

Furthermore, the output $ z_ {out, i} $ of the hidden layer multiplied by the weight $ w ^ 2_ {i, j} $ becomes the input $ y_ {in, i} $ to the output layer, and the sigmoid function is applied. What is the final output $ y_ {out, i} $.

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

The output {\ bf y} is a 10-dimensional vector. The one with the largest output value is the estimation result.

Neural network variables have weights $ {\ bf w ^ 1}, {\ bf w ^ 2} $. Learn its value. It is summarized as follows. Writing / reading of learned parameters is also added.

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']

Learning

We will train this neural network.

For the data set, I used MNIST data set. Some of the http://deeplearning.net/tutorial/gettingstarted.html is in Pickle format because parsing the raw dataset is a hassle. So I used this.

Since the size of the input image of this dataset is 28x28, the size of the input layer is 784 dimensions, the output layer recognizes numbers from 0 to 9, so it is 10 dimensions, and the intermediate layer is appropriately set to 300 dimensions.

Run on handwritten_classifier.py included in Repository I can do it.

It took about 2-3 minutes to train 50,000 points of the MNIST data set, and the accuracy was 92.52%.

Use from a web app

Use the number recognition system using this neural network from the browser. The idea is

It is a mechanism. handwritten_classifier uses Flask to create a web front end.

It is like this to get the brightness value of the image from canvas with JS and send it.

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;
};

If the size of the canvas is 28x28, it is too small, so draw on a large canvas on the browser and Then shrink.

The json sent is

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

Like this.

This is what you get at 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})

In the previous repository

$ python app.py

You can try it at http: // localhost: 5000.

Docker Because it supports Docker with glue https://registry.hub.docker.com/u/ginrou/handwritten-classifier/ Can be used with. If you want to try it quickly, you may want to deploy it on heroku.

Miscellaneous feelings

Writing in Python makes it so short! Web application, unexpectedly poor recognition accuracy

Recommended Posts

Create a web application that recognizes numbers with a neural network
Build a web application with Django
Tornado-Let's create a Web API that easily returns JSON with JSON
Create a web API that can deliver images with Django
Compose with a neural network! Run Magenta
[Python] A quick web application with Bottle!
Create a simple web app with flask
Run a Python web application with Docker
Create a web service with Docker + Flask
I made a WEB application with Django
Create a web app that can be easily visualized with Plotly Dash
Experiment with various optimization algorithms with a neural network
Create a page that loads infinitely with python
Create a dashboard for Network devices with Django!
Create a one-file hello world application with django
Create a Python console application easily with Click
[kotlin] Create an app that recognizes photos taken with a camera on android
The story of making a web application that records extensive reading with Django
I want to create a web application that uses League of Legends data ①
Create an application that recognizes images by writing numbers on the screen on android (PyTorch Mobile) [CNN network creation]
(Note) A web application that uses TensorFlow to infer recommended song names [Create an execution environment with docker-compose]
Train MNIST data with a neural network in PyTorch
code-server Online environment (2) Create a virtual network with Boto3
Create a chatbot that supports free input with Word2Vec
Launch a Python web application with Nginx + Gunicorn with Docker
I made a web application that maps IT event information with Vue and Flask
Implement a 3-layer neural network
Create a PythonBox that outputs with Random after PEPPER Input
Try to build a deep learning / neural network with scratch
Create a web surveillance camera with Raspberry Pi and OpenCV
Neural network with Python (scikit-learn)
3. Normal distribution with neural network!
Let's create a script that registers with Ideone.com in Python.
Create a life game that is manually updated with tkinter
Web application development with Flask
Create a homepage with django
Web application creation with Django
Neural network starting with Chainer
Create a heatmap with pyqtgraph
4. Circle parameters with neural network!
Web application with Python + Flask ② ③
Create a directory with python
Construction of a neural network that reproduces XOR by Z3
[Golang] A program that determines the turn with random numbers
I made a neural network generator that runs on FPGA
Web application with Python + Flask ④
A story that I had a hard time trying to create an "app that converts images like paintings" with the first web application
Note that I was addicted to accessing the DB with Python's mysql.connector using a web application.
Create a Python3.4 + Nginx + uWSGI + Flask Web application execution environment with haste using pyenv on Ubuntu 12.04
Create a program that can generate your favorite images with Selenium
If you know Python, you can make a web application with Django
Let's make a WEB application for phone book with flask Part 1
Build a Flask / Bottle-like web application on AWS Lambda with Chalice
[Python / Django] Create a web API that responds in JSON format
Web App Development Practice: Create a Shift Creation Page with Django! (Shift creation page)
Let's make a WEB application for phone book with flask Part 2
I tried to create a list of prime numbers with python
[LINE Messaging API] Create a BOT that connects with someone with Python
Let's make a WEB application for phone book with flask Part 3
Create a poster with matplotlib to visualize multiplication tables that remember multiplication
Let's make a WEB application for phone book with flask Part 4