[DL4J] Erstes Java Deep Learning (Handschriftliche Zeichenerkennung über ein vollständig verbundenes neuronales Netzwerk)

Hallo. Obwohl es ein Seetag ist, ist Tokio immer noch cool.

Heute, am 15. Juli 2019, betrug die höchste Temperatur in Tokio 25 ° C und die niedrigste Temperatur 19 ° C. Nach den Aufzeichnungen der Meteorologischen Agentur sind die durchschnittlichen Höchst- und Mindesttemperaturen in Tokio von 1981 bis 2010 wie folgt.

Durchschnittliche Maximaltemperatur Durchschnittliche Mindesttemperatur
29.0℃ 21.7℃

(Quelle: https://www.data.jma.go.jp/obd/stats/etrn/view/nml_sfc_d.php?prec_no=44&block_no=47662&year=0month=7&day=1view=p1)

Persönlich mag ich das aktuelle Klima, weil es leicht zu verbringen ist, aber wie lange wird es dauern?

Deeplearning4j / DL4J

In diesem Artikel wird nun ** Deeplearning4j ** oder ** DL4J ** vorgestellt, entwickelt von ** Skymind **. Wie der Name schon sagt, ist DL4J ein Deep-Learning-Entwicklungsframework **, das in ** JVM-Sprachen wie ** Java **, ** Scala ** und ** Kotlin ** ausgeführt wird. Weitere bekannte Deep-Learning-Frameworks sind TensorFlow von Google, integrierte Keras, PyTorch von FaceBook und Chainer von Preferred Networks. Grundsätzlich wird davon ausgegangen, dass diese Frameworks in Python entwickelt wurden, und Sie können mit einer kleinen Anzahl von Codes problemlos recherchieren und entwickeln.

DL4J wird als ** Enterprise Framework ** unterschieden, da es in der JVM-Sprache geschrieben werden kann, die in Unternehmenssystemen weit verbreitet ist. ** Eines der Verkaufsargumente ist die Möglichkeit, eine native Verbindung zu Big-Data-Analyseplattformen wie Hadoop und Spark herzustellen **.

Schauen wir uns ein Beispiel für den Aufbau eines neuronalen Netzwerks mit DL4J an.

DL4J-Beispielcode

Der DL4J-Beispielcode ist im offiziellen Repository reichlich verfügbar. https://github.com/deeplearning4j/dl4j-examples

Die Skalierung ist zu groß, um es zu versuchen. Klonen Sie daher das folgende Repository, das diesmal nur Code enthält.

python


$ git clone https://github.com/kmotohas/oreilly-book-dl4j-examples-ja

Dies ist die japanische Version von "Deep Learning-A Practitioner's Approach", geschrieben von Adam Gibson et al., Der Autor von DL4J selbst. Detaillierte Erklärung Deep Learning-Ansatz für Praktiker "](https://www.amazon.co.jp/dp/4873118808/) ist ein öffentliches Repository für Beispielcode.

Als einfaches Beispiel wird der handgeschriebene numerische Standarddatensatz MNIST von einem mehrschichtigen Perzeptron (MLP, auch ein vollständig verbundenes neuronales Netzwerk in einer losen Definition) erkannt MLPMnistTwoLayerExample.java Werfen wir einen Blick auf den Inhalt von -dl4j-examples-ja / blob / master / dl4j-examples / src / main / java / org / deeplearning4j / examples / feedforward / mnist / MLPMNistTwoLayerExample.java).

Es wird empfohlen, das Beispiel mit einer integrierten Entwicklungsumgebung wie Intellij IDEA auszuführen. Es ist jedoch auch möglich, es über die Befehlszeile mit einem Build-Tool wie Maven auszuführen.

Übersicht über MLPMnistTwoLayerExample.java

Der folgende Code ist der gesamte Code, wobei die Anweisung "import" am Anfang weggelassen wird.

python


public class MLPMnistTwoLayerExample {

    private static Logger log = LoggerFactory.getLogger(MLPMnistSingleLayerExample.class);

    public static void main(String[] args) throws Exception {
        //number of rows and columns in the input pictures
        final int numRows = 28;
        final int numColumns = 28;
        int outputNum = 10; // number of output classes
        int batchSize = 64; // batch size for each epoch
        int rngSeed = 123; // random number seed for reproducibility
        int numEpochs = 15; // number of epochs to perform
        double rate = 0.0015; // learning rate

        //Get the DataSetIterators:
        DataSetIterator mnistTrain = new MnistDataSetIterator(batchSize, true, rngSeed);
        DataSetIterator mnistTest = new MnistDataSetIterator(batchSize, false, rngSeed);


        log.info("Build model....");
        MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
            .seed(rngSeed) //include a random seed for reproducibility
            .activation(Activation.RELU)
            .weightInit(WeightInit.XAVIER)
            .updater(new Nesterovs(rate, 0.98)) //specify the rate of change of the learning rate.
            .l2(rate * 0.005) // regularize learning model
            .list()
            .layer(0, new DenseLayer.Builder() //create the first input layer.
                    .nIn(numRows * numColumns)
                    .nOut(500)
                    .build())
            .layer(1, new DenseLayer.Builder() //create the second input layer
                    .nIn(500)
                    .nOut(100)
                    .build())
            .layer(2, new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD) //create hidden layer
                    .activation(Activation.SOFTMAX)
                    .nIn(100)
                    .nOut(outputNum)
                    .build())
            .build();

        MultiLayerNetwork model = new MultiLayerNetwork(conf);
        model.init();
        model.setListeners(new ScoreIterationListener(5));  //print the score with every iteration

        log.info("Train model....");
        for( int i=0; i<numEpochs; i++ ){
        	log.info("Epoch " + i);
            model.fit(mnistTrain);
        }


        log.info("Evaluate model....");
        Evaluation eval = new Evaluation(outputNum); //create an evaluation object with 10 possible classes
        while(mnistTest.hasNext()){
            DataSet next = mnistTest.next();
            INDArray output = model.output(next.getFeatures()); //get the networks prediction
            eval.eval(next.getLabels(), output); //check the prediction against the true class
        }

        log.info(eval.stats());
        log.info("****************Example finished********************");
    }
}

Die Hauptmethode dieser Klasse ist grob in die folgenden vier Teile unterteilt.

  1. Vorbereitung von DataSetIterator

Ich werde jeden Teil der Reihe nach erklären.

1. Vorbereitung von DataSetIterator

Das Training eines Modells in Deep Learning ist der Prozess der Eingabe eines Datensatzes in das Modell und der Aktualisierung der Parameter, um den Unterschied zwischen der erwarteten und der tatsächlichen Ausgabe zu minimieren.

In DL4J wird [DataSetIterator](https://github.com/eclipse/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-api-parent/nd4j] als Iterator verwendet, um Daten iterativ in das Modell einzuspeisen. Eine Klasse mit dem Namen api / src / main / java / org / nd4j / linalg / dataset / api / iterator / DataSetIterator.java wird bereitgestellt. (Tatsächlich [implementiert] in der ND4J-Bibliothek, die auch als JVM-Version von Numpy bezeichnet werden kann (https://github.com/eclipse/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-api-parent/nd4j-api/src/main) /java/org/nd4j/linalg/dataset/api/iterator/DataSetIterator.java). Es erbt java.util.Iterator und java.io.Serializable.)

Der MNIST-Datensatz handgeschriebener Textnummern enthält 70.000 handgeschriebene Zahlenbilder und korrekte Beschriftungen (auf den Bildern gezeichnete Zahlen. Informationen zu 0,1,2,3, ..., 9). Im Allgemeinen werden diese aufgeteilt und 60.000 werden als Trainingsdatensätze und 10.000 als Testdatensätze für die Leistungsbewertung verwendet.

image.png

(Quelle: https://weblabo.oscasierra.net/python/ai-mnist-data-detail.html)

Wie in der folgenden Abbildung gezeigt, kann es weiter in Verifizierungsdaten für die Optimierung von Hyperparametern wie die Lernrate unterteilt werden, diesmal wird es jedoch nicht behandelt.

image.png

(Quelle: https://www.procrasist.com/entry/10-cross-validation)

Wie andere Frameworks verfügt DL4J über einen Iterator für MNIST. Es gibt auch Iteratoren für andere bekannte Datensätze wie CIFAR-10 und Tiny ImageNet. Weitere Informationen finden Sie in der offiziellen Dokumentation (https://deeplearning4j.org/docs/latest/deeplearning4j-nn-iterators).

Informationen wie "RecordReaderDataSetIterator" für eigene Bilder und Datensätze wie CSV und "SequenceRecordReaderDataSetIterator" für Sequenzdaten befinden sich ebenfalls auf derselben Seite.

python


        //Get the DataSetIterators:
        DataSetIterator mnistTrain = new MnistDataSetIterator(batchSize, true, rngSeed);
        DataSetIterator mnistTest = new MnistDataSetIterator(batchSize, false, rngSeed);

Hier haben wir einen Iterator für das Training und einen Iterator für das Testen. Quellcode für MnistDataSetIterator Aus /MnistDataSetIterator.java) werde ich den diesmal verwendeten Konstruktor zitieren.

python


public MnistDataSetIterator(int batchSize, boolean train, int seed)

Die Argumente sind wie folgt.

--int batchSize: Die Größe des Mini-Batches, dh die Anzahl der Proben, die in einer Trainingsiteration in das Modell eingegeben werden sollen. --boolean train: Boolescher Wert, der angibt, ob es sich um Trainingsdaten oder Testdaten handelt --int seed: Zufälliger Startwert beim Mischen eines Datensatzes

2. Einstellung von "MultiLayerConfiguration"

Dies ist der Teil, in dem das neuronale Netzwerk entworfen wird. Verwenden Sie "MultiLayerConfiguration", um Ebenen für Keras nacheinander zu stapeln.

Wenn Sie ein Netzwerk mit komplizierten Zweigen aufbauen möchten, verwenden Sie "ComputationGraphConfiguration". Es ist wie die funktionale API von Keras. Weitere Informationen finden Sie in diesem Dokument.

python


        MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
            .seed(rngSeed) //include a random seed for reproducibility
            .activation(Activation.RELU)
            .weightInit(WeightInit.XAVIER)
            .updater(new Nesterovs(rate, 0.98)) //specify the rate of change of the learning rate.
            .l2(rate * 0.005) // regularize learning model
            .list()
            .layer(0, new DenseLayer.Builder() //create the first input layer.
                    .nIn(numRows * numColumns)
                    .nOut(500)
                    .build())
            .layer(1, new DenseLayer.Builder() //create the second input layer
                    .nIn(500)
                    .nOut(100)
                    .build())
            .layer(2, new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD) //create hidden layer
                    .activation(Activation.SOFTMAX)
                    .nIn(100)
                    .nOut(outputNum)
                    .build())
            .build();

MultiLayerConfiguration ist im sogenannten [Builder-Muster] implementiert (https://qiita.com/disc99/items/840cf9936687f97a482b). Sie können Ihr Netzwerk anpassen, indem Sie Parameter in der Form ". " angeben.

python


        MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
            .seed(rngSeed) //include a random seed for reproducibility
            .activation(Activation.RELU)
            .weightInit(WeightInit.XAVIER)
            .updater(new Nesterovs(rate, 0.98)) //specify the rate of change of the learning rate.
            .l2(rate * 0.005) // regularize learning model
            .list()

In der oberen Hälfte werden die Parameter für das gesamte Netzwerk festgelegt. Insbesondere werden die folgenden Einstellungen vorgenommen.

python


            .layer(0, new DenseLayer.Builder() //create the first input layer.
                    .nIn(numRows * numColumns)
                    .nOut(500)
                    .build())
            .layer(1, new DenseLayer.Builder() //create the second input layer
                    .nIn(500)
                    .nOut(100)
                    .build())
            .layer(2, new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD) //create hidden layer
                    .activation(Activation.SOFTMAX)
                    .nIn(100)
                    .nOut(outputNum)
                    .build())
            .build();

Die untere Hälfte gibt die Schichtstruktur des neuronalen Netzwerks an.

Die 0. Verbindung verwendet eine "dichte Schicht" mit einer Eingabe von $ 28 \ mal 28 = $ 784 Dimensionen und einer Ausgabe von 500 Dimensionen. Das MNIST-Bild hat eine Höhe von 28 Pixel, eine Breite von 28 Pixel und Schwarzweiß, sodass die Anzahl der Kanäle 1 beträgt. Um dies in die vollständig verbundene Schicht einzugeben, ist es im Allgemeinen notwendig, von einer $ 28 \ mal 28 $ -Matrix in einen Vektor umzuwandeln. Diese Arbeit ist jedoch nicht erforderlich, da sie bereits flach im Iterator für MNIST von DL4J aufgezeichnet ist. Die 500-dimensionale Zahl in der Ausgabe hat hier keine Bedeutung und ist ein Hyperparameter, der frei eingestellt werden kann. Diese Zahl ist nicht immer der optimale Wert.

In ähnlicher Weise hat die erste Verbindung eine "DenseLayer" mit einer Eingabe von 500 Dimensionen (der gleiche Wert wie die 0. Ausgabe) und einer Ausgabe von 100 Dimensionen. Es klingt unangenehm, aber die Zahl 100-dimensional ist ein Wert, der von no bestimmt wird, und er hat keine Bedeutung.

Die zweite Verbindung ist speziell und verwendet "OutputLayer". Die Eingabe hat 100 Dimensionen wie in der vorherigen Verbindung, und die Ausgabe gibt die Anzahl der Datenbeschriftungen 10 (0 bis 9) an. Die Aktivierungsfunktion wird mit Activation.SOFTMAX überschrieben und LossFunction.NEGATIVELOGLIKELIHOOD als Verlustfunktion gesetzt. Die Softmax-Funktion ist eine Funktion, die zum Konvertieren des Eingabewerts als Wahrscheinlichkeit (ein positiver Wert mit einer Summe von 1) verwendet wird und eine Menge mit negativer Log-Wahrscheinlichkeit (negative logarithmische Wahrscheinlichkeit) bei der Lösung eines Klassifizierungsproblems für mehrere Klassen ist. Es ist benutzt.

Das Bild des hier eingestellten Modells ist wie folgt.

image.png

3. Erstellen Sie "MultiLayerNetwork"

Erstellen Sie eine Instanz von "MultiLayerNetwork" mit "MultiLayerConfiguration" als Argument, um ein neuronales Netzwerk zu erstellen!

python


        MultiLayerNetwork model = new MultiLayerNetwork(conf);
        model.init();

4. Training des konstruierten neuronalen Netzwerkmodells

python


        model.setListeners(new ScoreIterationListener(5));  //print the score with every iteration
        for( int i=0; i<numEpochs; i++ ){
        	log.info("Epoch " + i);
            model.fit(mnistTrain);
        }

Danach können Sie das neuronale Netzwerk trainieren, indem Sie "fit (DataSetIterator iterator)" von "MultiLayerNetwork" mit dem Iterator der Trainingsdaten als Argument aufrufen. Die Trainingsdaten werden nicht nur einmal verwendet, sondern grundsätzlich mehrfach wiederholt. Diese sich wiederholende Einheit wird als Epoche bezeichnet.

Es ist auch möglich, einen Listener einzustellen, der den Trainingsstatus überwacht. Dies ist ein Bild von Keras 'Rückruf. ScoreIterationListener (int printIterations) druckt den Score (Verlustfunktionswert) in der Standardausgabe nach jeder angegebenen Anzahl von Iterationen (in der DL4J-Terminologie ist eine Iteration des Gewichtungsparameters eine Iteration). ..

Begriffe hier finden Sie im offiziellen Glossar (https://skymind.ai/wiki/glossary). Beachten Sie, dass beim Trainieren eines Datensatzes mit 1000 Proben mit einer Mini-Batch-Größe von 100 eine Epoche 10 Iterationen umfasst. Wenn Sie für 30 Epochen trainieren, entspricht dies 300 Iterationen.

Sie können "CheckpointListener" verwenden, wenn Sie das Modell nicht nur nach Abschluss des Trainings, sondern auch in der Mitte speichern möchten, oder Sie können "EvaluativeListener" verwenden, wenn Sie die Leistung in der Mitte bewerten möchten. Weitere Hörer finden Sie in der offiziellen Dokumentation (https://deeplearning4j.org/docs/latest/deeplearning4j-nn-listeners).

5. Leistungsbewertung des trainierten Modells

python


        Evaluation eval = new Evaluation(outputNum); //create an evaluation object with 10 possible classes
        while(mnistTest.hasNext()){
            DataSet next = mnistTest.next();
            INDArray output = model.output(next.getFeatures()); //get the networks prediction
            eval.eval(next.getLabels(), output); //check the prediction against the true class
        }

        log.info(eval.stats());

Für die Bewertung der Modellleistung unter Verwendung von Testdaten [public Evaluation (int num Classes)](https://github.com/eclipse/deeplearning4j/blob/master/deeplearning4j/deeplearning4j-nn/src/main/java/ Verwenden Sie eine Instanz von org / deeplearning4j / eval / Evaluation.java). Drehen Sie den Testiterator "mnistTest", rufen Sie den Datenvektor mit der Methode "getFeatures ()" ab und leiten Sie das trainierte Modell ["public INDArray output (INDArray input)" (https://github.com/) ab. eclipse / deeplearning4j / blob / master / deeplearning4j / deeplearning4j-nn / src / main / java / org / deeplearning4j / nn / multilayer / MultiLayerNetwork.java). Beschriften Sie dieses Inferenzergebnis und testen Sie die Daten [public void eval (INDArray realOutcomes, INDArray-Vermutungen)](https://github.com/eclipse/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-api- parent / nd4j-api / src / main / java / org / nd4j / Evaluierung / Klassifizierung / Evaluation.java) Beim Vergleich mit der Methode und Anzeige des Ergebnisses mit "eval.stats ()" wird die Genauigkeit / Präzision / Rückruf / F1-Punktzahl angezeigt Sie können den Wert überprüfen.

Weitere Informationen finden Sie in der offiziellen Dokumentation (https://deeplearning4j.org/docs/latest/deeplearning4j-nn-evaluation).

abschließend

Es ist lange her, aber jetzt [MLPMnistTwoLayerExample.java](https://github.com/kmotohas/oreilly-book-dl4j-examples-ja/blob/master/dl4j-examples/src/main/java/org/ Die Erklärung von deeplearning4j / examples / feedforward / mnist / MLPMNistTwoLayerExample.java) ist beendet.

  1. Vorbereitung von DataSetIterator

Mit Schritten wie können Sie Deep Learning auch mit Java oder Scala problemlos trainieren und bewerten. Wenn Sie Fragen oder Kommentare haben, verwenden Sie bitte den Kommentarbereich unten oder Gitters deeplearning4j-jp-Kanal.

Für detailliertere Informationen empfehlen wir O'Reilly Japans Detaillierter Deep Learning-Ansatz für Praktiker.

Recommended Posts

[DL4J] Erstes Java Deep Learning (Handschriftliche Zeichenerkennung über ein vollständig verbundenes neuronales Netzwerk)
Zum ersten Mal Java lernen [Einführung]
Lernnotiz beim ersten Lernen von Java (persönliches Lernnotiz)
Einführung in Java zum ersten Mal # 2
Erste Schritte für tiefes Lernen in Java
Deep Learning von Grund auf neu Java Kapitel 4 Lernen neuronaler Netze
[Deep Learning von Grund auf neu] in Java 3. Neuronales Netzwerk
Eindrücke und Zweifel an der erstmaligen Verwendung von Java in Android Studio
[Deep Learning von Grund auf neu] in Java 1. Zur Zeit Differenzierung und teilweise Differenzierung
Zum ersten Mal lernen Java # 3 Ausdrücke und Operatoren
Zusammenfassung der Punkte, die Java-Programmierer beim ersten Lesen der Kotlin-Quelle als rutschig empfinden
[Rails] Ich habe zum ersten Mal versucht, die button_to-Methode zu verwenden
Backpropagation Neural Network Java Code zum Lernen des XOR-Gate-Musters
Erstmaliges Modellieren von Digimon mit DDD Teil 1
Spring Boot zum ersten Mal
Spring AOP zum ersten Mal
[Erstes Java] Machen Sie etwas, das vorerst mit Intellij funktioniert
[Socket-Kommunikation (Java)] Eindrücke von der erstmaligen Implementierung der Socket-Kommunikation in der Praxis
Erste Programmierung in meinem Leben Java 1st Hello World
Die Geschichte, absichtlich zum ersten Mal in meinem Leben Try Catch zu verwenden
Eine Geschichte über einen Super-Anfänger, der zum ersten Mal am AtCoder-Wettbewerb teilnimmt (AtCoder-Anfängerwettbewerb 140)