Ας κωδικοποιήσουμε ένα νευρωνικό δίκτυο από το μηδέν - Μέρος 1

Μέρος 1, Μέρος 2 & Μέρος 3

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

Αυτό το σεμινάριο στοχεύει να διδάξει στους δημιουργικούς κωδικοποιητές πώς να δημιουργήσουν ένα τεχνητό νευρωνικό δίκτυο (ANN). Για να είμαστε λίγο πιο συγκεκριμένοι το δίκτυό μας θα αποτελείται από νευρώνες και perceptrons που θα τροφοδοτήσουν και θα χρησιμοποιήσουν το backpropagation για να μάθουν. Αυτό μπορεί να ακούγεται αλλόκοτο για εσάς, αλλά δεν φοβάται, θα εξηγήσω τα πάντα λεπτομερώς. Είναι επίσης ANN στην απλούστερη μορφή του, επομένως, μην περιμένετε έναν αμφισβητία της Tensorflow, η ομορφιά της βρίσκεται στην απλότητα της. Χρειάζεται κάποια εξοικείωση με τον προγραμματισμό αντικειμένων (OOP).

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

Ως δευτερεύουσα σημείωση, αν τυχαίνει να έχω οποιονδήποτε έμπειρο αναγνώστη από την AI, θα ήθελα πολύ να μάθω αν / πώς μπορεί να βελτιωθεί η απόδοση χωρίς να προσθέσετε υπερβολική πολυπλοκότητα ή βιβλιοθήκες.

Σύνολο δεδομένων NMIST - Εικόνα από τον Adam Geitgey

Πώς λειτουργεί ο εγκέφαλός μας;

Ας εξερευνήσουμε πρώτα από πού προέρχεται το ANN - τα μυαλά μας. Με την όραση ενός σημείου ορίου ταχύτητας "70", τα φωτόνια που αναπηδούν από τους προβολείς σας, στον πίνακα και πίσω στον αμφιβληστροειδή προκαλούν μια χημική αντίδραση. Μερικοί από τους νευρώνες που συνδέονται με τον οπτικό φλοιό σας θα αποκτήσουν ενθουσιασμό και θα περάσουν το σήμα σε άλλους νευρώνες μέσω δικτύων δενδριτών που απελευθερώνουν ένα χημικό σήμα.

Neuron Signal @ GIF από το DynamicScience

Εν κατακλείδι, η δραστηριότητα ξεπερνάει τα περιστατικά και τα χρονικά Lobes (περιοχές για την ερμηνεία οπτικών πληροφοριών) και σας κάνει να συνειδητοποιήσετε ότι υπερβαίνετε το όριο ταχύτητας. Έτσι, τα φωτόνια επεξεργάζονται μέσω ενός αριθμού στρώσεων που οδηγούν σε σωστή ενέργεια, μειώνοντας έτσι την ταχύτητά σας.

Με τη στοιχειώδη κατανόηση της λειτουργίας του εγκεφάλου ας προχωρήσουμε στην εξερεύνηση της δομής του NN που πρόκειται να χτίσουμε. Μπορούμε να αφηρηθούμε την προαναφερθείσα έννοια κατασκευάζοντας ένα σύνολο νευρώνων "Inputs" που αντιπροσωπεύουν τον αμφιβληστροειδή, αυτό θα πάρει το σχήμα ενός πλέγματος pixel. Οι πληροφορίες μεταφέρονται έπειτα σε ένα "κρυφό" στρώμα που αντιπροσωπεύει τα στρώματα του εγκεφάλου μας. Τέλος, αυτό το κρυφό στρώμα συνδέεται με ένα στρώμα εξόδου, το οποίο ισοδυναμεί με τους κινητικούς νευρώνες που σας προκάλεσε την επιβράδυνση.

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

Όσον αφορά το μέγεθος των πινάκων σε κάθε στρώμα, έχουν διατηρηθεί όσο το δυνατόν μικρότερα, ώστε το δίκτυο να μπορεί να τρέξει σε οποιοδήποτε φορητό υπολογιστή. Κάθε ψηφίο (είσοδος) αντιπροσωπεύεται ως πλέγμα 14x14 εικονοστοιχείων (βλέπε παρακάτω) το οποίο μειώθηκε από 28x28 από τον Alasdair Turner. Το κρυφό στρώμα αποτελείται από ένα πλέγμα 7x7, αυτή είναι μια εντελώς αυθαίρετη επιλογή και σας ενθαρρύνω να παίξετε με αυτό μόλις έχετε τα πάντα τρέξει. Τέλος, η παραγωγή μας είναι μια σειρά από 10 νευρώνες η καθεμία που δείχνει ένα πιθανό ψηφίο από 0 έως 9.

Χειρογράφημα

Αντί να έχουμε νευρώνες σε κάθε στρώμα, θα έχουμε επίσης Perceptrons. Ο σκοπός αυτών είναι να πάρει το άθροισμα των εισροών και εάν είναι πάνω από ένα δεδομένο κατώφλι, τότε θα "πυροβολήσει". Παρατηρήστε πώς σταθμίζεται κάθε είσοδος, εκείνες με υψηλότερο αριθμό (έντονο βέλος) σημαίνουν ισχυρότερη σύνδεση μεταξύ των νευρώνων. Στην περίπτωση αυτή θα περάσει το 90% (0,9 * 100) του σήματος.

Ας γράψουμε κάποιο κωδικό

Με τα βασικά στοιχεία εκτός του τρόπου ας δομήσουμε το πρόγραμμά μας, μπορείτε να το επαναλάβετε στην Επεξεργασία ανοίγοντας μια καρτέλα για κάθε ένα από τα παρακάτω τμήματα.

  1. Κύρια καρτέλα: Αυτό θα μας επιτρέψει να σχεδιάζουμε, να «εκπαιδεύουμε» και να «δοκιμάζουμε» το νευρωνικό μας δίκτυο.
  2. Στοιχεία φόρτωσης: Αυτή η καρτέλα θα μας επιτρέψει να φορτώσουμε ένα σύνολο από ετικέτες "κάρτες flash". Κάθε κάρτα flash θα έχει έναν χειρόγραφο αριθμό σε αυτό για να αναγνωρίσει το νευρωνικό δίκτυο και μια ετικέτα στο πίσω μέρος για να μας πει ποιος αριθμός είναι στην πραγματικότητα.
  3. Neuron: Αυτός θα είναι ο κώδικας για ένα μεμονωμένο perceptron ως παραπάνω.
  4. Δίκτυο: Αυτό θα αποτελείται από έναν αριθμό συστοιχιών νευρώνων. Ένα για το στρώμα εισόδου, ένα για το κρυφό στρώμα και ένα για το στρώμα εξόδου.
  5. Sigmoid: Σκοπός αυτής της καρτέλας είναι να κατασκευάσει μια λειτουργία "πώς να πυροβολήσει μια νευρώνα". Περισσότερες λεπτομέρειες σχετικά με αυτό στο μέρος 2.

Φόρτωση των δεδομένων

Το πρώτο πράγμα που πρέπει να κάνουμε είναι να φορτώσετε τα δεδομένα και να τα εμφανίσετε ως πλέγμα. Ας αναφερθούμε τώρα σε κάθε κουκίδα ως νευρώνα, παρατηρήστε πως είναι σε κλίμακα του γκρι. Θα πούμε ότι ο νευρώνας δεν θα είναι απλώς ενεργοποιημένος ή απενεργοποιημένος, αλλά σε ένα εύρος +1 (μαύρο, σε), 0 (γκρι, μερικώς ενεργοποιημένο / απενεργοποιημένο) και -1 (λευκό, off). Σε αντίθεση με τον εγκέφαλό μας, θα παραμείνουν σε όποια κατάσταση είχαν τεθεί για τελευταία φορά.

Το πλήρες σύνολο δεδομένων περιέχει 10.000 γραπτά ψηφία, θα το χωρίσουμε σε δύο, έτσι έχουμε ένα σετ εκπαίδευσης των 8.000 ψηφίων και ένα σετ δοκιμών 2.000 ψηφίων. Κατά την εκπαίδευση του δικτύου θα χρησιμοποιήσουμε την αντίστοιχη αριθμητική ετικέτα για να "διδάξουμε" αυτό. Κατά τη δοκιμή, οι κάρτες θα χρησιμοποιηθούν ως ερώτηση "εξέτασης" για τον υπολογιστή σας για να διαπιστωθεί αν μπορεί να μαντέψει σωστά. Δεν θα δοθεί η σωστή λύση.

Δεν νομίζω ότι αξίζει να καλύψουμε πώς εισάγουμε τα δεδομένα που παρουσιάζονται ως σύνολο τιμών ακατέργαστων ψηφίων, είναι δευτερεύουσα στη λειτουργία του αλγορίθμου. Μπορείτε επίσης να βρείτε την πλήρη αναφορά στη βάση δεδομένων NMIST σχετικά με τον τρόπο επεξεργασίας. Αξίζει να σημειωθεί ότι κάθε ψηφίο αντιπροσωπεύεται ως αντικείμενο της κατηγορίας "Κάρτα". Όλα φορτώνονται χρησιμοποιώντας τη συνάρτηση "loadData ()" που καλείται πριν από οτιδήποτε στο "setup ()" και βρίσκεται εκτός της κατηγορίας "Card"

Η είσοδος είναι ένα πλέγμα 14x14 και μας δίνει 196 εισόδους οι οποίες αποθηκεύονται σε απλή συστοιχία. Η έξοδος αποθηκεύεται επίσης ως συστοιχία 10 πιθανών απαντήσεων, ως +1 αν αντιστοιχεί στην έξοδο του -1 αν δεν το κάνει. Θα αποθηκεύσουμε επίσης την ετικέτα ως ένα απλό ψηφιακό αντίγραφο ασφαλείας στις εξόδους χρησιμοποιώντας τη μεταβλητή "ετικέτα".

Κατηγορία εισόδου & νευρώνων

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

Θα ξεκινήσουμε με μια πολύ απλή κλάση "Neuron" με λειτουργία απεικόνισης.

Ο επισημασμένος υπολογισμός μέσα στο "fill ()" κλιμακώνει έναν αριθμό από +1 έως -1 σε έναν αριθμό 0 και 255. Υπάρχει επίσης μια αντιστροφή για να επιτευχθεί ένα στυλό (μαύρο) και ένα χαρτί (λευκό) αποτέλεσμα. Οι νευρώνες εκτόξευσης έχουν μια τιμή κοντά στο +1 που θέλουμε να σχεδιάσουμε ως μαύρο ή μια τιμή περίπου 0 ως μαύρο / γκρι ανάλογα με τη δύναμη.

Ας δημιουργήσουμε επίσης μια κλάση "δικτύου" την οποία θα χρησιμοποιήσουμε για την κατασκευή κάθε στρώματος. Έχει τρεις λειτουργίες:

  • Δίκτυο: Αυτός είναι ο αρχικός κώδικας, εδώ ορίσαμε ένα δίκτυο με δεδομένο αριθμό εισόδων, στην περίπτωση αυτή θα είναι 196 (ένα για κάθε εικονοστοιχείο).
  • Απάντηση: Εδώ απαντάμε σε μια κάρτα που εμφανίζεται, γιατί τώρα θα αντιγράψουμε μόνο την είσοδο της κάρτας στην έξοδο της κάρτας χωρίς υπολογισμούς.
  • Οθόνη: Χρησιμοποιείται για να σχεδιάσουμε τους 196 νευρώνες μας ως πλέγμα 14x14

Κάνοντας τα πάντα μαζί μας στην κύρια καρτέλα μας δίνουμε κάτι που μοιάζει με αυτό:

Σε αυτή την κύρια καρτέλα χρησιμοποιήσαμε μόνο την κλάση "Δίκτυο", αρχικοποιείται σε "setup ()" με 196 εισόδους (14x14). Στη συνέχεια τροφοδοτούμε το σετ δοκιμών με τυχαίο "cardNum" που παράγεται με ποντίκι.

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

Εάν απολαμβάνετε αυτό, πατήστε το πλήκτρο

Μεταβείτε στο Μέρος 2

Αρχικός αλγόριθμος από τον Alasdair Turner