Το επίπεδο ομαλοποίησης παρτίδας του Keras είναι σπασμένο PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Το στρώμα της Κανονικοποίησης παρτίδας του Keras είναι σπασμένο

ΕΝΗΜΕΡΩΣΗ: Δυστυχώς το αίτημα έλξης μου προς την Keras που άλλαξε τη συμπεριφορά του επιπέδου κανονικοποίησης παρτίδας δεν έγινε αποδεκτό. Μπορείτε να διαβάσετε τις λεπτομέρειες εδώ. Για όσους από εσάς είναι αρκετά τολμηροί για να μπλέξετε με προσαρμοσμένες υλοποιήσεις, μπορείτε να βρείτε τον κώδικα μέσα το κλαδί μου. Μπορεί να το διατηρήσω και να το συγχωνεύσω με την πιο πρόσφατη σταθερή έκδοση του Keras (2.1.6, 2.2.2 και 2.2.4) για όσο διάστημα το χρησιμοποιώ αλλά χωρίς υποσχέσεις.

Οι περισσότεροι άνθρωποι που εργάζονται στο Deep Learning είτε το έχουν χρησιμοποιήσει είτε το έχουν ακούσει Keras. Για όσους από εσάς δεν το έχετε κάνει, είναι μια εξαιρετική βιβλιοθήκη που αφαιρεί τα υποκείμενα πλαίσια Deep Learning όπως το TensorFlow, το Theano και το CNTK και παρέχει API υψηλού επιπέδου για εκπαίδευση ANN. Είναι εύκολο στη χρήση, επιτρέπει τη γρήγορη δημιουργία πρωτοτύπων και έχει μια φιλική ενεργή κοινότητα. Το χρησιμοποιώ σε μεγάλο βαθμό και συνεισφέρω περιοδικά στο έργο εδώ και αρκετό καιρό και το συνιστώ ανεπιφύλακτα σε όποιον θέλει να εργαστεί στο Deep Learning.

Παρόλο που ο Keras έκανε τη ζωή μου πιο εύκολη, πολλές φορές με έχει δαγκώσει η περίεργη συμπεριφορά του επιπέδου Normalization Batch. Η προεπιλεγμένη συμπεριφορά του έχει αλλάξει με την πάροδο του χρόνου, ωστόσο εξακολουθεί να προκαλεί προβλήματα σε πολλούς χρήστες και ως εκ τούτου υπάρχουν αρκετά σχετικά ανοιχτά ζητήματα στο Github. Σε αυτήν την ανάρτηση ιστολογίου, θα προσπαθήσω να δημιουργήσω μια περίπτωση γιατί το επίπεδο BatchNormalization του Keras δεν παίζει καλά με το Transfer Learning, θα παράσχω τον κώδικα που διορθώνει το πρόβλημα και θα δώσω παραδείγματα με τα αποτελέσματα του Κηλίδα.

Στις παρακάτω υποενότητες, παρέχω μια εισαγωγή σχετικά με τον τρόπο με τον οποίο χρησιμοποιείται η Εκμάθηση μεταφοράς στο Deep Learning, τι είναι το επίπεδο κανονικοποίησης παρτίδας, πώς λειτουργεί το Learnining_phase και πώς η Keras άλλαξε τη συμπεριφορά BN με την πάροδο του χρόνου. Εάν τα γνωρίζετε ήδη, μπορείτε να μεταβείτε με ασφάλεια απευθείας στην ενότητα 2.

1.1 Η χρήση της Transfer Learning είναι ζωτικής σημασίας για τη Deep Learning

Ένας από τους λόγους για τους οποίους το Deep Learning επικρίθηκε στο παρελθόν είναι ότι απαιτεί πάρα πολλά δεδομένα. Αυτό δεν είναι πάντα αλήθεια; υπάρχουν πολλές τεχνικές για την αντιμετώπιση αυτού του περιορισμού, μία από τις οποίες είναι η Εκμάθηση Μεταβίβασης.

Ας υποθέσουμε ότι εργάζεστε σε μια εφαρμογή Computer Vision και θέλετε να δημιουργήσετε έναν ταξινομητή που να διακρίνει το Cats από το Dogs. Δεν χρειάζεστε πραγματικά εκατομμύρια εικόνες γάτας/σκύλου για να εκπαιδεύσετε το μοντέλο. Αντίθετα, μπορείτε να χρησιμοποιήσετε έναν προ-εκπαιδευμένο ταξινομητή και να ρυθμίσετε τις κορυφαίες συνελεύσεις με λιγότερα δεδομένα. Η ιδέα πίσω από αυτό είναι ότι δεδομένου ότι το προ-εκπαιδευμένο μοντέλο ήταν κατάλληλο για εικόνες, οι κάτω συνελεύσεις μπορούν να αναγνωρίσουν χαρακτηριστικά όπως γραμμές, άκρες και άλλα χρήσιμα μοτίβα, πράγμα που σημαίνει ότι μπορείτε να χρησιμοποιήσετε τα βάρη του είτε ως καλές τιμές αρχικοποίησης είτε εν μέρει να επανεκπαιδεύσετε το δίκτυο με τα δεδομένα σας .
Το επίπεδο ομαλοποίησης παρτίδας του Keras είναι σπασμένο PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.
Το Keras συνοδεύεται από πολλά προεκπαιδευμένα μοντέλα και εύχρηστα παραδείγματα για το πώς να τελειοποιήσετε τα μοντέλα. Μπορείτε να διαβάσετε περισσότερα στο τεκμηρίωση.

1.2 Τι είναι το επίπεδο κανονικοποίησης παρτίδας;

Το επίπεδο κανονικοποίησης παρτίδας εισήχθη το 2014 από τους Ioffe και Szegedy. Αντιμετωπίζει το πρόβλημα της κλίσης εξαφάνισης τυποποιώντας την έξοδο του προηγούμενου επιπέδου, επιταχύνει την εκπαίδευση μειώνοντας τον αριθμό των απαιτούμενων επαναλήψεων και επιτρέπει την εκπαίδευση βαθύτερων νευρωνικών δικτύων. Η επεξήγηση του πώς ακριβώς λειτουργεί ξεφεύγει από το πεδίο εφαρμογής αυτής της ανάρτησης, αλλά σας ενθαρρύνω να το διαβάσετε αρχικό χαρτί. Μια υπεραπλουστευμένη εξήγηση είναι ότι επανακλιμακώνει την είσοδο αφαιρώντας τη μέση τιμή της και διαιρώντας με την τυπική της απόκλιση. μπορεί επίσης να μάθει να αναιρεί τον μετασχηματισμό εάν είναι απαραίτητο.
Το επίπεδο ομαλοποίησης παρτίδας του Keras είναι σπασμένο PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

1.3 Τι είναι η μαθησιακή_φάση στον Κέρα;

Ορισμένα επίπεδα λειτουργούν διαφορετικά κατά τη διάρκεια της εκπαίδευσης και της λειτουργίας συμπερασμάτων. Τα πιο αξιοσημείωτα παραδείγματα είναι το Batch Normalization και τα επίπεδα Dropout. Στην περίπτωση του BN, κατά τη διάρκεια της εκπαίδευσης χρησιμοποιούμε τον μέσο όρο και τη διακύμανση της μίνι-παρτίδας για να επανακλιμακώσουμε την είσοδο. Από την άλλη πλευρά, κατά την εξαγωγή συμπερασμάτων χρησιμοποιούμε τον κινητό μέσο όρο και τη διακύμανση που υπολογίστηκαν κατά τη διάρκεια της προπόνησης.

Το Keras ξέρει σε ποια λειτουργία να τρέξει επειδή έχει έναν ενσωματωμένο μηχανισμό που ονομάζεται μαθησιακή_φάση. Η φάση εκμάθησης ελέγχει εάν το δίκτυο βρίσκεται σε λειτουργία τρένου ή δοκιμαστικής λειτουργίας. Εάν δεν έχει οριστεί χειροκίνητα από τον χρήστη, κατά τη διάρκεια της fit() το δίκτυο εκτελείται με Learning_phase=1 (train mode). Κατά την παραγωγή προβλέψεων (για παράδειγμα όταν καλούμε τις μεθόδους predict() & αξιολογούμε() ή στο βήμα επικύρωσης της fit()) το δίκτυο εκτελείται με Learning_phase=0 (λειτουργία δοκιμής). Παρόλο που δεν συνιστάται, ο χρήστης μπορεί επίσης να αλλάξει στατικά τη φάση learning_phase σε μια συγκεκριμένη τιμή, αλλά αυτό πρέπει να συμβεί πριν προστεθεί οποιοδήποτε μοντέλο ή τανυστής στο γράφημα. Εάν το Learning_phase ρυθμιστεί στατικά, το Keras θα κλειδωθεί σε όποια λειτουργία έχει επιλέξει ο χρήστης.

1.4 Πώς εφάρμοσε η Keras την κανονικοποίηση παρτίδων με την πάροδο του χρόνου;

Η Keras άλλαξε τη συμπεριφορά της κανονικοποίησης παρτίδας αρκετές φορές, αλλά η πιο πρόσφατη σημαντική ενημέρωση έγινε στο Keras 2.1.3. Πριν από την έκδοση 2.1.3 όταν το επίπεδο BN ήταν παγωμένο (trainable = False) συνέχιζε να ενημερώνει τα στατιστικά της παρτίδας, κάτι που προκαλούσε επικούς πονοκεφάλους στους χρήστες του.

Αυτή δεν ήταν απλώς μια περίεργη πολιτική, ήταν στην πραγματικότητα λάθος. Φανταστείτε ότι υπάρχει ένα επίπεδο BN μεταξύ των συνελίξεων. Εάν το στρώμα είναι παγωμένο, δεν θα πρέπει να συμβούν αλλαγές σε αυτό. Εάν ενημερώσουμε εν μέρει τα βάρη του και τα επόμενα επίπεδα παγώσουν, δεν θα έχουν ποτέ την ευκαιρία να προσαρμοστούν στις ενημερώσεις των στατιστικών mini-batch που οδηγούν σε υψηλότερα σφάλματα. Ευτυχώς, ξεκινώντας από την έκδοση 2.1.3, όταν ένα επίπεδο BN παγώνει, δεν ενημερώνει πλέον τα στατιστικά του. Αρκεί όμως αυτό; Όχι εάν χρησιμοποιείτε το Transfer Learning.

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

2.1 Τεχνική περιγραφή του προβλήματος

Το πρόβλημα με την τρέχουσα εφαρμογή του Keras είναι ότι όταν ένα επίπεδο BN παγώνει, συνεχίζει να χρησιμοποιεί τα στατιστικά mini-batch κατά τη διάρκεια της εκπαίδευσης. Πιστεύω ότι μια καλύτερη προσέγγιση όταν το BN είναι παγωμένο είναι η χρήση του κινούμενου μέσου όρου και της διακύμανσης που έμαθε κατά τη διάρκεια της εκπαίδευσης. Γιατί; Για τους ίδιους λόγους για τους οποίους τα στατιστικά mini-batch δεν πρέπει να ενημερώνονται όταν το επίπεδο είναι παγωμένο: μπορεί να οδηγήσει σε κακά αποτελέσματα επειδή τα επόμενα επίπεδα δεν εκπαιδεύονται σωστά.

Ας υποθέσουμε ότι κατασκευάζετε ένα μοντέλο Computer Vision αλλά δεν έχετε αρκετά δεδομένα, οπότε αποφασίζετε να χρησιμοποιήσετε ένα από τα προεκπαιδευμένα CNN της Keras και να το ρυθμίσετε με ακρίβεια. Δυστυχώς, με αυτόν τον τρόπο δεν λαμβάνετε εγγυήσεις ότι ο μέσος όρος και η διακύμανση του νέου σας δεδομένων εντός των επιπέδων BN θα είναι παρόμοια με αυτά του αρχικού συνόλου δεδομένων. Να θυμάστε ότι αυτή τη στιγμή, κατά τη διάρκεια της εκπαίδευσης το δίκτυό σας θα χρησιμοποιεί πάντα τα στατιστικά mini-batch είτε το επίπεδο BN είναι παγωμένο είτε όχι. Επίσης, κατά τη διάρκεια της εξαγωγής συμπερασμάτων, θα χρησιμοποιήσετε τα στατιστικά στοιχεία των παγωμένων επιπέδων BN που έχετε μάθει προηγουμένως. Ως αποτέλεσμα, εάν ρυθμίσετε με ακρίβεια τα ανώτερα στρώματα, τα βάρη τους θα προσαρμοστούν στη μέση/διακύμανση του νέος σύνολο δεδομένων. Ωστόσο, κατά την εξαγωγή συμπερασμάτων θα λάβουν δεδομένα τα οποία κλιμακώνονται διαφορετικά γιατί ο μέσος όρος/διακύμανση του πρωτότυπο θα χρησιμοποιηθεί σύνολο δεδομένων.
Το επίπεδο ομαλοποίησης παρτίδας του Keras είναι σπασμένο PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.
Παραπάνω παρέχω μια απλοϊκή (και μη ρεαλιστική) αρχιτεκτονική για σκοπούς επίδειξης. Ας υποθέσουμε ότι ρυθμίζουμε το μοντέλο από το Convolution k+1 μέχρι την κορυφή του δικτύου (δεξιά πλευρά) και κρατάμε παγωμένο το κάτω μέρος (αριστερή πλευρά). Κατά τη διάρκεια της προπόνησης, όλα τα επίπεδα BN από το 1 έως το k θα χρησιμοποιούν τη μέση/διακύμανση των δεδομένων προπόνησής σας. Αυτό θα έχει αρνητικές επιπτώσεις στα κατεψυγμένα ReLU αν ο μέσος όρος και η διακύμανση σε κάθε BN δεν είναι κοντά σε αυτά που μάθαμε κατά την προ-προπόνηση. Θα προκαλέσει επίσης την εκπαίδευση του υπόλοιπου δικτύου (από CONV k+1 και μεταγενέστερα) με εισόδους που έχουν διαφορετικές κλίμακες σε σύγκριση με αυτό που θα λάβει κατά τη διάρκεια της εξαγωγής συμπερασμάτων. Κατά τη διάρκεια της εκπαίδευσης, το δίκτυό σας μπορεί να προσαρμοστεί σε αυτές τις αλλαγές, ωστόσο τη στιγμή που θα μεταβείτε στη λειτουργία πρόβλεψης, η Keras θα χρησιμοποιήσει διαφορετικά στατιστικά στοιχεία τυποποίησης, κάτι που θα επιταχύνει την κατανομή των εισόδων των επόμενων επιπέδων οδηγώντας σε κακά αποτελέσματα.

2.2 Πώς μπορείτε να εντοπίσετε εάν επηρεάζεστε;

Ένας τρόπος για να το εντοπίσετε είναι να ρυθμίσετε στατικά τη φάση εκμάθησης του Keras στο 1 (τρόπος τρένου) και στο 0 (λειτουργία δοκιμής) και να αξιολογήσετε το μοντέλο σας σε κάθε περίπτωση. Εάν υπάρχει σημαντική διαφορά στην ακρίβεια στο ίδιο σύνολο δεδομένων, επηρεάζεστε από το πρόβλημα. Αξίζει να σημειωθεί ότι, λόγω του τρόπου με τον οποίο εφαρμόζεται ο μηχανισμός Learn_phase στον Keras, συνήθως δεν συνιστάται να τον μπερδέψετε. Οι αλλαγές στη φάση εκμάθησης δεν θα έχουν καμία επίδραση σε μοντέλα που έχουν ήδη μεταγλωττιστεί και χρησιμοποιούνται. Όπως μπορείτε να δείτε στα παραδείγματα στις επόμενες υποενότητες, ο καλύτερος τρόπος για να το κάνετε αυτό είναι να ξεκινήσετε με μια καθαρή συνεδρία και να αλλάξετε τη φάση εκμάθησης πριν οριστεί οποιοσδήποτε τανυστής στο γράφημα.

Ένας άλλος τρόπος για να εντοπίσετε το πρόβλημα κατά την εργασία με δυαδικούς ταξινομητές είναι να ελέγξετε την ακρίβεια και την AUC. Εάν η ακρίβεια είναι κοντά στο 50% αλλά η AUC είναι κοντά στο 1 (και επίσης παρατηρείτε διαφορές μεταξύ της λειτουργίας αμαξοστοιχίας/δοκιμής στο ίδιο σύνολο δεδομένων), θα μπορούσε να είναι ότι οι πιθανότητες είναι εκτός κλίμακας λόγω των στατιστικών BN. Ομοίως, για την παλινδρόμηση μπορείτε να χρησιμοποιήσετε τη συσχέτιση MSE και Spearman για να την εντοπίσετε.

2.3 Πώς μπορούμε να το διορθώσουμε;

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

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

2.4 Αξιολόγηση των επιπτώσεων του έμπλαστρου

Παρόλο που έγραψα την παραπάνω υλοποίηση πρόσφατα, η ιδέα πίσω από αυτήν έχει δοκιμαστεί σε μεγάλο βαθμό σε προβλήματα του πραγματικού κόσμου χρησιμοποιώντας διάφορες λύσεις που έχουν το ίδιο αποτέλεσμα. Για παράδειγμα, η ασυμφωνία μεταξύ των τρόπων εκπαίδευσης και δοκιμής και μπορεί να αποφευχθεί με το διαχωρισμό του δικτύου σε δύο μέρη (παγωμένο και μη παγωμένο) και την εκτέλεση προσωρινής εκπαίδευσης (πέρασμα δεδομένων από το παγωμένο μοντέλο μία φορά και στη συνέχεια χρήση τους για την εκπαίδευση του μη παγωμένου δικτύου). Ωστόσο, επειδή το «εμπιστέψου με, το έκανα πριν» συνήθως δεν έχει καμία βαρύτητα, παρακάτω παραθέτω μερικά παραδείγματα που δείχνουν τα αποτελέσματα της νέας εφαρμογής στην πράξη.

Ακολουθούν μερικά σημαντικά σημεία σχετικά με το πείραμα:

  1. Θα χρησιμοποιήσω έναν μικρό όγκο δεδομένων για να προσαρμόσω σκόπιμα το μοντέλο και θα εκπαιδεύσω και θα επικυρώσω το μοντέλο στο ίδιο σύνολο δεδομένων. Με αυτόν τον τρόπο, αναμένω σχεδόν τέλεια ακρίβεια και πανομοιότυπες επιδόσεις στο σύνολο δεδομένων αμαξοστοιχίας/επικύρωσης.
  2. Εάν κατά την επικύρωση αποκτήσω σημαντικά χαμηλότερη ακρίβεια στο ίδιο σύνολο δεδομένων, θα έχω μια σαφή ένδειξη ότι η τρέχουσα πολιτική BN επηρεάζει αρνητικά την απόδοση του μοντέλου κατά τη διάρκεια της εξαγωγής συμπερασμάτων.
  3. Οποιαδήποτε προεπεξεργασία θα πραγματοποιείται εκτός των Γεννήτριων. Αυτό γίνεται για να επιλύσετε ένα σφάλμα που παρουσιάστηκε στην έκδοση 2.1.5 (προς το παρόν διορθώθηκε στην επερχόμενη έκδοση 2.1.6 και στην τελευταία κύρια έκδοση).
  4. Θα αναγκάσουμε τον Keras να χρησιμοποιήσει διαφορετικές φάσεις μάθησης κατά την αξιολόγηση. Εάν εντοπίσουμε διαφορές μεταξύ της αναφερόμενης ακρίβειας, θα γνωρίζουμε ότι επηρεαζόμαστε από την τρέχουσα πολιτική BN.

Ο κώδικας για το πείραμα φαίνεται παρακάτω:

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

Ας ελέγξουμε τα αποτελέσματα στο Keras v2.1.5:

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

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

Μετά την ολοκλήρωση της εκπαίδευσης αξιολογούμε το μοντέλο χρησιμοποιώντας 3 διαφορετικές διαμορφώσεις φάσης εκμάθησης: Dynamic, Static = 0 (τρόπος δοκιμής) και Static = 1 (training mode). Όπως μπορούμε να δούμε, οι δύο πρώτες διαμορφώσεις θα παρέχουν τα ίδια αποτελέσματα όσον αφορά την απώλεια και την ακρίβεια και η τιμή τους ταιριάζει με την αναφερόμενη ακρίβεια του μοντέλου στο σύνολο επικύρωσης στην τελευταία επανάληψη. Ωστόσο, μόλις μεταβούμε στη λειτουργία προπόνησης, παρατηρούμε μια τεράστια απόκλιση (βελτίωση). Γιατί έτσι; Όπως είπαμε νωρίτερα, τα βάρη του δικτύου συντονίζονται αναμένοντας να λάβουν δεδομένα κλιμακωμένα με τη μέση/διακύμανση των δεδομένων εκπαίδευσης. Δυστυχώς, αυτά τα στατιστικά στοιχεία είναι διαφορετικά από αυτά που είναι αποθηκευμένα στα επίπεδα BN. Δεδομένου ότι τα επίπεδα BN ήταν παγωμένα, αυτά τα στατιστικά στοιχεία δεν ενημερώθηκαν ποτέ. Αυτή η απόκλιση μεταξύ των τιμών των στατιστικών BN οδηγεί σε επιδείνωση της ακρίβειας κατά τη διάρκεια της εξαγωγής συμπερασμάτων.

Ας δούμε τι θα συμβεί μόλις εφαρμόσουμε το Κηλίδα:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

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

2.5 Πώς λειτουργεί η ενημέρωση κώδικα σε ένα πραγματικό σύνολο δεδομένων;

Πώς λειτουργεί λοιπόν το patch σε ένα πιο ρεαλιστικό πείραμα; Ας χρησιμοποιήσουμε το προεκπαιδευμένο ResNet50 της Keras (αρχικά προσαρμοσμένο στο imagenet), αφαιρέστε το ανώτερο επίπεδο ταξινόμησης και βελτιστοποιήστε το με και χωρίς την ενημερωμένη έκδοση κώδικα και συγκρίνετε τα αποτελέσματα. Για δεδομένα, θα χρησιμοποιήσουμε το CIFAR10 (το τυπικό διαχωρισμό αμαξοστοιχίας/δοκιμών που παρέχεται από την Keras) και θα αλλάξουμε το μέγεθος των εικόνων σε 224×224 για να τις κάνουμε συμβατές με το μέγεθος εισόδου του ResNet50.

Θα κάνουμε 10 εποχές για να εκπαιδεύσουμε το ανώτερο επίπεδο ταξινόμησης χρησιμοποιώντας το RSMprop και, στη συνέχεια, θα κάνουμε άλλες 5 για να τελειοποιήσουμε τα πάντα μετά το 139ο επίπεδο χρησιμοποιώντας SGD(lr=1e-4, ορμή=0.9). Χωρίς το patch το μοντέλο μας επιτυγχάνει ακρίβεια 87.44%. Χρησιμοποιώντας το patch, έχουμε ακρίβεια 92.36%, σχεδόν 5 πόντους υψηλότερη.

2.6 Πρέπει να εφαρμόσουμε την ίδια διόρθωση σε άλλα επίπεδα όπως το Dropout;

Η κανονικοποίηση παρτίδας δεν είναι το μόνο επίπεδο που λειτουργεί διαφορετικά μεταξύ τρένου και δοκιμαστικής λειτουργίας. Το Dropout και οι παραλλαγές του έχουν επίσης το ίδιο αποτέλεσμα. Πρέπει να εφαρμόσουμε την ίδια πολιτική σε όλα αυτά τα επίπεδα; Δεν πιστεύω (παρόλο που θα ήθελα πολύ να ακούσω τις σκέψεις σας για αυτό). Ο λόγος είναι ότι το Dropout χρησιμοποιείται για να αποφευχθεί η υπερβολική προσαρμογή, με αποτέλεσμα να το κλειδώνετε μόνιμα στη λειτουργία πρόβλεψης κατά τη διάρκεια της προπόνησης θα νικήσει τον σκοπό του. Τι νομίζετε;

Πιστεύω ακράδαντα ότι αυτή η απόκλιση πρέπει να λυθεί στον Κέρα. Έχω δει ακόμη πιο βαθιά αποτελέσματα (από 100% έως και 50% ακρίβεια) σε εφαρμογές πραγματικού κόσμου που προκαλούνται από αυτό το πρόβλημα. Εγώ σχέδιο αποστολής έχει ήδη σταλεί α PR στον Κέρα με την επισκευή και ελπίζουμε να γίνει αποδεκτή.

Αν σας άρεσε αυτό το blogpost, αφιερώστε λίγο χρόνο για να το μοιραστείτε στο Facebook ή στο Twitter. 🙂

Σφραγίδα ώρας:

Περισσότερα από Databox