TL;DR Sie können es auf dieser Seite versuchen. http://handwritten-classifier.app.ginrou.com/ Der Quellcode ist hier. https://github.com/ginrou/handwritten_classifier
Es ist so.
Es ist eine Anwendung, die das Eingabebild auf ein neuronales Netzwerk anwendet und ausgibt, welche Nummer eingegeben wurde. Der Quellcode basiert darauf. handgeschriebener_Klassifizierer
Dies kann hilfreich sein für diejenigen, die den Quellcode des neuronalen Netzwerks anzeigen und ihn schnell über eine Webanwendung verwenden möchten.
Es ist ein allgemeines 3-Schicht-Perzeptron, das aus einer Eingangsschicht-verborgenen Schicht-Ausgangsschicht besteht. Wir beschäftigen uns nicht mit tiefem Lernen. Die Sigmoidfunktion wird als Aktivierungsfunktion verwendet.
Das Folgende ist hilfreich für Details des Algorithmus.
Der Umriss ist wie folgt.
Von (0,0) bis (W, H) des Bildes wird ein eindimensionaler Vektor gebildet, und ein konstanter Term wird hinzugefügt, um das Eingangssignal $ {\ bf x} $ zu erzeugen.
Multiplizieren Sie $ {\ bf x} $ mit dem Gewicht $ w ^ 1_ {i, j} $, um die Eingabe $ z_ {in, i} $ in der verborgenen Ebene zu erhalten. Die Ausgabe der verborgenen Schicht wird erhalten, indem diese mit der Sigmoidfunktion multipliziert wird.
z_{in,i} = \sum_{j=0}^{N} w^1_{i,j} x_j \\
z_{out,i} = sigmoid(z_{in,i})
Darüber hinaus wird die Ausgabe $ z_ {out, i} $ der verborgenen Schicht multipliziert mit dem Gewicht $ w ^ 2_ {i, j} $ zur Eingabe $ y_ {in, i} $ in die Ausgabeebene, und die Sigmoidfunktion wird angewendet. Die endgültige Ausgabe ist $ y_ {out, i} $.
y_{in,i} = \sum_{j=0}^{N} w^2_{i,j} z_{out,j} \\
y_{out,i} = sigmoid(y_{in,i})
Die Ausgabe {\ bf y} ist ein 10-dimensionaler Vektor. Der mit dem größten Ausgabewert ist das Schätzergebnis.
Neuronale Netzwerkvariablen haben Gewichte $ {\ bf w ^ 1}, {\ bf w ^ 2} $. Lerne seinen Wert. Es ist wie folgt zusammengefasst. Das Schreiben / Lesen der gelernten Parameter wird ebenfalls hinzugefügt.
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']
Wir werden dieses neuronale Netzwerk trainieren.
Für den Datensatz habe ich MNIST-Datensatz verwendet. Einige der http://deeplearning.net/tutorial/gettingstarted.html sind im Pickle-Format, da das Parsen des Rohdatensatzes mühsam ist. Also habe ich das benutzt.
Da die Größe des Eingabebilds dieses Datensatzes 28 x 28 beträgt, beträgt die Größe der Eingabeebene 784 Dimensionen, die Ausgabeebene erkennt Zahlen von 0 bis 9, also 10 Dimensionen, und die Zwischenebene ist entsprechend auf 300 Dimensionen eingestellt.
Führen Sie es mit handwritten_classifier.py aus, das in Repository enthalten ist. Ich kann es schaffen
Es dauerte ungefähr 2-3 Minuten, um 50.000 Punkte des MNIST-Datensatzes zu trainieren, und die Genauigkeit betrug 92,52%.
Verwenden Sie das Nummernerkennungssystem mit diesem neuronalen Netzwerk aus dem Browser. Die Idee ist
Es ist ein Mechanismus. handwritten_classifier verwendet Flask, um ein Web-Frontend zu erstellen.
So können Sie mit JS den Helligkeitswert des Bildes von der Leinwand abrufen und senden.
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;
};
Wenn die Größe der Leinwand 28 x 28 beträgt, ist sie zu klein. Zeichnen Sie daher im Browser und auf eine große Leinwand Dann schrumpfen.
Der gesendete JSON ist
{"input":[0,0,255,255,,,,255]}
So was.
Das bekommen Sie bei 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})
Im vorherigen Repository
$ python app.py
Sie können es unter http: // localhost: 5000
versuchen.
Docker Weil es Docker mit Kleber unterstützt https://registry.hub.docker.com/u/ginrou/handwritten-classifier/ Kann mit verwendet werden. Wenn Sie es schnell ausprobieren möchten, können Sie es für Heroku bereitstellen.
Das Schreiben in Python macht es so kurz! Webanwendung, unerwartet schlechte Erkennungsgenauigkeit
Recommended Posts