["Deep Learning from scratch - la théorie et la mise en œuvre du deep learning appris en Python"] (https://www.oreilly.co.jp/books/9784873117584/) (écrit par Yasuki Saito, O'Reilly Japan) est un livre qui explique le Deep Learning depuis le début. J'utilise Python comme langage de programmation, mais cet article (et la série d'articles qui suivent) l'implémente en Java. Cependant, [Deep Learning from scratch] Il ne remplace pas (https://www.oreilly.co.jp/books/9784873117584/), mais il est décrit en supposant qu'il sera lu ensemble.
Numpy
[Apprentissage profond à partir de zéro] (https://www.oreilly.co.jp/books/9784873117584/) utilise NumPy comme bibliothèque pour le calcul numérique. Cet article utilise ND4J. ND4J est une bibliothèque pour Java qui a des fonctions similaires à NumPy et Matlib. Il est célèbre pour être utilisé dans l'open source Deeplearning4J. Cependant, la documentation n'est pas très bien organisée. Il est nécessaire d'apprendre à l'utiliser par quelques essais et erreurs. ND4J peut utiliser le GPU via CUDA. Je pense que c'est avantageux pour accélérer.
Matplotlib
[Apprentissage profond à partir de zéro] (https://www.oreilly.co.jp/books/9784873117584/) utilise Matplotlib comme bibliothèque pour dessiner des graphiques. Les graphiques ne sont pas essentiels pour le Deep Learning, donc cet article n'utilise pas de bibliothèque pour dessiner des graphiques.
[Apprentissage profond à partir de zéro] Les programmes écrits en Python qui apparaissent dans (https://www.oreilly.co.jp/books/9784873117584/) seront réécrits en Java un par un. Écrivez-le sous forme de code JUnit pour vous assurer que les résultats sont identiques. Par exemple, cela ressemble à ce qui suit.
public class C1_5_NumPy {
@Test
public void C1_5_2_Génération du tableau NumPy() {
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 3.0});
assertEquals("[1.00,2.00,3.00]", Util.string(x));
}
}
Il s'agit d'une version Java de l'exemple de programme qui apparaît dans "1 Introduction à Python 1.5 NumPy 1.5.2 Génération de tableaux NumPy". Étant donné que le japonais est utilisé pour les noms de classe et les noms de méthode, il peut ne pas fonctionner selon l'environnement. Cela fonctionne correctement dans mon environnement (Windows10 + Eclipse Oxygen.2 Release 4.7.2). Étant donné que seules les sections dans lesquelles le code Python est écrit sont décrites, les numéros d'article des en-têtes ne sont pas des numéros de série. Tous les programmes écrits en Java sont publiés sur GitHub à saka1029 / Deep.Learning.
Les dépendances suivantes doivent être définies dans pom.xml pour créer un projet sur GitHub.
<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>
Vous devez également définir les paramètres du projet sur l'EDI pour utiliser * Java 8 *. Avec Java 9, le chargeur de classe peut lever une exception lors de l'exécution.
1.5 ND4J
[Apprentissage profond à partir de zéro] (https://www.oreilly.co.jp/books/9784873117584/) décrit Python, Numpy et Matplotlib au chapitre 1, mais cet article ne décrit que ND4J.
Dans ND4J, le type de tableau est INDArray. Pour initialiser en donnant une valeur initiale, utilisez la méthode factory de la classe Nd4j comme suit. Util.string (INDArray) est une chaîne du contenu du tableau C'est une fonction d'utilité auto-créée à convertir.
INDArray x = Nd4j.create(new double[] {1.0, 2.0, 3.0});
assertEquals("[1.00,2.00,3.00]", Util.string(x));
Les quatre règles d'un tableau unidimensionnel sont les suivantes.
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) est une multiplication pour chaque élément, et le produit de la matrice est [INDArray](https: / /nd4j.org/doc/org/nd4j/linalg/api/ndarray/INDArray.html). mmul (INDArray). INDArray a également add (Number), sub (Number), mul (Number), div Puisque (Number) est surchargé, les quatre règles de fonctionnement avec la valeur scalaire peuvent être exécutées de la même manière. La substance de x est un tableau à deux dimensions avec 1 ligne et 3 colonnes. Veuillez noter que ce point est différent de NumPy. INDArray .rank () renvoie les dimensions du tableau.
assertArrayEquals(new int[] {1,3}, x.shape());
assertEquals(2, x.rank());
C'est la même idée que NumPy en ce sens qu'il utilise INDArray même s'il devient deux dimensions ou plus. Pour créer un tableau à deux dimensions avec des valeurs initiales, procédez comme suit.
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());
Avec NumPy, il est possible d'exécuter quatre règles comme entre des tableaux de dimensions différentes, mais avec ND4J, ce n'est pas possible. Vous devez aligner explicitement les dimensions à l'aide de la méthode INDArray.broadcast (int []). .. Si vous oubliez cela, une IllegalStateException sera lancée.
INDArray A = Nd4j.create(new double[][] {{1, 2}, {3, 4}});
INDArray B = Nd4j.create(new double[] {10, 20});
//INDArray, méthode mul(INDArray)Et ajouter(INDArray)Ne diffuse pas automatiquement.
// broadcast(int[])Vous devez utiliser pour ajuster la dimension du côté gauche.
assertEquals("[[10.00,40.00],[30.00,80.00]]", Util.string(A.mul(B.broadcast(A.shape()))));
//IllegalStateException lorsqu'il est simplement multiplié:Ce seront des formes incompatibles.
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());
}
//Ou mulRowVector(INDArray)Vous pouvez aussi utiliser.
assertEquals("[[10.00,40.00],[30.00,80.00]]", Util.string(A.mulRowVector(B)));
INDArray n'implémente pas l'interface Iterable. En outre, aucune méthode ne renvoie un Iterator. L'accès à l'élément doit se faire à l'aide d'indices. INDArray.getDouble (int ...) pour récupérer des éléments, [INDArray] pour récupérer des lignes (https://nd4j.org/doc/org/nd4j/linalg/api/ndarray/INDArray.html).getRow (int), INDArray pour récupérer les colonnes Utilisez org / nd4j / linalg / api / ndarray / INDArray.html) .getColumn (int). Pour changer un tableau bidimensionnel en tableau unidimensionnel, utilisez la méthode Nd4j.toFlattened (INDArray).
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 n'implémente pas l'interface Iterable.
for (int i = 0, size = X.size(0); i < size; ++i)
assertEquals(2, X.getRow(i).size(1));
//Convertissez X en vecteur.
X = Nd4j.toFlattened(X);
assertEquals("[51.00,55.00,14.00,19.00,0.00,4.00]", Util.string(X));
//Vous pouvez également récupérer tous les éléments spécifiés.
assertEquals("[51.00,14.00,0.00]", Util.string(X.getColumns(0, 2, 4)));
En regardant les exemples jusqu'à présent, INDArray semble contenir le double tableau en interne car il est initialisé à l'aide du double tableau. Cependant, ND4J réserve un tableau de flottants par défaut. La documentation a la description suivante:
** Paramètre du type de données ** ND4J permet actuellement le support avec INDArray avec des valeurs flottantes ou double précision. La valeur par défaut est simple précision (float). Pour configurer ND4J pour utiliser la double précision pour l'ensemble du tableau, vous pouvez utiliser: ** 0.4-rc3.8 et versions antérieures, ** Nd4j.dtype = DataBuffer.Type.DOUBLE; NDArrayFactory factory = Nd4j.factory(); factory.setDType(DataBuffer.Type.DOUBLE); ** 0.4-rc3.9 et versions ultérieures, ** DataTypeUtil.setDTypeForContext(DataBuffer.Type.DOUBLE);
Créons un tableau de doubles en utilisant DataTypeUtil.
//Créez un tableau avec la précision par défaut.
INDArray a = Nd4j.create(new double[] {1D / 3});
//Double précision(double)Mis à.
DataTypeUtil.setDTypeForContext(DataBuffer.Type.DOUBLE);
//Vous pouvez voir qu'il a été changé pour doubler.
assertEquals(DataBuffer.Type.DOUBLE, DataTypeUtil.getDtypeFromContext());
//Créez un tableau à double précision.
INDArray b = Nd4j.create(new double[] {1D / 3});
//a est un tableau simple précision, initialisé avec double.
assertEquals(0.3333333432674408, a.getDouble(0), 5e-14);
//b a été initialisé avec double, mais c'est un tableau à double précision.
assertEquals(0.3333333333333333, b.getDouble(0), 5e-14);
//Précision simple(float)Retourner à.
DataTypeUtil.setDTypeForContext(DataBuffer.Type.FLOAT);
Je pense que ND4J utilise float par défaut principalement parce qu'il est destiné à être utilisé en Deep Learning. ND4J peut utiliser le GPU via CUDA, mais float est probablement plus facile à gérer dans ce cas également. Cette série d'articles utilise systématiquement le type double, mais l'intérieur de INDArray est le type float. Veuillez noter que.