Ich habe mein ganzes Leben lang in der Forschung gearbeitet, daher kenne ich das Klischee, dass Forscher hässlichen Code schreiben (siehe z. B. hier , hier oder hier ). Aber ich dachte: Wir können es reparieren, oder? Deshalb habe ich mehrmals versucht, schöne Forschungsrahmen zu entwerfen. Ich habe versucht, mithilfe von Software-Engineering-Büchern und Blogs, die ich gern gelesen habe, Schnittstellen einzuführen und schöne Abstraktionen zu erstellen.
Doch all diese Bemühungen waren immer wieder vergebens. Der Großteil der Forschungssoftware, an der ich gearbeitet habe, ging nie in Produktion (obwohl einige es schon taten). Es wäre großartig für meine geistige Gesundheit gewesen, wenn mir jemand eine einfache Wahrheit gesagt hätte: Sterbender Forschungscode ist eigentlich das, was passieren soll . Forscher sollten von vornherein nicht viel Zeit damit verbringen, es zu entwickeln.
Professionelle Softwareentwickler schauen immer auf Forscher herab, die nicht die besten Softwarepraktiken anwenden. Es gibt mehrere Beiträge, die versuchen, die Messlatte für Forschungscode höher zu legen (z. B. dieser großartige Beitrag und ein Handbuch zum Forschungscode ). Aber dieser Beitrag geht andersherum: Er argumentiert, wie man es mit den besten Softwarepraktiken nicht übertreibt und stattdessen nur in schnelle Erkundung investiert. Es richtet sich an forschungsorientierte Unternehmen, deren Ziel es ist, viele Ideen schnell auszuprobieren.
Ein erfolgreiches Forschungsprojekt in einem Unternehmen besteht aus zwei Phasen: Exploration und Exploitation. Beim „Explorieren“ möchten Sie möglichst viele unterschiedliche Lösungen ausprobieren. Bei der „Ausbeutung“ müssen Sie die beste Lösung robustisieren und in ein nützliches Produkt umwandeln.
Die optimalen Softwarepraktiken unterscheiden sich erheblich. Aus diesem Grund verfügen Unternehmen oft über getrennte Forschungs- und Produktbereiche. In allen Büchern, die Sie normalerweise zum Thema Softwaredesign lesen, geht es hauptsächlich um die zweite „Ausbeutungsphase“. In dieser Phase schaffen Sie den Grundstein für ein skalierbares Produkt. Hier kommen alle Entwurfsmuster ins Spiel: nette APIs, Protokollierung, Fehlerbehandlung und so weiter.
Aber in der ersten „Erkundungsphase“ baut man keine Fundamente, die ewig bestehen bleiben. Wenn die meisten Ihrer Bemühungen bestehen bleiben, dann haben Sie (per Definition) nicht genug erforscht.
Viele Praktiken in diesem Beitrag sind Beispiele dafür, was normalerweise zu „Tech-Schulden“ führen würde. Das erreichen Sie, wenn Sie keinen sauberen, wiederverwendbaren, gut abstrahierten Code schreiben. Sind Schulden immer schlecht? Wir nehmen lieber nie einen Kredit oder eine Hypothek auf, aber Geld zu leihen ist oft eine gute Strategie im Leben. Es ist in Ordnung, sich zu verschulden, um schnell voranzukommen und später Gewinne zu erzielen.
Ebenso verlangsamen Sie möglicherweise Ihre Forschung, wenn Sie keine technischen Schulden aufnehmen. Die gute Nachricht ist, dass Sie es in den meisten Fällen nicht zurückzahlen müssen. Der Großteil Ihres Forschungscodes wird wahrscheinlich sowieso sterben. Im Durchschnitt werden Sie also nicht unter den gesamten technischen Schulden leiden, die Sie aufgenommen haben.
Viele Softwarearchitekturen und Refactoring-Techniken sind speziell darauf ausgerichtet, die Wiederverwendbarkeit von Code zu verbessern. Die Wiederverwendung von Code hat allgemeine Nachteile . In der Produktion werden sie jedoch durch die bekannten Vorteile aufgewogen (siehe beispielsweise diesen typischen Beitrag ). In Forschungsprojekten ist der Großteil des Codes dazu verdammt, in Vergessenheit zu geraten. Das Streben nach Wiederverwendung von Code könnte Sie tatsächlich verlangsamen.
Die Einschränkung der Code-Wiederverwendung ist die Art technischer Schulden, die in der Forschung in Kauf genommen werden darf. Es gibt mehrere Muster der Code-Wiederverwendung, die ich diskutieren möchte: Hinzufügen einer unnötigen Abhängigkeit, Kopieren von Code, Beibehalten einer Menge gemeinsam genutztem Forschungscode, vorzeitige Designinvestitionen.
Wenn Sie eine gut gepflegte versionierte Bibliothek kennen, die Sie schneller macht, dann greifen Sie zu! Aber bevor Sie eine neue Abhängigkeit aufnehmen, sollten Sie überlegen, ob es sich lohnt. Jeder weitere bringt Sie der Abhängigkeitshölle näher. Dadurch investieren Sie Zeit in das Erlernen und in die Fehlerbehebung. Weitere Fallstricke von Abhängigkeiten finden Sie in diesem kurzen Beitrag .
Es ist wahrscheinlich in Ordnung, sich auf etwas zu verlassen, wenn:
Seien Sie jedoch vorsichtig bei einer Abhängigkeit, wenn:
Sie können nicht schnell herausfinden, wie man es benutzt, es ist sehr neu (oder sehr alt) oder niemand scheint davon zu wissen; Es gibt keine Dokumente oder Tests
Es stammt aus Ihrem Monorepo und wird ständig von anderen Teams geändert
es bezieht viele andere Abhängigkeiten und Tools ein; oder es ist einfach nur schwer zu installieren
und schließlich haben Sie das Gefühl, dass Sie (oder ein LLM) diesen Code in ein paar Stunden schreiben können.
Anstelle einer expliziten Abhängigkeit können Sie einem schönen Go-Sprichwort folgen: „ Ein wenig Kopieren ist besser als eine kleine Abhängigkeit “, was unser nächstes Thema ist.
Manche sagen, dass „ Kopieren und Einfügen illegal sein sollte “. Aber zu meiner Überraschung habe ich mich ziemlich oft dafür ausgesprochen. Copypaste könnte während der Erkundungsphase die optimale Wahl sein.
Wenn Sie auf eine stark genutzte Funktion aus einem anderen Teil der Codebasis angewiesen sind, können Sie vergessen, sie einfach zu ändern. Es ist wahrscheinlich, dass Sie jemandem etwas kaputt machen und wertvolle Zeit in Codeüberprüfungen und -korrekturen investieren müssen. Wenn Sie jedoch den erforderlichen Code kopieren und in Ihren Ordner einfügen, können Sie damit alles machen, was Sie wollen. Dies ist eine große Sache bei Forschungsprojekten, bei denen Experimente eher die Norm als die Ausnahme sind. Vor allem, wenn Sie nicht sicher sind, ob Änderungen für alle von Nutzen sein werden.
Ich finde, dass Deep-Learning-Codebasen am besten zum Kopieren geeignet sind. Normalerweise ist die Menge an Code, die zur Beschreibung eines Modells und seines Trainings erforderlich ist, nicht so groß. Aber gleichzeitig kann es sehr nuanciert und schwer zu verallgemeinern sein. Gemeinsam nutzbare Trainingsskripte neigen dazu, eine unüberschaubare Größe zu erreichen: Beispielsweise hat Hugging Face transformers
Trainer +4.000 Zeilen. Interessanterweise haben sich Transformer auf Modellebene für Copypaste entschieden. Bitte lesen Sie ihren Beitrag mit der Begründung für ihre „Single-File-Modell“-Richtlinie. Weitere Ressourcen über die Schönheit von Copypaste finden Sie am Ende.
Eine Alternative zum Kopieren und Einfügen besteht darin, in einem Zweig zu bleiben. Aber ich habe das Gefühl, dass es bei der Teamarbeit zu viel Aufwand mit sich bringt. Außerdem habe ich mehrere weitere Beiträge über die Schönheit von Copypaste gefunden – weitere Beiträge finden Sie im Fazit.
Die Wartung von stark genutztem Shared Code erfordert viel Arbeit. Sehen Sie sich die Anzahl der Dateizeilen von torch.nn.Module
im Vergleich zur Pytorch
Version an. Sie sehen, dass selbst die fortschrittlichsten Forschungsteams Schwierigkeiten haben, die Komplexität unter Kontrolle zu halten.
Unterschätzen Sie nicht den Zeit- und Ressourcenaufwand, der für die Pflege eines großen gemeinsamen Forschungscodes erforderlich ist. Je häufiger eine Forschungsbibliothek genutzt wird, desto komplizierter wird es. Dies geschieht schneller als in einer typischen Bibliothek, da jede Forschungsrichtung einen etwas anderen Anwendungsfall hat. Legen Sie sehr strenge Regeln fest, was zurückgezahlt werden kann. Andernfalls wird der gemeinsam genutzte Code brüchig und mit einer Vielzahl von Optionen, fehlerhaften Optimierungen und Randfällen überwuchert. Da der Großteil des Forschungscodes ausstirbt, wird all diese zusätzliche Komplexität nie wieder verwendet. Wenn Sie einen Teil Ihres freigegebenen Codes löschen, gewinnen Sie etwas Zeit für die eigentliche Recherche.
Es ist in gewisser Weise richtig, dass Sie Ihren Code auch in der Produktion nicht zu sehr zukunftssicher machen möchten. Versuchen Sie, eine möglichst einfache Lösung zu implementieren, die den Anforderungen entspricht. Aber im Produktionscode müssen immer Aspekte der Wartbarkeit berücksichtigt werden. Beispielsweise müssen Sie normalerweise über Fehlerbehandlung, Geschwindigkeit, Protokollierung und Modularisierung nachdenken.
Im Forschungscode spielt das keine Rolle. Sie möchten nur schnellstmöglich beweisen, dass eine Idee gut oder schlecht ist, und dann weitermachen. Die schmutzige Einfachheit, die ohne Module oder APIs erreicht wird, ist also völlig in Ordnung!
Verschwenden Sie keine wertvolle Zeit mit vorzeitigen Software-Investitionen wie:
Das Ziel eines Forschungsprojekts ist es, eine neuartige Lösung zu finden. Niemand weiß (per Definition), wie es aussieht. Es ähnelt einem Optimierungsprozess in einer komplizierten Forschungslandschaft mit begrenzten Informationen. Um ein gutes Minimum zu finden, müssen Sie viele Pfade ausprobieren, gute und schlechte Pfade erkennen und dürfen nicht in lokalen Minima stecken bleiben. Um alles schnell zu erledigen, müssen Sie manchmal in Software investieren, anstatt technische Schulden aufzunehmen.
Es gibt verschiedene Forschungswege, die Sie ausprobieren möchten. Gibt es ein Design, eine Bibliothek oder eine Optimierung, die bei den meisten Pfaden Zeit einsparen würde? Sie sollten darauf achten, nichts zu sehr zu konstruieren, da Sie nicht immer alle Ideen kennen, die Sie ausprobieren möchten. Dies ist für jedes Projekt sehr individuell, aber hier sind einige Beispiele:
Forscher sollen in der Lage sein, schnell neue, vielfältige Ideen zu initiieren. Zu Beginn des Projekts scheint es einfach zu sein. Aber dann wird es immer schwieriger, wenn die Menschen sich auf ihre bevorzugten Forschungswege festlegen. Um diesem entgegenzuwirken, sind kulturelle und organisatorische Veränderungen unerlässlich. Es sollte einen Prozess geben, der nicht erfolgversprechende Forschung stoppt, bevor zu viel Geld und Emotionen in sie gesteckt werden. Regelmäßige Demotage und technische Peer-Reviews können hierfür wirksame Strategien sein. Es ist auch wichtig, ein Gleichgewicht zu finden zwischen Leuten, die sich auf eine neue glänzende Idee einlassen, und dem richtigen Abschluss aktueller Projekte.
Da dies jedoch ein Software-Beitrag ist, finden Sie hier einige Vorgehensweisen, die das Verzweigen neuer Projekte erleichtern:
Lauter und fehlerhafter Code führt dazu, dass die Ergebnisse so mehrdeutig und nicht schlüssig sind, dass das gesamte Projekt Zeitverschwendung ist. Obwohl Sie nicht zu viel entwickeln sollten, können Sie diese einfachen Faustregeln leicht befolgen, um unordentlichen Code zu vermeiden:
Vermeiden Sie Code mit Nebenwirkungen
Standardmäßig werden Funktionen anstelle von Klassen verwendet. und bei Klassen bevorzugen Sie Kapselung gegenüber Vererbung
Länge von Funktionen/Klassen/Modulen minimieren; Minimieren Sie die Anzahl der If-Anweisungen
Ich kenne Python gut, verwende aber einfache Techniken. Widerstehen Sie der Versuchung, sich auf die intellektuellen Abgründe von Metaklassen, Dekoratoren und funktionaler Programmierung einzulassen.
Es ist schwierig, mit Software zu arbeiten, die bei verschiedenen Durchläufen unterschiedliche Ergebnisse liefert. Wenn Sie aufgrund eines unglücklichen Samens eine wichtige, aber falsche Entscheidung getroffen haben, werden Sie viel Zeit mit der Genesung verschwenden. Hier einige Tipps zum Umgang mit nichtdeterministischer Software:
Die Pointe stammt aus diesem Beitrag über Forschungscode:
„Man kümmert sich nicht um [gutes Softwaredesign], weil es nicht um den Code geht. Der Code ist ein Werkzeug, das Ihnen die Antwort liefert, die Sie brauchen.“
Es ist äußerst wichtig, über gute Codierungsgrundlagen zu verfügen. Aber letztendlich kommt es auf die Erkundung und das tatsächlich nützliche Produkt an. Wenn Sie in der Forschung zu viel Produktionssoftware verwenden, verschwenden Sie die Zeit, die Sie brauchen, um etwas Neues zu entdecken. Finden Sie stattdessen heraus, was Ihren Erkundungsprozess verlangsamt. Beschleunigen Sie Forschungswege, indem Sie in schnelle Verzweigungen, schnelle Ergebnisse und sauberen, geräuschlosen Code investieren.
Es wäre verrückt, komplett gegen die Wiederverwendung von Code zu argumentieren. Ich möchte nur darauf hinweisen, dass die Wiederverwendung von Code eine ausgewogene Aktivität sein sollte. In der Forschung ist der Anteil an Wegwerfcode größer als in der Produktion. Die Waage neigt sich weiter gegen eine Wiederverwendung. Hier sind einige weitere großartige Beiträge mit Fallstricken bei der Wiederverwendung von Code:
Wiederverwendbarer Code: Das Gute, das Schlechte und das Hässliche
Ausgewogener StackExchange mit Vor- und Nachteilen der Wiederverwendung
Und hier sind noch ein paar Beiträge, die sich für Copypaste-Praktiken aussprechen:
Vielen Dank fürs Lesen! Ich habe das Gefühl, dass einige Teile etwas kontrovers sind. Bitte lassen Sie es mich in den Kommentaren wissen!
Erscheint auch hier .