Introduction à Neuroph

Introduction à Neuroph

1. introduction

Cet article examineNeuroph - une bibliothèque open-source pour créer des réseaux de neurones et utiliser l'apprentissage automatique.

Dans cet article, nous examinons les concepts de base et plusieurs exemples sur la manière de les assembler.

2. Neuroph

Nous pouvons interagir avec Neuroph en utilisant:

  • un outil basé sur une interface graphique

  • une librairie Java

Les deux approches reposent sur une hiérarchie de classes sous-jacente qui construit des réseaux de neurones artificiels à partir de couches deneurons.

Nous nous concentrerons sur l'aspect programmatique, mais nous ferons référence à plusieurs classes partagées de l'approche basée sur l'interface graphique de Neuroph pour aider à clarifier ce que nous faisons.

Pour en savoir plus sur l'approche basée sur l'interface graphique, jetez un œil à Neurophdocumentation.

2.1. Les dépendances

Si vous souhaitez utiliser Neuroph, nous devons ajouter l'entrée Maven suivante:


    org.beykery
    neuroph
    2.92

La version la plus récente peut être trouvéeon Maven Central.

3. Classes et concepts clés

Tous les blocs de construction conceptuels de base utilisés ont des classes Java correspondantes.

Neurons sont connectés àLayers qui sont ensuite regroupés enNeuralNetworks. LesNeuralNetworks sont ensuite formés à l'aide deLearningRules etDataSets.

3.1. Neuron

La classeNeuron a quatre attributs principaux:

  1. inputConnection: connexions pondérées entreNeurons

  2. inputFunction: spécifieweights etvector sums appliqués aux données de connexion entrantes

  3. transferFunction: spécifieweights etvector sums appliqués aux données sortantes __

  4. output: la valeur de sortie résultant de l'application detransferFunctions etinputFunctions à uninputConnection

Ensemble, ces quatre attributs principaux établissent le comportement:

output = transferFunction(inputFunction(inputConnections));

3.2. Layer

Layers are essentially groupings of Neurons de telle sorte que chaqueNeuron dans lesLayer soit (généralement) uniquement connecté avecNeurons dans lesLayers précédents et suivants.

LesLayers transmettent donc des informations entre eux via les fonctions pondérées qui existent sur leursNeurons.

Neurons peuvent être ajoutés aux calques: __

Layer layer = new Layer();
layer.addNeuron(n);

3.3. NeuralNetwork

La superclasse de niveau supérieurNeuralNetwork est sous-classée dans plusieurs types familiers de réseaux de neurones artificiels, y compris les réseaux de neurones convolutifs (sous-classeConvolutionalNetwork), les réseaux de neurones Hopfield (sous-classeHopfield) et les réseaux de neurones perceptrons multicouches (sous-classeMultilayerPerceptron).

All NeuralNetworks are composed of Layers qui sont généralement organisés en trichotomie:

  1. couches d'entrée

  2. couches cachées

  3. couches de sortie

Si nous utilisons le constructeur d'une sous-classe deNeuralNetwork (commePerceptron), nous pouvons passer leLayers, le nombre deNeurons pour chaqueLayer , et leur index en utilisant cette méthode simple:

NeuralNetwork ann = new Perceptron(2, 4, 1);

Parfois, nous voudrons le faire manuellement (et il est bon de voir ce qui se passe sous le capot). L'opération de base pour ajouter unLayer à unNeuralNetwork est accomplie comme ceci:

NeuralNetwork ann = new NeuralNetwork();
Layer layer = new Layer();
ann.addLayer(0, layer);
ann.setInputNeurons(layer.getNeurons());

Le premier argument spécifie l'indice desLayer dans lesNeuralNetwork; le deuxième argument spécifie leLayer lui-même. LesLayers ajoutés manuellement doivent être connectés en utilisant la classeConnectionFactory:

ann.addLayer(0, inputLayer);
ann.addLayer(1, hiddenLayerOne);
ConnectionFactory.fullConnect(ann.getLayerAt(0), ann.getLayerAt(1));

Le premier et le dernierLayer doivent également être connectés:

ConnectionFactory.fullConnect(ann.getLayerAt(0),
  ann.getLayerAt(ann.getLayersCount() - 1), false);
ann.setOutputNeurons(ann.getLayerAt(
  ann.getLayersCount() - 1).getNeurons());

N'oubliez pas que la force et la puissance d'unNeuralNetwork dépendent largement de:

  1. le nombre deLayers dans lesNeuralNetwork

  2. le nombre deNeurons dans chaqueLayer (et lesweighted functions entre eux), et

  3. l'efficacité des algorithmes d'apprentissage / la précision desDataSet

3.4. Former nosNeuralNetwork

NeuralNetworks sont formés à l'aide des classesDataSet etLearningRule.

DataSet est utilisé pour représenter et fournir les informations à apprendre ou à utiliser pour former lesNeuralNetwork. DataSets sont caractérisés par leursinput size, outputsize, et les lignes(DataSetRow).

int inputSize = 2;
int outputSize = 1;
DataSet ds = new DataSet(inputSize, outputSize);

DataSetRow rOne
  = new DataSetRow(new double[] {0, 0}, new double[] {0});
ds.addRow(rOne);
DataSetRow rTwo
  = new DataSetRow(new double[] {1, 1}, new double[] {0});
ds.addRow(rTwo);

LearningRule spécifie la manière dont lesDataSet sont enseignés ou entraînés par lesNeuralNetwork. Les sous-classes deLearningRule incluentBackPropagation etSupervisedLearning.

NeuralNetwork ann = new NeuralNetwork();
//...
BackPropagation backPropagation = new BackPropagation();
backPropagation.setMaxIterations(1000);
ann.learn(ds, backPropagation);

4. Mettre tous ensemble

Maintenant, rassemblons ces éléments de base en un véritable exemple. Nous allons commencer parcombining several layers together into the familiar input layer, hidden layer, and output layer pattern illustrés par la plupart des architectures de réseaux neuronaux.

4.1. Couches

Nous assemblerons nosNeuralNetwork en combinant quatre couches. Notre objectif est de construire un (2, 4, 4, 1)NeuralNetwork.

Définissons d'abord notre couche d'entrée:

Layer inputLayer = new Layer();
inputLayer.addNeuron(new Neuron());
inputLayer.addNeuron(new Neuron());

Ensuite, nous implémentons la couche 1 masquée:

Layer hiddenLayerOne = new Layer();
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());

Et la couche cachée deux:

Layer hiddenLayerTwo = new Layer();
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());

Enfin, nous définissons notre couche de sortie:

Layer outputLayer = new Layer();
outputLayer.addNeuron(new Neuron());

4.2. NeuralNetwork

Ensuite, nous pouvons les rassembler dans unNeuralNetwork:

NeuralNetwork ann = new NeuralNetwork();
ann.addLayer(0, inputLayer);
ann.addLayer(1, hiddenLayerOne);
ConnectionFactory.fullConnect(ann.getLayerAt(0), ann.getLayerAt(1));
ann.addLayer(2, hiddenLayerTwo);
ConnectionFactory.fullConnect(ann.getLayerAt(1), ann.getLayerAt(2));
ann.addLayer(3, outputLayer);
ConnectionFactory.fullConnect(ann.getLayerAt(2), ann.getLayerAt(3));
ConnectionFactory.fullConnect(ann.getLayerAt(0),
  ann.getLayerAt(ann.getLayersCount()-1), false);
ann.setInputNeurons(inputLayer.getNeurons());
ann.setOutputNeurons(outputLayer.getNeurons());

4.3. Formation

À des fins de formation, rassemblons unDataSet en spécifiant la taille du vecteur d'entrée et de sortie résultant:

int inputSize = 2;
int outputSize = 1;
DataSet ds = new DataSet(inputSize, outputSize);

Nous ajoutons une ligne élémentaire à nosDataSet adhérant aux contraintes d'entrée et de sortie définies ci-dessus - notre objectif dans cet exemple est d'apprendre à notre réseau à faire des opérations XOR de base (exclusives ou):

DataSetRow rOne
  = new DataSetRow(new double[] {0, 1}, new double[] {1});
ds.addRow(rOne);
DataSetRow rTwo
  = new DataSetRow(new double[] {1, 1}, new double[] {0});
ds.addRow(rTwo);
DataSetRow rThree
  = new DataSetRow(new double[] {0, 0}, new double[] {0});
ds.addRow(rThree);
DataSetRow rFour
  = new DataSetRow(new double[] {1, 0}, new double[] {1});
ds.addRow(rFour);

Ensuite, entraînons nosNeuralNetwork avec lesBackPropogation LearningRule intégrés:

BackPropagation backPropagation = new BackPropagation();
backPropagation.setMaxIterations(1000);
ann.learn(ds, backPropagation);

4.4. Essai

Maintenant que notreNeuralNetwork est entraîné, testons-le. Pour chaque paire de valeurs logiques passées dans nosDataSet en tant queDataSetRow, nous exécutons le type de test suivant:

ann.setInput(0, 1);
ann.calculate();
double[] networkOutputOne = ann.getOutput();

Une chose importante à retenir est queNeuralNetworks only output a value on the inclusive interval of 0 and 1. Pour afficher une autre valeur, nous devonsnormalize etdenormalize nos données.

Dans ce cas, pour les opérations logiques, 0 et 1 sont parfaits pour le travail. La sortie sera:

Testing: 1, 0 Expected: 1.0 Result: 1.0
Testing: 0, 1 Expected: 1.0 Result: 1.0
Testing: 1, 1 Expected: 0.0 Result: 0.0
Testing: 0, 0 Expected: 0.0 Result: 0.0

Nous voyons que notreNeuralNetwork prédit avec succès la bonne réponse!

5. Conclusion

Nous venons de passer en revue les concepts de base et les classes utilisés par Neuroph.

De plus amples informations sur cette bibliothèque sont disponibleshere, et les exemples de code utilisés dans cet article peuvent être trouvésover on GitHub.