["Deep Learning von Grund auf neu - die Theorie und Implementierung des in Python erlernten Deep Learning"] (https://www.oreilly.co.jp/books/9784873117584/) (geschrieben von Yasuki Saito, O'Reilly Japan) ist ein Buch, das Deep Learning von Anfang an erklärt. Ich verwende Python als Programmiersprache, aber dieser Beitrag (und die folgende Reihe von Beiträgen) implementiert es in Java. Allerdings [Deep Learning von Grund auf neu] Es ist kein Ersatz für (https://www.oreilly.co.jp/books/9784873117584/), wird jedoch unter der Annahme beschrieben, dass es zusammen gelesen wird.
Numpy
[Deep Learning von Grund auf neu] (https://www.oreilly.co.jp/books/9784873117584/) verwendet NumPy als Bibliothek für die numerische Berechnung. Dieser Beitrag verwendet ND4J. ND4J ist eine Bibliothek für Java, die ähnliche Funktionen wie NumPy und Matlib hat. Es ist berühmt für seine Verwendung in Open Source Deeplearning4J. Die Dokumentation ist jedoch nicht sehr gut organisiert. Es ist notwendig zu lernen, wie man es durch Versuch und Irrtum benutzt. ND4J kann die GPU über CUDA verwenden. Ich denke, es ist vorteilhaft für die Beschleunigung.
Matplotlib
[Deep Learning von Grund auf neu] (https://www.oreilly.co.jp/books/9784873117584/) verwendet Matplotlib als Bibliothek zum Zeichnen von Diagrammen. Diagramme sind für Deep Learning nicht unbedingt erforderlich, daher wird in diesem Beitrag keine Bibliothek zum Zeichnen von Diagrammen verwendet.
[Deep Learning von Grund auf neu] Die in Python geschriebenen Programme, die in (https://www.oreilly.co.jp/books/9784873117584/) angezeigt werden, werden nacheinander in Java neu geschrieben. Schreiben Sie es als JUnit-Code, um sicherzustellen, dass die Ergebnisse gleich sind. Zum Beispiel sieht es wie folgt aus.
public class C1_5_NumPy {
@Test
public void C1_5_2_Generierung eines NumPy-Arrays() {
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 3.0});
assertEquals("[1.00,2.00,3.00]", Util.string(x));
}
}
Dies ist eine Java-Version des Beispielprogramms, das in "1 Einführung in Python 1.5 NumPy 1.5.2 Generieren von NumPy-Arrays" angezeigt wird. Da Japanisch für Klassennamen und Methodennamen verwendet wird, funktioniert es je nach Umgebung möglicherweise nicht. In meiner Umgebung funktioniert es einwandfrei (Windows 10 + Eclipse Oxygen.2 Release 4.7.2). Da nur die Abschnitte beschrieben werden, in denen der Python-Code geschrieben ist, sind die Artikelnummern der Überschriften keine Seriennummern. Alle in Java geschriebenen Programme werden auf GitHub unter saka1029 / Deep.Learning veröffentlicht.
Die folgenden Abhängigkeiten müssen in pom.xml festgelegt werden, um ein Projekt auf GitHub zu erstellen.
<dependencies>
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-native-platform</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
Sie müssen auch die Projekteinstellungen in der IDE festlegen, um * Java 8 * zu verwenden. Mit Java 9 kann der Klassenlader zur Laufzeit eine Ausnahme auslösen.
1.5 ND4J
[Deep Learning von Grund auf neu] (https://www.oreilly.co.jp/books/9784873117584/) beschreibt Python, Numpy und Matplotlib in Kapitel 1, aber dieser Beitrag beschreibt nur ND4J.
In ND4J lautet der Array-Typ INDArray. Verwenden Sie zum Initialisieren mit einem Anfangswert die Factory-Methode der Nd4j-Klasse wie folgt. Util.string (INDArray) ist eine Zeichenfolge des Inhalts des Arrays Es ist eine selbst erstellte Dienstprogrammfunktion, die konvertiert werden soll.
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 3.0});
assertEquals("[1.00,2.00,3.00]", Util.string(x));
Die vier Regeln eines eindimensionalen Arrays lauten wie folgt.
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 3.0});
INDArray y = Nd4j.create(new double[] {2.0, 4.0, 6.0});
assertEquals("[3.00,6.00,9.00]", Util.string(x.add(y)));
assertEquals("[-1.00,-2.00,-3.00]", Util.string(x.sub(y)));
assertEquals("[2.00,8.00,18.00]", Util.string(x.mul(y)));
assertEquals("[0.50,0.50,0.50]", Util.string(x.div(y)));
INDArray .mul (INDArray) ist eine Multiplikation für jedes Element, und das Matrixprodukt ist [INDArray](https: / /nd4j.org/doc/org/nd4j/linalg/api/ndarray/INDArray.html). mmul (INDArray). INDArray hat auch add (Number), sub (Number), mul (Number), div Da (Number) überladen ist, können die vier Betriebsregeln mit dem Skalarwert auf die gleiche Weise ausgeführt werden. Die Substanz von x ist ein zweidimensionales Array mit 1 Zeile und 3 Spalten. Bitte beachten Sie, dass sich dieser Punkt von NumPy unterscheidet. INDArray .rank () gibt die Dimensionen des Arrays zurück.
assertArrayEquals(new int[] {1,3}, x.shape());
assertEquals(2, x.rank());
Es ist dieselbe Idee wie NumPy, da es INDArray verwendet, selbst wenn es zwei oder mehr Dimensionen aufweist. Gehen Sie wie folgt vor, um ein zweidimensionales Array mit Anfangswerten zu erstellen.
INDArray A = Nd4j.create(new double[][] {{1, 2}, {3, 4}});
assertEquals("[[1.00,2.00],[3.00,4.00]]", Util.string(A));
assertArrayEquals(new int[] {2,2}, A.shape());
assertEquals(2, A.rank());
Mit NumPy ist es möglich, vier Regeln auszuführen, wie dies zwischen Arrays mit unterschiedlichen Dimensionen der Fall ist. Mit ND4J ist dies jedoch nicht möglich. Sie müssen die Dimensionen explizit mit der Methode INDArray.broadcast (int []) ausrichten. .. Wenn Sie dies vergessen, wird eine IllegalStateException ausgelöst.
INDArray A = Nd4j.create(new double[][] {{1, 2}, {3, 4}});
INDArray B = Nd4j.create(new double[] {10, 20});
//INDArray-Methode mul(INDArray)Und hinzufügen(INDArray)Sendet nicht automatisch.
// broadcast(int[])Sie müssen verwenden, um die linke Seitenabmessung anzupassen.
assertEquals("[[10.00,40.00],[30.00,80.00]]", Util.string(A.mul(B.broadcast(A.shape()))));
//IllegalStateException bei einfacher Multiplikation:Es werden nicht übereinstimmende Formen sein.
try {
assertEquals("[[10.00,40.00],[30.00,80.00]]", Util.string(A.mul(B)));
fail();
} catch (IllegalStateException e) {
assertEquals("Mis matched shapes", e.getMessage());
}
//Oder mulRowVector(INDArray)Sie können auch verwenden.
assertEquals("[[10.00,40.00],[30.00,80.00]]", Util.string(A.mulRowVector(B)));
INDArray implementiert die Iterable-Schnittstelle nicht. Es gibt auch keine Methode, die einen Iterator zurückgibt. Der Zugriff auf das Element muss über Indizes erfolgen. INDArray.getDouble (int ...) zum Abrufen von Elementen, [INDArray] zum Abrufen von Zeilen (https://nd4j.org/doc/org/nd4j/linalg/api/ndarray/INDArray.html).getRow (int), INDArray zum Abrufen von Spalten Verwenden Sie org / nd4j / linalg / api / ndarray / INDArray.html) .getColumn (int). Verwenden Sie die Methode Nd4j.toFlattened (INDArray), um ein zweidimensionales Array in ein eindimensionales zu ändern.
INDArray X = Nd4j.create(new double[][] {{51, 55}, {14, 19}, {0, 4}});
assertEquals("[[51.00,55.00],[14.00,19.00],[0.00,4.00]]", Util.string(X));
assertEquals("[51.00,55.00]", Util.string(X.getRow(0)));
assertEquals(55.0, X.getDouble(0, 1), 5e-6);
//INDArray implementiert die Iterable-Schnittstelle nicht.
for (int i = 0, size = X.size(0); i < size; ++i)
assertEquals(2, X.getRow(i).size(1));
//Konvertiere X in einen Vektor.
X = Nd4j.toFlattened(X);
assertEquals("[51.00,55.00,14.00,19.00,0.00,4.00]", Util.string(X));
//Sie können auch alle angegebenen Elemente abrufen.
assertEquals("[51.00,14.00,0.00]", Util.string(X.getColumns(0, 2, 4)));
Wenn man sich die bisherigen Beispiele ansieht, scheint das INDArray das Doppelarray intern zu halten, da es mit dem Doppelarray initialisiert wird. ND4J reserviert jedoch standardmäßig eine Reihe von Floats. Die Dokumentation enthält die folgende Beschreibung:
** Datentypeinstellung ** ND4J ermöglicht derzeit das Sichern mit INDArray mit float- oder doppelter Genauigkeit. Die Standardeinstellung ist einfache Genauigkeit (float). Um ND4J so zu konfigurieren, dass für das gesamte Array die doppelte Genauigkeit verwendet wird, können Sie Folgendes verwenden: ** 0,4-rc3,8 und früher, ** Nd4j.dtype = DataBuffer.Type.DOUBLE; NDArrayFactory factory = Nd4j.factory(); factory.setDType(DataBuffer.Type.DOUBLE); ** 0,4-rc3,9 und höher ** DataTypeUtil.setDTypeForContext(DataBuffer.Type.DOUBLE);
Erstellen wir mit [DataTypeUtil] ein Array von Doubles (https://nd4j.org/doc/org/nd4j/linalg/api/buffer/util/DataTypeUtil.html).
//Erstellen Sie ein Array mit Standardgenauigkeit.
INDArray a = Nd4j.create(new double[] {1D / 3});
//Doppelte Genauigkeit(double)Einstellen.
DataTypeUtil.setDTypeForContext(DataBuffer.Type.DOUBLE);
//Sie können sehen, dass es in double geändert wurde.
assertEquals(DataBuffer.Type.DOUBLE, DataTypeUtil.getDtypeFromContext());
//Erstellen Sie ein Array mit doppelter Genauigkeit.
INDArray b = Nd4j.create(new double[] {1D / 3});
//a ist ein Array mit einfacher Genauigkeit, das mit double initialisiert wurde.
assertEquals(0.3333333432674408, a.getDouble(0), 5e-14);
//b wurde mit double initialisiert, ist jedoch ein Array mit doppelter Genauigkeit.
assertEquals(0.3333333333333333, b.getDouble(0), 5e-14);
//Mit einfacher Genauigkeit(float)Zurücksenden an.
DataTypeUtil.setDTypeForContext(DataBuffer.Type.FLOAT);
Ich denke, dass ND4J standardmäßig float verwendet, hauptsächlich weil es für die Verwendung in Deep Learning vorgesehen ist. ND4J kann GPU über CUDA verwenden, aber float ist wahrscheinlich auch in diesem Fall einfacher zu handhaben. Diese Reihe von Posts verwendet konsistent den Doppeltyp, aber das Innere von INDArray ist der Float-Typ. Bitte beachte, dass.
Recommended Posts