Es gibt viele Materialien im Internet über die Grundlagen und Mechanismen des maschinellen Lernens, aber lassen Sie uns den Code tatsächlich schreiben! Ich denke, es ist schwer, das in den Griff zu bekommen. Besonders Chainer und Tensorflow sind nützlich, aber ich verstehe das überhaupt nicht, selbst wenn ich sie installiere, und einige Leute versuchen, das Beispiel zu verschieben und zu beenden, ohne sich zu bewegen. Darüber hinaus versteht das Bildmaterial, das im Bilderkennungsbeispiel mit dem Chainer geliefert wird, möglicherweise nicht, was es ist, wenn Sie versuchen, den Code zu lesen. Daher habe ich mich zunächst entschlossen, diesen Artikel zu schreiben, um ** das einfachste Beispiel für die handschriftliche Zeichenerkennung von Grund auf mithilfe von Chainer zu implementieren und den Mechanismus und das Schreiben von Code zu verstehen **. Ich habe vor kurzem angefangen, Chainer als Hobby zu studieren, aber ich bin ein Amateur. Mein Ziel ist es, mein Verständnis durch das Schreiben von Artikeln zu überprüfen. Darüber hinaus denke ich, dass hier für den Mechanismus und das Studium des neuronalen Netzwerks selbst hilfreich sein wird.
Bis ich den Chainer berührte, machte ich oft vollständige Kratzer mit der grundlegenden C-Sprache, und mir war immer bewusst, dass das Programm, das ich schrieb, "Eingabe ○, Ausgabe ×" war. Infolgedessen litt ich unter Beispielcode, bei dem der Code für die Eingabe von Daten, die Reihenfolge und Speicherung von Daten verborgen war und die Ausgabe nur die Informationen des Modells nach dem Training waren (lacht). Seit ich es gelernt habe, dachte ich, es wäre so, als gäbe es Ein- und Ausgänge. Es ist eine Bestrafung, die gezögert hat, die Bibliothek zu lesen.
Erstellen Sie eine Umgebung, in der Python ausgeführt werden kann. In meiner Umgebung habe ich python3.5 mit [pyenv] installiert (http://qiita.com/Kodaira_/items/feadfef9add468e3a85b). Versuchen Sie, Chainer mit Pip oder etwas anderem zu installieren. Als Referenz
chainer==1.13.0
Ich benutze. Zuerst müssen Sie die Eingabedaten abrufen und als Vektor lesen. chainer/example/mnist/ Sie finden den Code in data.py unten. Kopieren Sie ihn daher in Ihr Entwicklungsverzeichnis. Wieder als Magie
chainer_test.py
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, report, training, utils, Variable
from chainer import datasets, iterators, optimizers, serializers
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
from chainer.training import extensions
import data
Bitte schreiben Sie den Quellcode. Ich werde es dieser Quelldatei unten hinzufügen.
Es gibt vier Netzwerkkonfigurationen (Eingabe, verborgene Schicht 1, verborgene Schicht 2, Ausgabe). Die jeweiligen Abmessungen betragen 784, 100, 100, 10. Weil der Eingang 28 * 28 px ist. Für die Ausgabe werden 10 Dimensionen verwendet, um 0-9 auszudrücken.
chainer_test.py
class MLP(Chain):
def __init__(self):
super(MLP, self).__init__(
l1=L.Linear(784, 100),
l2=L.Linear(100, 100),
l3=L.Linear(100, 10),
)
def __call__(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
y = self.l3(h2)
return y
Es wird beschrieben als. Zunächst zu init, das die Schichtstruktur definiert. Es fühlt sich an, als würde sich die Vektordimension als 784-> 100, 100-> 100, 100-> 10 ändern. Als nächstes ist call der Ausbreitungszustand in jeder Schicht, dh die Berechnung der Vorwärtsbewegung. Die Feuerfunktion wird routinemäßig auf den Ausgang des Stratum Corneum im neuronalen Netz übertragen, dies wird jedoch vom Kettenhändler im Voraus vorbereitet, und hier wird F.relu () verwendet. Natürlich sollte es Tanh geben und so weiter.
Zusätzlich werden wir eine Funktion namens Predict erstellen, die persönlich wichtig ist. Der Grund ist, dass es schön ist, die Verlustrate zu trainieren und zu sehen, aber wenn Sie das trainierte neuronale Netz selbst verwenden, ist es schließlich schwierig zu verstehen, was die API ist. Es mag andere gute Möglichkeiten geben, aber ich werde mich selbst vorhersagen.
chainer_test.py
def predict(model, x_data):
x = Variable(x_data.astype(np.float32))
y = model.predictor(x)
return np.argmax(y.data, axis = 1)
Dies bedeutet, dass das trainierte Modell (später beschrieben) und der Eingabevektor (784 Dimensionen * N (Anzahl der Vektoren)) als Argumente verwendet werden, der Eingabevektor auf float32 gesetzt wird, die Eingabe in den Prädiktor eingegeben wird, die Ausgabe ausgegeben wird (Dimension 10) und das Maximum ist Gibt einen Index zurück, der eine Zahl enthält. Und so weiter. Dadurch erhalten Sie eine leicht verständliche Ausgabe.
Bereiten Sie die Daten vor.
chainer_test.py
batchsize = 100
datasize = 60000
N = 10000
mnist = data.load_mnist_data()
x_all = mnist['data'].astype(np.float32) / 255
y_all = mnist['target'].astype(np.int32)
x_train, x_test = np.split(x_all, [datasize])
y_train, y_test = np.split(y_all, [datasize])
Chargengröße und N werden später beschrieben. Speichern Sie die Daten mit data.load_mnist_data (). Als nächstes rufen mnist ['data'], ['target'] die Eingabe und ihre Klassifizierung ab. Anstatt alle vorbereiteten Daten für das Training zu verwenden, ist es normalerweise üblich, einige zu trainieren und den Rest zu testen. Auch diesmal haben wir zwei vorbereitet, x_traint und x_test.
Erstellen Sie ein Modell zur Vorbereitung auf das Lernen.
chainer_test.py
model = L.Classifier(MLP())
optimizer = optimizers.Adam()
optimizer.setup(model)
Bei einem Klassifizierungsproblem wie diesem wird L.Classifier (), das die Berechnung der Verlustfunktion und den Fehlerbericht implementiert, im Voraus erstellt. Geben Sie ihm daher die oben definierte Klasse und geben Sie sie als Modell aus. Der Optimierer ist ein hervorragendes Werkzeug, das automatisch gute Parameter basierend auf mathematischen Methoden einstellt.
Ich werde tatsächlich anfangen zu lernen.
chainer_test.py
for epoch in range(20):
print('epoch % d' % epoch)
indexes = np.random.permutation(datasize)
sum_loss, sum_accuracy = 0, 0
for i in range(0, datasize, batchsize):
x = Variable(np.asarray(x_train[indexes[i : i + batchsize]]))
t = Variable(np.asarray(y_train[indexes[i : i + batchsize]]))
optimizer.update(model, x, t)
sum_loss += float(model.loss.data) * batchsize
sum_accuracy += float(model.accuracy.data) * batchsize
print('train mean loss={}, accuracy={}'.format(sum_loss / datasize, sum_accuracy / datasize))
sum_loss, sum_accuracy = 0, 0
for i in range(0, N, batchsize):
x = Variable(np.asarray(x_test[i : i + batchsize]),volatile='on')
t = Variable(np.asarray(y_test[i : i + batchsize]),volatile='on')
loss = model(x, t)
sum_loss += float(loss.data) * batchsize
sum_accuracy += float(model.accuracy.data) * batchsize
print('test mean loss={}, accuracy={}'.format(sum_loss / N, sum_accuracy / N))
Epoche ist, wie oft das Lernen wiederholt wird. Dieses Mal werden wir jede Epoche trainieren und testen. Zum Zeitpunkt des Lernens wird das Array entsprechend neu angeordnet und die Stapelgröße wird wiederholt. Der eigentliche Test wird aus i mit einem Index von i + Batch-Größe (Eingabe, korrekte Antwortdaten) = (x, t) erstellt und vom Optimierer (Modell, x, t) trainiert. Wiederholen Sie danach diesen Vorgang und geben Sie die durchschnittliche Verlustrate und Genauigkeit aus. Der Test ist fast der gleiche.
Geben Sie dem trainierten Modell einen Vektor und prüfen Sie, ob die Antwort richtig ist.
chainer_test.py
p_test = np.empty((0, 784), float)
p_test = np.append(p_test, np.array([x_test[0]]), axis=0)
p_test = np.append(p_test, np.array([x_test[1]]), axis=0)
print(p_test)
print(predict(model, p_test))
print(y_test)
serializers.save_hdf5('myMLP.model',model)
p_test ist der Vektor der Eingabe, die Sie versuchen möchten. Diesmal war es mühsam, mich selbst vorzubereiten, daher verwendete ich den im Test verwendeten 0. und 1. Vektor als Vektordaten. Vielleicht möchten Sie mit einigen Werten herumspielen. Wenn ich versuche, es zu verwenden, erscheinen die ersten beiden von y_test als Rückgabewert von Predict. Dies bedeutet also, dass das Lernen erfolgreich ist (glaube ich).
In der letzten Zeile wird das Modell als Datei geschrieben. Sie können es jetzt wiederverwenden.
Chainer Mnist von Grund auf neu implementiert. Die japanische Übersetzungsseite war für diesen Test sehr hilfreich. Persönlich bin ich überrascht, wie einfach es ist, die Chainer-Klasse zu schreiben. In Zukunft möchte ich meine Freizeit nutzen, um über den Quellcode der Bibliothek selbst und die Implementierung von Imagenet von Grund auf neu zu schreiben.