Git als Verwaltungstool für Trainingsdaten und Experimente beim ML
Wir beginnen in diesem Teil der Artikelserie über MLOps mit Informationen, die den meisten von euch bekannt sein werden: Mit den Basics von Git. Um jedoch eine andere Sichtweise auf das bekannte Tool aufzuzeigen, bieten diese Grundlagen die Basis, um die Funktion und Vorteile von Git für das maschinelle Lernen (ML) und den Unterschied bei der Verwaltung von Trainingsdaten zu betonen.
Denn verglichen zur normalen Softwareentwicklung ergeben sich andere nützliche Ansätze, die für eure Arbeit bei ML mit vielen Daten entscheidend sind. Weshalb es oft ausreicht, bekannte Tools wie Git zur Code- und Datenverwaltung heranzuziehen, zeigen wir euch in diesem Beitrag.
Im Rahmen von Machine Learning brauchen wir Code und Daten für das Training und Code für die Anwendung von Modellen. Nach und nach erhalten wir verschiedene Versionen des trainierten Modells, die sich oft in kleinen, aber wichtigen Details unterscheiden. Es entstehen allmählich ganz viele Versionen und Branches. Eine große Herausforderung ist, diese vielen Versionen zu verwalten und bestehen zu lassen. Darin liegt der Kern bei der unterschiedlichen Anwendung von Git im Kontext eines ML-Projekts: Statt einer weitestgehend linearen Prozessentwicklung, wie es bei normaler Softwareentwicklung üblich ist, zweigen wir bei ML experimentell ab und führen dann die Features manchmal zusammen - aber nicht immer. Daher ist das Datenmanagement und das Experimentenmanagement so wesentlich bei ML. Insbesondere der Bestand dieser Experimentier-Branches ist essentiell - warum, das zeigen wir euch jetzt. Data as code ist in diesem Zusammenhang ein wichtiger Schlüsselbegriff, der ausdrückt, wie bedeutungsvoll die Speicherung einer eindeutigen Versionierung der verwendeten Trainingsdaten für eure Projekt-Verwaltung bei Git ist. Ihr wisst nie, wann ihr auf eine alte Version von Daten zurückgreifen müsst, zum Beispiel wegen eines neuen Papers, bei dem alte Daten plötzlich einen Sinn ergeben - oder um vergleichen zu können, wie sich eine Änderung der Daten auf euer Modell auswirkt. Mit Hilfe der eindeutigen Verknüpfung durch den Git-Hash könnt ihr bequem zu allen Zwischenschritten und Modellvarianten zurückgelangen. Durch Speichern des Hashs mit dem Trainingsergebnis habt ihr immer die eindeutige Zuordnung eurer Trainingsdaten - keine Version geht verloren.
Git zur Verwaltung der Trainingsdaten
In jedem normalen ML-Entwicklungsprojekt kommen immer wieder neue Daten hinzu - Bilder, Texte oder andere Assets. Mit Git könnt ihr all eure Ordner mit den zugehörigen Daten mitführen - Git vergisst nichts. Solange es nicht zu viele Daten sind, könnt ihr Git gut dafür nutzen. Bei ML haben wir es auch manchmal mit vielen Daten und schnellen Änderungen zu tun. Da kann Git auch mal an seine Grenzen stoßen. Faustregel ist daher: bei bis zu einigen hundert MB reicht Git für die Arbeit mit Trainingsdaten. Welche Wege ihr dann gehen könnt, um mit noch mehr Daten zu arbeiten, zeigen wir euch in einem der nächsten Artikel, in denen es auch um Beispiele zur Verwendung mit shares geht, wie NAS (Network Attached Storage) oder um Erweiterungen von Git, um mit größeren Datenmengen klar zu kommen.
Git zur Verwaltung von Experimenten
Normalerweise werden Feature- und Bugfix-Branches nach einiger Zeit gelöscht, nachdem ihr sie in den Hauptbranch gemerged habt - sie werden für gewöhnlich nicht mehr gebraucht. Auch wenn wir also immer wieder abzweigen, ergibt sich doch nach einem Merge eine “lineare” Entwicklungsgeschichte. Bei ML experimentieren wir öfter, wir probieren aus, Änderungen können übernommen werden oder auch nicht. Wichtig ist jedoch, auch verworfene Experimente zu archivieren und nicht vollständig zu löschen. Denn manchmal kann es sein, dass eine Idee Monate später wieder aufgegriffen wird, oder man möchte zumindest einen alten Stand als Referenz aufheben, um nachvollziehen zu können, warum eine Idee nicht funktioniert hat.
Da Git alle Branches vom Prinzip her gleich behandelt, ist es eine organisatorische Frage in eurem Team, wie ihr Branches richtig kennzeichnet, die dann gemerged und gelöscht oder archiviert werden, indem ihr ihnen sprechende Namen gebt (beispielsweise “experiment/gelu_activactions”). Herkömmliche Feature-Branches, Bugfix-Branches etc. werden, wie bei herkömmlicher Softwareentwicklung üblich, gemerged und gelöscht. Branches mit Experimenten hingegen sollten aus den oben genannten Gründen langfristig aufbewahrt werden. Je nachdem, wie ihr euren zentralen Git-Server hostet (z.B. auf Github, mit bitbucket, GitLab oder anderen Lösungen), können Einstellungen am Repository oder Commit-Hooks neben organisatorischen Maßnahmen dafür sorgen, dass Experimentier-Branches aufbewahrt werden. So kann Git als automatisches Backup eurer Trainingsversionen dienen, sodass nichts gelöscht wird.
Texte, Assets, Logos - aber auch Trainingsdaten - alles in Git
Wie wir eben beschrieben haben, könnt ihr im Prinzip alles in Git machen. Es erlaubt euch eine 80-20-Lösung, die euch einfach und effizient in eurer Arbeit unterstützt, ohne gleich aufwändigere, zusätzliche Tools in euren Workflow einzubeziehen. Bevor ihr über große Maschinerien nachdenkt, probiert aus, welche Möglichkeiten euch mit Git zur Verfügung stehen. Wenn ihr euer Modell mit Texten, Bildern oder anderen Daten trainieren möchtet, oder Ein- und Ausgaben vergleichen wollt und iterativ trainiert, Git kann genauso Daten wie Code verwalten. Ob ein Bild, wie bei herkömmlicher Web-Entwicklung einfach ein Logo oder ein Trainingsdatum ist, ist Git egal - warum also gleich zu einem neuen Tool greifen? Wichtig ist dabei stets eine sprechende Benennung, um die organisatorische Struktur nicht zu gefährden. Hier einige Beispiele aus unserer täglichen Arbeit, um zu entscheiden, wann ihr eure Daten zusammen mit den Trainings-, Validierungs- und Testdaten bequem mit dem dazugehörigen Code in Git verwalten könnt - und wann nicht:
- Transfer-Training mit Texten: Der Vorteil neuer, vortrainierter Sprachmodelle ist, dass immer weniger Daten für die eigentliche Anpassung an eine spezielle Aufgabe benötigt werden. Die speziellen Trainingsdaten für unsere NLP/NLG-Engine “Sokratext” z.B. sind nur wenige, handkurierte MB Text. Diese können am bequemsten direkt in Git mit dem Trainingscode gespeichert werden - wir machen das schon lange so und sparen so viel Zeit in unseren Workflow.
- Transfer-Training für einen Bild-Classifier mit einigen hundert oder tausend Bildern: auch einige hundert Megabyte sind in diesem Fall für Git kein Problem, solange nur langsam neue Daten hinzukommen. So wisst ihr genau, welcher Code-Stand mit welchem Datensatz trainiert wurde.
- Training für kleinere neuronale Netze auf wenigen MB Zeitreihendaten: auch hier gilt: Die Art der Daten ist egal, solange euer Repo nicht zu sehr anwächst, ist ein eindeutiger Git-Hash die perfekte Referenz für die verwendeten Trainingsdaten, um nachzuvollziehen, womit ein Modell trainiert wurde.
- Wächst die Datenmenge allerdings zu sehr, z.B. bei einem umfangreichen Pretraining auf Wikipedias, großen Web-Scraping Datensätzen oder Videodaten, dann erst stößt man mit Git an seine Grenzen.
In der Praxis benötigt ihr also oft kein zusätzliches Tool, das ihr euch antrainieren (und ggfs. bezahlen) müsst, um ML zu betreiben. Das bedeutet einen enormen Vorteil hinsichtlich Zeitersparnis, da ihr bereits alle Kniffe und Züge zur Verwaltung des Codes kennt - und diese einfach auch auf Daten anwendet. Vielleicht hilft euch diese Orientierung bei euren Experimenten und in eurer Einschätzung, wann Git eine gute Methode zur Datenverwaltung für euer Projekt ist. Wie hat euch Git in der Entwicklung am besten unterstützt und wobei nicht? Schreibt uns gern euer Feedback - wir freuen uns über eure Erfahrung! Ihr könnt außerdem auch auf die kommenden Artikel gespannt sein - unter anderem steigen wir mehr in das Thema DJL als Framework ein und wie ihr Maven in den Entwicklungsprozess einbezieht.