Comment créer un réseau de neurones en JavaScript en seulement 30 lignes de code

Dans cet article, je vais vous montrer comment créer et entraîner un réseau de neurones à l'aide de Synaptic.js, qui vous permet de faire un apprentissage en profondeur dans Node.js et le navigateur.

Nous allons créer le réseau de neurones le plus simple possible: celui qui parvient à résoudre l'équation XOR.

J'ai également créé un tutoriel Scrimba interactif sur cet exemple, alors vérifiez-le également:

Dans le didacticiel Scrimba, vous pourrez jouer avec le code quand vous le souhaitez.

Ou si vous êtes intéressé par un cours complet sur les réseaux de neurones en JavaScript, veuillez consulter notre cours gratuit sur Brain.js à Scrimba.

Cliquez sur l'image pour accéder au cours

Mais avant de regarder le code, passons en revue les bases mêmes des réseaux de neurones.

Neurones et synapses

Le premier élément constitutif d'un réseau neuronal est, eh bien, les neurones.

Un neurone est comme une fonction, il prend quelques entrées et renvoie une sortie.

Il existe de nombreux types de neurones. Notre réseau va utiliser des neurones sigmoïdes, qui prennent n'importe quel nombre donné et le réduisent à une valeur comprise entre 0et 1.

Le cercle ci-dessous illustre un neurone sigmoïde. Son entrée est 5et sa sortie est 1. Les flèches sont appelées synapses, qui connectent le neurone à d'autres couches du réseau.

Alors pourquoi le nombre rouge 5? Parce que c'est la somme des trois synapses qui se connectent au neurone comme indiqué par les trois flèches à gauche. Décompressons cela.

À l'extrême gauche, nous voyons deux valeurs plus une valeur dite de biais . Les valeurs sont 1et 0qui sont les nombres verts. La valeur du biais -2est le nombre marron.

Tout d'abord, les deux entrées sont multipliées par leurs poids , qui sont 7et 3comme indiqué par les nombres bleus.

Enfin, nous l'additionnons avec le biais et nous nous retrouvons avec 5ou le nombre rouge. C'est l'entrée de notre neurone artificiel.

Comme il s'agit d'un neurone sigmoïde qui écrase toute valeur entre 0 et 1, la sortie est réduite à 1.

Si vous connectez un réseau de ces neurones ensemble, vous disposez d'un réseau neuronal. Cela se propage en avant de l'entrée à la sortie, via des neurones qui sont connectés les uns aux autres via des synapses. Comme sur l'image ci-dessous:

Le but d'un réseau de neurones est de le former à faire des généralisations, telles que la reconnaissance de chiffres manuscrits ou de spam par courrier électronique. Et pour bien généraliser, il faut avoir les bonnes pondérations et valeurs de biais à travers le réseau. Comme avec les nombres bleus et bruns dans notre exemple ci-dessus.

Lors de la formation du réseau, vous lui montrez simplement de nombreux exemples, tels que des chiffres manuscrits, et vous demandez au réseau de prédire la bonne réponse.

Après chaque prédiction, vous calculerez à quel point  la prédiction était erronée et ajusterez les pondérations et les valeurs de biais afin que le réseau devine un peu plus correctement la prochaine fois. Ce processus d'apprentissage est appelé rétropropagation. Faites cela des milliers de fois et votre réseau deviendra bientôt bon pour généraliser.

Le fonctionnement technique de la rétropropagation sort du cadre de ce didacticiel, mais voici les trois meilleures sources que j'ai trouvées pour le comprendre:

  • Un exemple de rétropropagation étape par étape - par Matt Mazur
  • Guide des pirates sur les réseaux neuronaux - par Andrej Karpathy
  • NeuralNetworksAndDeepLarning - par Michael Nielsen

Le code

Maintenant que vous avez une introduction de base, passons au code. La première chose à faire est de créer les couches. Nous faisons cela avec la new Layer()fonction synaptique. Le nombre passé à la fonction dicte le nombre de neurones que chaque couche doit avoir.

Si vous ne savez pas ce qu'est une couche , consultez le screencast ci-dessus.

const {Couche, Réseau} = window.synaptic;

var inputLayer = new Layer (2);

var hiddenLayer = nouveau calque (3);

var outputLayer = new Layer (1);

Ensuite, nous connecterons ces couches ensemble et instancierons un nouveau réseau, comme ceci:

inputLayer.project (hiddenLayer);

hiddenLayer.project (outputLayer);

var myNetwork = nouveau réseau ({

entrée: inputLayer,

caché: [hiddenLayer],

sortie: outputLayer

});

Il s'agit donc d'un réseau 2–3–1, qui peut être visualisé comme ceci:

Maintenant, formons le réseau:

// train the network - learn XOR var learningRate = .3; for (var i = 0; i  0 myNetwork.activate([0,0]); myNetwork.propagate(learningRate, [0]); // 0,1 => 1 myNetwork.activate([0,1]); myNetwork.propagate(learningRate, [1]); // 1,0 => 1 myNetwork.activate([1,0]); myNetwork.propagate(learningRate, [1]); // 1,1 => 0 myNetwork.activate([1,1]); myNetwork.propagate(learningRate, [0]); } 

Ici, nous exécutons le réseau 20 000 fois. Chaque fois que nous propage en avant et en arrière quatre fois, en passant dans les quatre entrées possibles pour ce réseau: [0,0] [0,1] [1,0] [1,1].

Nous commençons par faire myNetwork.activate([0,0]), où [0,0]est le point de données que nous envoyons dans le réseau. Il s'agit de la propagation directe, également appelée activation  du réseau. Après chaque propagation vers l'avant, nous devons faire une rétropropagation, où le réseau met à jour ses propres pondérations et biais.

The backpropagation is done with this line of code: myNetwork.propagate(learningRate, [0]), where the learningRate is a constant that tells the network how much it should adjust its weights each time. The second parameter 0 represents the correct output given the input [0,0].

The network then compares its own prediction to the correct label. This tells it how right or wrong it was.

It uses the comparison as a basis for correcting its own weights and bias values so that it will guess a little bit more correct the next time.

After it has done this process 20,000 times, we can check how well our network has learned by activating the network with all four possible inputs:

console.log(myNetwork.activate([0,0])); // -> [0.015020775950893527] console.log(myNetwork.activate([0,1])); // -> [0.9815816381088985] console.log(myNetwork.activate([1,0])); // -> [0.9871822457132193] console.log(myNetwork.activate([1,1])); // -> [0.012950087641929467] 

If we round these values to the closest integer, we’ll get the correct answers for the XOR equation. Hurray!

Et c'est à peu près tout. Même si nous venons de gratter la surface des réseaux de neurones, cela devrait vous en donner assez pour commencer à jouer avec Synaptic pour vous-même et continuer à apprendre par vous-même. Leur wiki contient beaucoup de bons tutoriels.

Enfin, assurez-vous de partager vos connaissances en créant un screencast Scrimba ou en écrivant un article lorsque vous apprenez quelque chose de nouveau! :)

PS: Nous avons plus de cours gratuits pour vous!

Si vous recherchez votre prochain défi, nous avons plusieurs autres cours gratuits que vous pouvez consulter sur Scrimba.com. En voici trois qui pourraient vous intéresser:

  • Réseaux de neurones en JavaScript
  • Introduction à ES6 +
  • Apprenez D3 JS

Bon codage!