Unit Testing ist dein Freund
Es gibt ein Sprichwort unter den Schriftstellern, dass "alles Schreiben ein Umschreiben ist" - das heißt, der größte Teil des Schreibens wird überarbeitet. Für Programmierer (oder zumindest Datenwissenschaftler) könnte der Ausdruck wie folgt umformuliert werden: "Die gesamte Codierung ist Debugging."
Jedes Mal, wenn Sie Code schreiben, müssen Sie sicherstellen, dass er wie beabsichtigt funktioniert. Die beste Methode, die ich je zur Überprüfung der Richtigkeit gefunden habe, besteht darin, den Code in kleine Segmente zu unterteilen und zu überprüfen, ob jedes Segment funktioniert. Dies kann erreicht werden, indem die Segmentausgabe mit der richtigen Antwort verglichen wird. Dies wird Unit-Test genannt . Das Schreiben guter Komponententests ist ein Schlüsselelement, um ein guter Statistiker / Datenwissenschaftler / Experte für maschinelles Lernen / Praktiker für neuronale Netze zu werden. Es gibt einfach keinen Ersatz.
Sie müssen überprüfen, ob Ihr Code fehlerfrei ist, bevor Sie die Netzwerkleistung optimieren können! Andernfalls können Sie Liegestühle auf der RMS Titanic auch neu anordnen .
Bei neuronalen Netzen gibt es zwei Merkmale, die die Verifizierung noch wichtiger machen als bei anderen Arten des maschinellen Lernens oder bei statistischen Modellen.
Neuronale Netze sind keine Standardalgorithmen wie zufällige Gesamtstrukturen oder logistische Regressionen. Selbst bei einfachen Feed-Forward-Netzwerken muss der Benutzer zahlreiche Entscheidungen darüber treffen, wie das Netzwerk konfiguriert, verbunden, initialisiert und optimiert wird. Dies bedeutet das Schreiben von Code und das Schreiben von Code das Debuggen.
Selbst wenn ein neuronaler Netzwerkcode ausgeführt wird, ohne eine Ausnahme auszulösen, kann das Netzwerk dennoch Fehler aufweisen! Diese Fehler könnten sogar die heimtückische Art sein, für die das Netzwerk trainiert, bleiben aber bei einer suboptimalen Lösung hängen, oder das resultierende Netzwerk weist nicht die gewünschte Architektur auf. ( Dies ist ein Beispiel für den Unterschied zwischen einem syntaktischen und einem semantischen Fehler .)
Dieses Medium Beitrag „ Wie Unit - Test für maschinelles Lernen Code “ von Chase Robert diskutiert Komponententests für die Modelle für maschinelles Lernen im Detail. Ich habe dieses Beispiel für Buggy-Code aus dem Artikel ausgeliehen:
def make_convnet(input_image):
net = slim.conv2d(input_image, 32, [11, 11], scope="conv1_11x11")
net = slim.conv2d(input_image, 64, [5, 5], scope="conv2_5x5")
net = slim.max_pool2d(net, [4, 4], stride=4, scope='pool1')
net = slim.conv2d(input_image, 64, [5, 5], scope="conv3_5x5")
net = slim.conv2d(input_image, 128, [3, 3], scope="conv4_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool2')
net = slim.conv2d(input_image, 128, [3, 3], scope="conv5_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool3')
net = slim.conv2d(input_image, 32, [1, 1], scope="conv6_1x1")
return net
Siehst du den fehler Viele der verschiedenen Operationen werden nicht verwendet, da vorherige Ergebnisse mit neuen Variablen überschrieben werden. Die Verwendung dieses Codeblocks in einem Netzwerk wird weiterhin trainiert und die Gewichte werden aktualisiert und der Verlust kann sich sogar verringern - aber der Code tut definitiv nicht das, was beabsichtigt war. (Der Autor ist auch in Bezug auf die Verwendung von einfachen oder doppelten Anführungszeichen inkonsistent, aber das ist rein stilistisch.)
Die häufigsten Programmierfehler bei neuronalen Netzen sind
- Variablen werden erstellt, aber nie verwendet (normalerweise aufgrund von Fehlern beim Kopieren und Einfügen).
- Ausdrücke für Gradientenaktualisierungen sind falsch.
- Gewichtsaktualisierungen werden nicht angewendet.
- Verlustfunktionen werden nicht auf der richtigen Skala gemessen (zum Beispiel kann der Kreuzentropieverlust in Form von Wahrscheinlichkeiten oder Logs ausgedrückt werden)
- Der Verlust ist für die Aufgabe nicht geeignet (z. B. Verwendung eines kategorialen entropieübergreifenden Verlusts für eine Regressionsaufgabe).
Kriechen, bevor Sie gehen; Gehen Sie, bevor Sie rennen
Breite und tiefe neuronale Netze und neuronale Netze mit exotischer Verkabelung sind derzeit das A und O beim maschinellen Lernen. Aber diese Netzwerke sind nicht vollständig entstanden. Ihre Designer haben sich aus kleineren Einheiten zusammengesetzt. Erstellen Sie zunächst ein kleines Netzwerk mit einer einzelnen verborgenen Ebene und stellen Sie sicher, dass es ordnungsgemäß funktioniert. Fügen Sie dann schrittweise zusätzliche Modellkomplexität hinzu und vergewissern Sie sich, dass jede dieser Funktionen auch funktioniert.
Zu wenige Neuronen in einer Ebene können die Darstellung, die das Netzwerk lernt, einschränken und zu einer Unteranpassung führen. Zu viele Neuronen können zu einer Überanpassung führen, da sich das Netzwerk die Trainingsdaten "merkt".
Auch wenn Sie mathematisch nachweisen können, dass nur eine geringe Anzahl von Neuronen zur Modellierung eines Problems erforderlich ist, ist es für den Optimierer häufig einfacher , eine "gute" Konfiguration zu finden , wenn "ein paar" Neuronen vorhanden sind. (Ich glaube jedoch, dass niemand vollständig versteht, warum dies der Fall ist.) Ich gebe hier ein Beispiel im Zusammenhang mit dem XOR-Problem: Werden meine Iterationen nicht benötigt, um NN für XOR mit MSE <0,001 zu hoch zu trainieren? .
Wenn Sie die Anzahl der ausgeblendeten Ebenen auswählen, lernt das Netzwerk eine Abstraktion aus den Rohdaten. Deep Learning ist heutzutage der letzte Schrei, und Netzwerke mit einer großen Anzahl von Ebenen haben beeindruckende Ergebnisse gezeigt. Das Hinzufügen zu vieler versteckter Ebenen kann jedoch zu einer Überanpassung des Risikos führen oder die Optimierung des Netzwerks erheblich erschweren.
Die Wahl einer cleveren Netzwerkverkabelung kann einen Großteil der Arbeit für Sie erledigen. Ist Ihre Datenquelle für spezielle Netzwerkarchitekturen geeignet? Faltungs-Neuronale Netze können beeindruckende Ergebnisse bei "strukturierten" Datenquellen, Bild- oder Audiodaten erzielen. Wiederkehrende neuronale Netze eignen sich gut für sequenzielle Datentypen wie natürliche Sprache oder Zeitreihendaten. Verbleibende Verbindungen können tiefe Feed-Forward-Netzwerke verbessern.
Neuronales Netzwerktraining ist wie das Öffnen von Schlössern
Um hochmoderne oder nur gute Ergebnisse zu erzielen, müssen Sie alle Teile so konfiguriert haben, dass sie gut zusammenarbeiten . Das Einrichten einer neuronalen Netzwerkkonfiguration, die tatsächlich lernt, ähnelt dem Aufheben eines Schlosses: Alle Teile müssen genau richtig ausgerichtet sein. Ebenso wenig, wie es nicht ausreicht, einen einzelnen Becher am richtigen Ort zu haben, reicht es auch nicht aus, nur die Architektur oder nur den Optimierer korrekt einzurichten.
Das Einstellen der Konfigurationsoptionen ist nicht so einfach, als dass gesagt wird, dass eine Art der Konfigurationsauswahl (z. B. Lernrate) mehr oder weniger wichtig ist als eine andere (z. B. Anzahl der Einheiten), da alle diese Auswahlmöglichkeiten mit allen anderen Auswahlmöglichkeiten interagieren Wahl kann in Kombination mit einer anderen Wahl gut tun, die anderswo getroffen wird .
Dies ist eine nicht vollständige Liste der Konfigurationsoptionen, bei denen es sich nicht nur um Regularisierungsoptionen oder numerische Optimierungsoptionen handelt.
Alle diese Themen sind aktive Forschungsbereiche.
Die Netzwerk - Initialisierung wird oft als Quelle von neuronalen Netz Bugs übersehen. Die Initialisierung über ein zu großes Intervall kann die anfänglichen Gewichte zu groß einstellen, was bedeutet, dass einzelne Neuronen einen übergroßen Einfluss auf das Netzwerkverhalten haben.
Der Hauptunterschied zwischen einem neuronalen Netzwerk und einem Regressionsmodell besteht darin, dass ein neuronales Netzwerk aus vielen nichtlinearen Funktionen besteht, die als Aktivierungsfunktionen bezeichnet werden . (Siehe: Was ist der wesentliche Unterschied zwischen dem neuronalen Netz und der linearen Regression? )
Die Ergebnisse klassischer neuronaler Netze konzentrierten sich auf sigmoidale Aktivierungsfunktionen (logistische oder Funktionen). Ein kürzlich veröffentlichtes Ergebnis hat ergeben, dass ReLU-Einheiten (oder ähnliche) tendenziell besser funktionieren, da sie steilere Verläufe aufweisen, sodass Aktualisierungen schnell angewendet werden können. (Siehe: Warum verwenden wir ReLU in neuronalen Netzen und wie verwenden wir es? ) Eine Warnung bei ReLUs ist das Phänomen "totes Neuron", das das Lernen behindern kann. Leaky Relus und ähnliche Varianten vermeiden dieses Problem. SehenTanh
Es gibt eine Reihe weiterer Optionen. Siehe: Umfassende Liste der Aktivierungsfunktionen in neuronalen Netzen mit Vor- / Nachteilen
Restverbindungen sind eine nette Entwicklung, die das Trainieren neuronaler Netze erleichtern kann. "Tiefes
Restlernen für die Bilderkennung " Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun In: CVPR. (2016). Darüber hinaus kann das Ändern der Reihenfolge von Operationen innerhalb des Restblocks das resultierende Netzwerk weiter verbessern. " Identitätszuordnungen in tiefen verbleibenden Netzwerken " von Kaiming He, Xiangyu Zhang, Shaoqing Ren und Jian Sun.
Eine nicht konvexe Optimierung ist schwierig
Die objektive Funktion eines neuronalen Netzwerks ist nur konvex, wenn es keine versteckten Einheiten gibt, alle Aktivierungen linear sind und die Entwurfsmatrix den vollen Rang hat - da diese Konfiguration identisch zu einem normalen Regressionsproblem ist.
In allen anderen Fällen ist das Optimierungsproblem nicht konvex und die nicht konvexe Optimierung ist schwierig. Die Herausforderungen beim Training neuronaler Netze sind bekannt (siehe: Warum ist es schwierig, tiefe neuronale Netze zu trainieren? ). Darüber hinaus haben neuronale Netze eine sehr große Anzahl von Parametern, was uns auf Methoden erster Ordnung beschränkt (siehe: Warum wird Newtons Methode beim maschinellen Lernen nicht häufig verwendet? ). Dies ist ein sehr aktives Forschungsgebiet.
Wenn Sie die Lernrate zu groß einstellen, läuft die Optimierung auseinander, da Sie von einer Seite des "Canyons" zur anderen springen. Wenn Sie diesen Wert zu klein einstellen, können Sie keine wirklichen Fortschritte erzielen, und möglicherweise kann das mit SGD verbundene Rauschen Ihre Gradientenschätzungen überfordern.
Gradient Clipping skaliert die Norm des Gradienten neu, wenn sie einen bestimmten Schwellenwert überschreitet. Früher dachte ich, dass dies ein Set-and-Forget-Parameter ist, normalerweise 1.0, aber ich fand heraus, dass ich ein LSTM-Sprachmodell dramatisch verbessern kann, indem ich es auf 0.25 setze. Ich weiß nicht warum das so ist.
Die Planung der Lernrate kann die Lernrate im Laufe des Trainings verringern. Meiner Erfahrung nach ähnelt der Versuch, die Zeitplanung zu verwenden, einem regulären Ausdruck : Er ersetzt ein Problem ("Wie lerne ich, nach einer bestimmten Epoche fortzufahren?") Durch zwei Probleme ("Wie lerne ich, nach einer bestimmten Epoche fortzufahren") "und" Wie wähle ich einen guten Zeitplan aus? "). Andere Leute bestehen darauf, dass Terminplanung unerlässlich ist. Ich lasse dich entscheiden.
Die Wahl einer guten Minibatch-Größe kann den Lernprozess indirekt beeinflussen, da ein größerer Minibatch tendenziell eine geringere Varianz ( Gesetz der großen Zahlen ) aufweist als ein kleinerer Minibatch. Sie möchten, dass der Mini-Batch groß genug ist, um über die Richtung des Gradienten zu informieren, aber klein genug, damit SGD Ihr Netzwerk regulieren kann.
Es gibt eine Reihe von Varianten für den stochastischen Gradientenabstieg, die Impulse, adaptive Lernraten, Nesterov-Aktualisierungen usw. verwenden, um die Vanille-SGD zu verbessern. Das Entwerfen eines besseren Optimierers ist ein sehr aktives Forschungsgebiet. Einige Beispiele:
Als es herauskam, stieß der Adam-Optimierer auf großes Interesse. Einige neuere Forschungen haben jedoch herausgefunden, dass SGD mit Impuls adaptive Gradientenmethoden für neuronale Netze übertreffen kann. " Der Grenzwert adaptiver Gradientenmethoden im maschinellen Lernen " von Ashia C. Wilson, Rebecca Roelofs, Mitchell Stern, Nathan Srebro und Benjamin Recht
Andererseits schlägt dieses kürzlich erschienene Papier einen neuen Optimierer für adaptive Lernraten vor, der die Lücke zwischen adaptiven Methoden und SGD mit Schwung schließen soll. " Schließung der Generalisierungslücke adaptiver Gradientenmethoden beim Training tiefer neuronaler Netze " von Jinghui Chen, Quanquan Gu
Es wurde beobachtet, dass adaptive Gradientenmethoden, die historische Gradienteninformationen verwenden, um die Lernrate automatisch anzupassen, eine schlechtere als die stochastische Gradientenabnahme (SGD) mit Momentum beim Trainieren tiefer neuronaler Netze verallgemeinern. Daher ist es ein offenes Problem, wie die Generalisierungslücke bei adaptiven Gradientenmethoden geschlossen werden kann. In dieser Arbeit zeigen wir, dass adaptive Gradientenmethoden wie Adam, Amsgrad manchmal "überangepasst" sind. Wir entwerfen einen neuen Algorithmus namens Partially Adaptive Momentum Estimation Method (Padam), der Adam / Amsgrad mit SGD vereint, um das Beste aus beiden Welten zu erzielen. Experimente mit Standardbenchmarks zeigen, dass Padam eine schnelle Konvergenzrate wie Adam / Amsgrad aufrechterhalten kann, während es beim Training tiefer neuronaler Netze Generalisierung und SGD durchführt.
Normalisierung
Der Umfang der Daten kann beim Training einen großen Unterschied machen.
Bevor Sie Daten einem neuronalen Netzwerk präsentieren, können Sie das Training verbessern , indem Sie die Daten so standardisieren , dass sie einen Mittelwert von 0 und eine Einheitsvarianz aufweisen oder in einem kleinen Intervall wie . Dies stellt eine Vorkonditionierung dar und beseitigt die Auswirkung, die eine Auswahl in Einheiten auf die Netzwerkgewichte hat. Beispielsweise repräsentieren Länge in Millimetern und Länge in Kilometern dasselbe Konzept, sind jedoch unterschiedlich skaliert. Die genauen Details zur Standardisierung der Daten hängen davon ab, wie Ihre Daten aussehen.[ - 0,5 , 0,5 ]
Durch die Normalisierung der Schichten kann das Netzwerktraining verbessert werden, indem der Mittelwert und die Standardabweichung für die Neuronenaktivierungen beibehalten werden. Es ist nicht klar, warum dies der Ausbildung hilft, und es bleibt ein aktives Forschungsgebiet.
Regulierung
Die Auswahl und Optimierung der Netzwerk-Regularisierung ist ein wesentlicher Bestandteil der Erstellung eines Modells, das sich gut verallgemeinern lässt (dh ein Modell, das nicht zu den Trainingsdaten passt). Zu der Zeit, in der Ihr Netzwerk Probleme hat, den Verlust der Trainingsdaten zu verringern - wenn das Netzwerk nicht lernt - kann die Regularisierung das Problem verdecken.
Wenn mein Netzwerk nicht lernt, deaktiviere ich alle Regularisierungen und stelle sicher, dass das nicht regularisierte Netzwerk ordnungsgemäß funktioniert. Dann füge ich jedes Regularisierungsstück zurück und überprüfe, ob jedes auf dem Weg funktioniert.
Diese Taktik kann genau bestimmen, wo eine Regularisierung möglicherweise schlecht eingestellt ist. Einige Beispiele sind
L2 Regularisierung (auch bekannt als Weight Decay) oder Regularisierung ist zu groß eingestellt, sodass sich die Gewichte nicht bewegen können.L1
Zwei Teile der Regularisierung stehen in Konflikt. Es ist beispielsweise weithin zu beobachten, dass Schichtnormalisierung und Dropout schwierig zusammen zu verwenden sind. Da beides für sich genommen sehr nützlich ist, ist es ein aktives Forschungsgebiet, zu verstehen, wie man beides einsetzt.
Führen Sie ein Logbuch der Experimente
Wenn ich ein neuronales Netzwerk einrichte, codiere ich keine Parametereinstellungen fest. Stattdessen mache ich das in einer Konfigurationsdatei (z. B. JSON), die gelesen und zum Auffüllen von Netzwerkkonfigurationsdetails zur Laufzeit verwendet wird. Ich behalte all diese Konfigurationsdateien. Wenn ich Parameter ändere, erstelle ich eine neue Konfigurationsdatei. Schließlich füge ich als Kommentar alle epochenbezogenen Verluste für Training und Validierung hinzu.
Der Grund, warum ich so besessen davon bin, alte Ergebnisse beizubehalten, ist, dass es sehr einfach ist, zurück zu gehen und frühere Experimente zu wiederholen. Es schützt auch davor, das gleiche Dead-End-Experiment fälschlicherweise zu wiederholen. Psychologisch gesehen können Sie auch zurückblicken und beobachten: "Nun, das Projekt ist vielleicht nicht dort, wo ich es heute haben möchte, aber ich mache Fortschritte im Vergleich zu dem, wo ich vor Wochen war."k
Als Beispiel wollte ich etwas über LSTM-Sprachmodelle lernen, deshalb habe ich mich für einen Twitter-Bot entschieden, der als Antwort auf andere Twitter-Benutzer neue Tweets schreibt. Daran habe ich in meiner Freizeit gearbeitet, zwischen Schule und Beruf. Es dauerte ungefähr ein Jahr, und ich durchlief über 150 verschiedene Modelle, bevor ich zu einem Modell kam, das genau das tat, was ich wollte: einen neuen Text in englischer Sprache zu generieren, der (irgendwie) Sinn ergibt. (Ein wesentlicher Knackpunkt und ein Grund dafür, dass so viele Versuche unternommen wurden, ist, dass es nicht ausreichte, nur einen geringen Verlust außerhalb der Stichprobe zu erzielen, da frühe Modelle mit geringem Verlust es geschafft hatten, die Trainingsdaten zu speichern.) es wurden also nur wichtige Textblöcke wörtlich als Antwort auf Eingabeaufforderungen reproduziert - es waren einige Anpassungen erforderlich, um das Modell spontaner zu gestalten und dennoch einen geringen Verlust zu erzielen.)