Πώς να δημιουργήσετε ένα νευρικό δίκτυο σε JavaScript σε μόνο 30 γραμμές κώδικα

Σε αυτό το άρθρο, θα σας δείξω πώς να δημιουργήσετε και να εκπαιδεύσετε ένα νευρωνικό δίκτυο χρησιμοποιώντας το Synaptic.js, το οποίο σας επιτρέπει να κάνετε βαθιά μάθηση στο Node.js και το πρόγραμμα περιήγησης.

Θα δημιουργήσουμε το απλούστερο δυνατό νευρικό δίκτυο: αυτό που καταφέρνει να λύσει την εξίσωση XOR.

Έχω δημιουργήσει επίσης ένα διαδραστικό φροντιστήριο Scrimba για αυτό το παράδειγμα, οπότε ελέγξτε και αυτό:

Στο σεμινάριο Scrimba, θα μπορείτε να παίζετε με τον κωδικό όποτε θέλετε.

Ή εάν ενδιαφέρεστε για ένα πλήρες μάθημα για νευρωνικά δίκτυα σε JavaScript, παρακαλούμε δείτε το δωρεάν μάθημα στο Brain.js στο Scrimba.

Κάντε κλικ στην εικόνα για να φτάσετε στο μάθημα

Αλλά πριν εξετάσουμε τον κώδικα, ας δούμε τα βασικά των νευρωνικών δικτύων.

Νευρώνες και συνάψεις

Το πρώτο δομικό στοιχείο ενός νευρικού δικτύου είναι, καλά, νευρώνες.

Ένας νευρώνας είναι σαν μια λειτουργία, παίρνει μερικές εισόδους και επιστρέφει μια έξοδο.

Υπάρχουν πολλοί διαφορετικοί τύποι νευρώνων. Το δίκτυό μας πρόκειται να χρησιμοποιήσει σιγμοειδείς νευρώνες, οι οποίοι λαμβάνουν οποιονδήποτε αριθμό και τον συμπιέζουν σε τιμή μεταξύ 0και 1.

Ο παρακάτω κύκλος απεικονίζει έναν σιγμοειδή νευρώνα. Η είσοδος είναι 5και η έξοδος είναι 1. Τα βέλη ονομάζονται συνάψεις, οι οποίες συνδέουν τον νευρώνα με άλλα στρώματα στο δίκτυο.

Γιατί λοιπόν είναι ο κόκκινος αριθμός 5; Επειδή είναι το άθροισμα των τριών συνάψεων που συνδέονται με τον νευρώνα όπως φαίνεται από τα τρία βέλη στα αριστερά. Ας αποσυμπιέσουμε αυτό.

Αριστερά, βλέπουμε δύο τιμές συν τη λεγόμενη τιμή μεροληψίας . Οι τιμές είναι 1και 0ποιοι είναι οι πράσινοι αριθμοί. Η τιμή μεροληψίας -2είναι ο αριθμός καφέ.

Πρώτον, οι δύο είσοδοι πολλαπλασιάζονται με τα βάρη τους , τα οποία είναι 7και 3όπως φαίνεται από τους μπλε αριθμούς.

Τέλος, το προσθέτουμε με την προκατάληψη και καταλήγουμε με 5τον κόκκινο αριθμό. Αυτή είναι η είσοδος για τον τεχνητό νευρώνα μας.

Καθώς αυτός είναι ένας σιγμοειδής νευρώνας που συμπιέζει οποιαδήποτε τιμή μεταξύ 0 και 1, η έξοδος συμπιέζεται 1.

Εάν συνδέσετε ένα δίκτυο αυτών των νευρώνων μαζί, έχετε ένα νευρικό δίκτυο. Αυτό διαδίδεται προς τα εμπρός από είσοδο σε έξοδο, μέσω νευρώνων που συνδέονται μεταξύ τους μέσω συνάψεων. Όπως στην παρακάτω εικόνα:

Ο στόχος ενός νευρικού δικτύου είναι να το εκπαιδεύσει να κάνει γενικεύσεις, όπως η αναγνώριση χειρόγραφων ψηφίων ή ανεπιθύμητων μηνυμάτων ηλεκτρονικού ταχυδρομείου. Και το να είσαι καλός στη γενίκευση είναι να έχουμε τα σωστά βάρη και τιμές μεροληψίας σε όλο το δίκτυο. Όπως με τους μπλε και καφέ αριθμούς στο παραπάνω παράδειγμά μας.

Όταν εκπαιδεύετε το δίκτυο, απλώς το δείχνετε πολλά παραδείγματα όπως χειρόγραφα ψηφία και ζητάτε από το δίκτυο να προβλέψει τη σωστή απάντηση.

Μετά από κάθε πρόβλεψη, θα υπολογίσετε πόσο λάθος  ήταν η πρόβλεψη και θα προσαρμόσετε τις τιμές βαρών και προκατάληψης, ώστε το δίκτυο να μαντέψει λίγο πιο σωστό την επόμενη φορά. Αυτή η μαθησιακή διαδικασία ονομάζεται backpropagation. Κάνετε αυτό για χιλιάδες φορές και το δίκτυό σας θα γίνει σύντομα καλό στη γενίκευση.

Το πώς λειτουργεί το backpropagation είναι εκτός του πεδίου αυτού του σεμιναρίου, αλλά εδώ είναι οι τρεις καλύτερες πηγές που έχω βρει για να το κατανοήσω:

  • Ένα βήμα προς βήμα Backpropagation Παράδειγμα - από τον Matt Mazur
  • Οδηγός χάκερ για νευρικά δίχτυα - από τον Andrej Karpathy
  • NeuralNetworksAndDeepLarning - από τον Michael Nielsen

Ο κώδικας

Τώρα που έχετε μια βασική εισαγωγή, ας περάσουμε στον κώδικα. Το πρώτο πράγμα που πρέπει να κάνουμε είναι να δημιουργήσουμε τα επίπεδα. Αυτό το κάνουμε με τη new Layer()συναπτική συνάρτηση. Ο αριθμός που περνά στη συνάρτηση υπαγορεύει πόσους νευρώνες πρέπει να έχει κάθε στρώμα.

Εάν είστε μπερδεμένοι με το τι είναι ένα επίπεδο , ρίξτε μια ματιά στο screencast παραπάνω.

const {Layer, Network} = window.synaptic;

var inputLayer = νέο επίπεδο (2);

var hiddenLayer = νέο επίπεδο (3);

var outputLayer = νέο επίπεδο (1);

Στη συνέχεια θα συνδέσουμε αυτά τα επίπεδα μαζί και θα δημιουργήσουμε ένα νέο δίκτυο, όπως αυτό:

inputLayer.project (κρυφό επίπεδο);

hiddenLayer.project (outputLayer);

var myNetwork = νέο δίκτυο ({

input: inputLayer,

κρυφό: [hiddenLayer],

έξοδος: outputLayer

});

Έτσι, αυτό είναι ένα δίκτυο 2–1–1, το οποίο μπορεί να απεικονιστεί έτσι:

Τώρα ας εκπαιδεύσουμε το δίκτυο:

// 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]); } 

Εδώ τρέχουμε το δίκτυο 20.000 φορές. Κάθε φορά που διαδίδονται προς τα εμπρός και προς τα πίσω τέσσερις φορές, περνώντας τις τέσσερις πιθανές εισόδους για αυτό το δίκτυο: [0,0] [0,1] [1,0] [1,1].

Ξεκινάμε κάνοντας myNetwork.activate([0,0]), πού [0,0]είναι το σημείο δεδομένων που στέλνουμε στο δίκτυο. Αυτή είναι η προώθηση προς τα εμπρός, που ονομάζεται επίσης ενεργοποίηση  του δικτύου. Μετά από κάθε προωθητική μετάδοση, πρέπει να κάνουμε backpropagation, όπου το δίκτυο ενημερώνει τα δικά του βάρη και προκαταλήψεις.

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!

Και αυτό είναι. Παρόλο που μόλις γρατσουνίστηκα η επιφάνεια των νευρωνικών δικτύων, αυτό θα σας δώσει αρκετά για να ξεκινήσετε να παίζετε με το Synaptic για τον εαυτό σας και να συνεχίσετε να μαθαίνετε μόνοι σας. Το wiki τους περιέχει πολλά καλά μαθήματα.

Τέλος, φροντίστε να μοιραστείτε τις γνώσεις σας δημιουργώντας ένα Scrimencast ή γράφοντας ένα άρθρο όταν μαθαίνετε κάτι νέο! :)

PS: Έχουμε περισσότερα δωρεάν μαθήματα για εσάς!

Αν ψάχνετε για την επόμενη πρόκληση, έχουμε πολλά άλλα δωρεάν μαθήματα που μπορείτε να δείτε στο Scrimba.com. Εδώ είναι τρία που μπορεί να σας ενδιαφέρουν:

  • Νευρωνικά δίκτυα σε JavaScript
  • Εισαγωγή στο ES6 +
  • Μάθετε D3 JS

Καλή κωδικοποίηση!