paint-brush
Software für die Erkundung: Ausgewogenheit bei der Entdeckung erreichenvon@sinavski
331 Lesungen
331 Lesungen

Software für die Erkundung: Ausgewogenheit bei der Entdeckung erreichen

von Oleg SInavski10m2024/03/21
Read on Terminal Reader

Zu lang; Lesen

Ein Beitrag, der argumentiert für: - Vermeidung zu vieler Produktionstechniken während der Forschung. Produktion und Forschung verfolgen unterschiedliche Ziele - Es ist in Ordnung, in der Forschung „technische Schulden“ aufzunehmen, da der Großteil des Codes sterben wird. Sie sollten beispielsweise nicht die Wiederverwendung von Code anstreben - Aber als Forscher sollten Sie dennoch in schnelle Erkundung, schnelle Verzweigungen und sauberen, einfachen Code investieren
featured image - Software für die Erkundung: Ausgewogenheit bei der Entdeckung erreichen
Oleg SInavski HackerNoon profile picture

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.

1. Nehmen Sie strategische Technologieschulden auf

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.

Während der Exploration sterben viele Projekte aus. Sie sollten nur während der Ausnutzung eine robuste Lösung erstellen.

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.

Es ist in Ordnung, in der Forschung Softwareschulden zu machen – man muss sie nicht vollständig zurückzahlen, sondern nur für die Minderheit auf den erfolgreichen Forschungspfaden.

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.

Der Fall gegen die Wiederverwendung von Code

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.

Überlegen Sie es sich zweimal, bevor Sie etwas Neues importieren

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:

  • Sie haben es bereits verwendet, es gibt nicht viel zu lernen, es gibt eine große Community, gute Dokumente und Tests
  • Es ist versioniert und einfach zu installieren
  • und schließlich gibt es keine Möglichkeit, es selbst umzusetzen.

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.

Copypaste gibt Ihnen die Freiheit des Experimentierens

Das Einfügen von Kopien geht schnell und ist manchmal das beste Werkzeug bei der Recherche.

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 Pflege gemeinsamer Forschungscodes ist schwierig

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.

Die Dateilänge von Torch.nn.Module hängt von der PyTorch-Version ab. Es wird nicht einfacher.

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.

Design für die Erkundung, nicht für die Wiederverwendung von Code

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:

  • Erstellen von Komponentenschnittstellen zu früh im Projekt. Sie werden zu viel Zeit damit verbringen, sich an selbst geschaffene künstliche Zwänge anzupassen
  • Optimierung der Deep-Learning-Schulungsinfrastruktur, bevor Sie sich für eine Deep-Learning-Lösung entscheiden
  • Verwendung von Produktionskonfigurationen/Fabriken/Serialisierungssystemen oder Basisklassen. Oft ist deren Funktionalität beim Prototyping nicht erforderlich
  • zu strenge Flusen- und Typprüfsysteme. Kein Grund, den sich schnell ändernden Wegwerf-Forschungscode zu bremsen.

2. Investieren Sie in eine schnelle Erkundung

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.

Gemeinsame Wege beschleunigen

Investieren Sie in die Beschleunigung gemeinsamer Teile Ihrer Forschungsprojekte.

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:


  • Wenn Sie tiefe Netzwerke trainieren, investieren Sie in die Trainingsinfrastruktur. Finden Sie Hyperparameter heraus, die Ihnen eine schnelle und zuverlässige Konvergenz während des Trainings ermöglichen
  • Wenn Sie für jedes Experiment ein anderes Modell verwenden müssen, finden Sie heraus, wie Sie diese schnell austauschen können (z. B. durch Verwendung eines einfachen Fabriksystems oder einfach durch Kopieren und Einfügen).
  • Wenn jedes Experiment zu viele Parameter hat und schwer zu verwalten ist, investieren Sie in eine schöne Konfigurationsbibliothek.

Verzweigen Sie sich schnell

Investieren Sie in die Geschwindigkeit, mit der neue Forschungswege eingeleitet werden. Um die Lösung zu finden, sind viele unterschiedliche Richtungen erforderlich.

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:

  • Halten Sie den Evaluierungscode von den Algorithmen getrennt. Bewertungen sind in der Regel stabiler als Forschungsrichtungen
  • Nehmen Sie es in Kauf, ein neues Projekt ganz von vorn zu beginnen, aber achten Sie dann darauf, welche Komponenten wiederverwendet werden. Sie zu modularisieren und zu bereinigen ist eine gute Investition
  • Implementieren Sie in einem neuen Forschungsprojekt zuerst die innovativste und riskanteste Komponente. Dadurch werden die meisten Engpässe identifiziert, die das zukünftige Softwaredesign beeinflussen.

Erhöhen Sie das Signal-Rausch-Verhältnis

Fehler und Nichtdeterminismus können Forschungsprojekte zum Scheitern bringen und dazu führen, dass die Ergebnisse nicht schlüssig sind

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:


  • Verstehen Sie, ob Rauschen vom Algorithmus oder seiner Auswertung herrührt. Lärmquellen verstärken sich und Sie sollten eine vollständig deterministische Bewertung anstreben.
  • Hören Sie nicht auf, Zufälligkeitsquellen zu finden, bis Sie wirklich ein reproduzierbares Skript erhalten. Denken Sie daran, dass nach dem Auffinden aller zufälligen Startwerte Rauschen von Daten oder von generischen Funktionen mit Nebenwirkungen herrühren kann.
  • Variieren Sie Samen und bestimmen Sie die Basisvarianz Ihrer Ergebnisse. Treffen Sie keine Entscheidungen auf der Grundlage nicht statistisch signifikanter Ergebnisse.

Abschluss

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:


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 .