Autoren:
(1) Sasun Hambardzumyan, Activeloop, Mountain View, CA, USA;
(2) Abhinav Tuli, Activeloop, Mountain View, CA, USA;
(3) Levon Ghukasyan, Activeloop, Mountain View, CA, USA;
(4) Fariz Rahman, Activeloop, Mountain View, CA, USA;.
(5) Hrant Topchyan, Activeloop, Mountain View, CA, USA;
(6) David Isayan, Activeloop, Mountain View, CA, USA;
(7) Mark McQuade, Activeloop, Mountain View, CA, USA;
(8) Mikayel Harutyunyan, Activeloop, Mountain View, CA, USA;
(9) Tatevik Hakobyan, Activeloop, Mountain View, CA, USA;
(10) Ivo Stranic, Activeloop, Mountain View, CA, USA;
(11) Davit Buniatyan, Activeloop, Mountain View, CA, USA.
Wie in Abb. 1 dargestellt, speichert Deep Lake Rohdaten und Ansichten in Objektspeichern wie S3 und materialisiert Datensätze mit vollständiger Herkunft. Streaming, Tensor Query Language-Abfragen und die Visualisierungs-Engine werden entweder zusammen mit Deep Learning-Berechnungen oder im Browser ausgeführt, ohne dass ein externer verwalteter oder zentralisierter Dienst erforderlich ist.
4.1.1 Extrahieren. Manchmal liegen Metadaten bereits in einer relationalen Datenbank. Wir haben zusätzlich einen ETL-Zielkonnektor mit Airbyte[3] [22] erstellt. Das Framework ermöglicht das Einbinden in jede unterstützte Datenquelle, einschließlich SQL/NoSQL-Datenbanken, Data Lakes oder Data Warehouses, und das Synchronisieren der Daten in Deep Lake. Das Konnektorprotokoll wandelt die Daten in ein spaltenbasiertes Format um.
4.1.2 Transformieren. Um die Datenverarbeitungsabläufe deutlich zu beschleunigen und Benutzer von der Sorge um das Chunk-Layout zu befreien, bietet Deep Lake eine Option zur parallelen Ausführung von Python-Transformationen. Die Transformation nimmt einen Datensatz auf, iteriert stichprobenweise über die erste Dimension und gibt einen neuen Datensatz aus. Eine benutzerdefinierte Python-Funktion erwartet zwei erforderliche Argumente 𝑠𝑎𝑚𝑝𝑙𝑒_𝑖𝑛, 𝑠𝑎𝑚𝑝𝑙𝑒_𝑜𝑢𝑡 und ist mit @𝑑𝑒𝑒𝑝𝑙𝑎𝑘𝑒.𝑐𝑜𝑚𝑝𝑢𝑡𝑒 dekoriert. Ein einzelnes 𝑠𝑎𝑚𝑝𝑙𝑒_𝑖𝑛 kann dynamisch mehrere 𝑠𝑎𝑚𝑝𝑙𝑒_𝑜𝑢𝑡𝑠 erstellen. Es ermöglicht sowohl Eins-zu-eins- als auch Eins-zu-viele-Transformationen. Die Transformation kann auch direkt angewendet werden, ohne dass ein neuer Datensatz erstellt wird.
Im Hintergrund verarbeitet der Scheduler stichprobenweise Transformationen, die auf benachbarten Blöcken ausgeführt werden, und plant sie in einem Prozesspool ein. Optional kann die Berechnung an einen Ray-Cluster delegiert werden [53]. Anstatt einen Eingabedatensatz zu definieren, kann der Benutzer einen beliebigen Iterator mit benutzerdefinierten Objekten bereitstellen, um Aufnahme-Workflows zu erstellen. Benutzer können auch mehrere Transformationen stapeln und komplexe Pipelines definieren.
Deep Lake geht auch auf die Notwendigkeit der Reproduzierbarkeit von Experimenten und der Einhaltung einer vollständigen Datenherkunft ein. Verschiedene Versionen des Datensatzes existieren im selben Speicher, getrennt durch Unterverzeichnisse. Jedes Unterverzeichnis fungiert als unabhängiger Datensatz mit seinen Metadatendateien. Im Gegensatz zu einem nicht versionierten Datensatz enthalten diese Unterverzeichnisse nur in der jeweiligen Version geänderte Blöcke sowie einen entsprechenden Blocksatz pro Tensor, der die Namen aller geänderten Blöcke enthält. Eine Versionskontroll-Infodatei im Stammverzeichnis des Verzeichnisses verfolgt die Beziehung zwischen diesen Versionen als verzweigter Versionskontrollbaum. Beim Zugriff auf einen beliebigen Block eines Tensors in einer bestimmten Version wird der Versionskontrollbaum beginnend beim aktuellen Commit in Richtung des ersten Commit durchlaufen. Während des Durchlaufs wird der Blocksatz jeder Version auf das Vorhandensein des erforderlichen Blocks überprüft. Wenn der Block gefunden wird, wird der Durchlauf gestoppt und die Daten werden abgerufen. Um Unterschiede zwischen den Versionen zu verfolgen, wird für jede Version auch eine Commit-Diff-Datei pro Tensor gespeichert. Dies beschleunigt den Vergleich zwischen Versionen und Zweigen. Darüber hinaus werden die IDs der Samples während der Datensatzbefüllung generiert und gespeichert. Dies ist wichtig, um bei Zusammenführungsvorgängen dieselben Samples im Auge zu behalten. Die Versionskontrollschnittstelle von Deep Lake ist die Python-API, die es Machine-Learning-Ingenieuren ermöglicht, ihre Datasets innerhalb ihrer Datenverarbeitungsskripte zu versionieren, ohne zwischen der CLI hin- und herwechseln zu müssen. Sie unterstützt die folgenden Befehle:
• Commit : Erstellt einen unveränderlichen Snapshot des aktuellen Status des Datensatzes.
• Checkout : checkt zu einem vorhandenen Branch/Commit aus oder erstellt einen neuen Branch, falls keiner vorhanden ist.
• Diff : vergleicht die Unterschiede zwischen zwei Versionen des Datensatzes.
• Zusammenführen : führt zwei unterschiedliche Versionen des Datensatzes zusammen und löst Konflikte entsprechend der vom Benutzer definierten Richtlinie.
Die Datenvisualisierung ist ein entscheidender Teil von ML-Workflows, insbesondere wenn die Daten analytisch schwer zu analysieren sind. Eine schnelle und nahtlose Visualisierung ermöglicht eine schnellere Datenerfassung, Annotation, Qualitätsprüfung und Trainingsiterationen. Die Deep Lake Visualizer-Engine bietet eine Weboberfläche zur Visualisierung großer Datenmengen direkt aus der Quelle. Sie berücksichtigt den H-Typ der Tensoren, um das beste Layout für die Visualisierung zu bestimmen. Primäre Tensoren wie Bild, Video und Audio werden zuerst angezeigt, während sekundäre Daten und Annotationen wie Text, class_label, bbox und binary_mask überlagert werden. Der Visualizer berücksichtigt auch die Metatypinformationen wie Sequenz, um eine sequenzielle Ansicht der Daten bereitzustellen, in der Sequenzen abgespielt und zur spezifischen Position der Sequenz gesprungen werden können, ohne die gesamten Daten abzurufen, was für Video- oder Audio-Anwendungsfälle relevant ist. Der Visualizer erfüllt kritische Anforderungen in ML-Workflows und ermöglicht es Benutzern, die Daten zu verstehen und Fehler zu beheben, ihre Entwicklung darzustellen, Vorhersagen mit der Grundwahrheit zu vergleichen oder mehrere Bildsequenzen (z. B. Kamerabilder und Disparitätskarten) nebeneinander anzuzeigen.
Das Abfragen und Ausgleichen von Datensätzen ist ein gängiger Schritt beim Trainieren von Deep-Learning-Workflows. Normalerweise wird dies in einem Dataloader erreicht, der Sampling-Strategien oder separate Vorverarbeitungsschritte verwendet, um eine Teilauswahl des Datensatzes zu treffen. Traditionelle Data Lakes hingegen verbinden sich mit externen analytischen Abfrage-Engines [66] und streamen Dataframes an Data-Science-Workflows. Um die Lücke zwischen dem Format und dem schnellen Zugriff auf die spezifischen Daten zu schließen, bieten wir eine eingebettete SQL-ähnliche Abfrage-Engine, die in C++ implementiert ist und Tensor Query Language (TQL) heißt. Eine Beispielabfrage ist in Abb. 5 dargestellt. Während der SQL-Parser von Hyrise [37] erweitert wurde, um Tensor Query Language zu entwickeln, haben wir unseren Planer und unsere Ausführungs-Engine implementiert, die die Berechnung optional an externe Tensor-Berechnungs-Frameworks delegieren kann. Der Abfrageplan generiert einen Berechnungsgraphen der Tensoroperationen. Anschließend führt der Scheduler den Abfragegraphen aus.
Die Ausführung der Abfrage kann an externe Tensor-Berechnungs-Frameworks wie PyTorch [58] oder XLA [64] delegiert werden und die zugrundeliegende beschleunigte Hardware effizient nutzen. Zusätzlich zu den Standard-SQL-Funktionen implementiert TQL auch numerische Berechnungen. Es gibt zwei Hauptgründe für die Implementierung einer neuen Abfragesprache. Erstens unterstützt traditionelles SQL keine mehrdimensionalen Array-Operationen wie die Berechnung des Mittelwerts der Bildpixel oder die Projektion von Arrays auf eine bestimmte Dimension. TQL löst dieses Problem, indem es Indizierung im Python/NumPy-Stil hinzufügt, Arrays aufteilt und eine große Anzahl praktischer Funktionen für die Arbeit mit Arrays bereitstellt, von denen viele gängige Operationen sind, die in NumPy unterstützt werden. Zweitens ermöglicht TQL eine tiefere Integration der Abfrage mit anderen Funktionen des Deep Lake, wie Versionskontrolle, Streaming-Engine und Visualisierung. Beispielsweise ermöglicht TQL die Abfrage von Daten zu bestimmten Versionen oder möglicherweise über mehrere Versionen eines Datensatzes hinweg. TQL unterstützt auch spezifische Anweisungen zum Anpassen der Visualisierung des Abfrageergebnisses oder die nahtlose Integration mit dem Dataloader für gefiltertes Streaming. Die eingebettete Abfrage-Engine läuft zusammen mit dem Client, entweder während ein Modell auf einer Remote-Compute-Instanz trainiert wird, oder im Browser, kompiliert über WebAssembly. TQL erweitert SQL mit numerischen Berechnungen auf der Grundlage mehrdimensionaler Spalten. Es erstellt Ansichten von Datensätzen, die visualisiert oder direkt an Deep-Learning-Frameworks gestreamt werden können. Abfrageansichten können jedoch spärlich sein, was die Streaming-Leistung beeinträchtigen kann.
Die meisten Rohdaten, die für Deep Learning verwendet werden, werden als Rohdateien (komprimiert in Formaten wie JPEG) gespeichert, entweder lokal oder in der Cloud. Eine gängige Methode zum Erstellen von Datensätzen besteht darin, Zeiger auf diese Rohdateien in einer Datenbank zu speichern, diese abzufragen, um die erforderliche Teilmenge an Daten zu erhalten, die gefilterten Dateien auf eine Maschine zu holen und dann ein Modell zu trainieren, das über die Dateien iteriert. Darüber hinaus muss die Datenherkunft manuell mit einer Herkunftsdatei gepflegt werden. Das Tensor Storage Format vereinfacht diese Schritte durch verknüpfte Tensoren – es speichert Zeiger (Links/URLs zu einem oder mehreren Cloud-Anbietern) zu den Originaldaten. Die Zeiger innerhalb eines einzelnen Tensors können mit mehreren Speicheranbietern verbunden werden, sodass Benutzer eine konsolidierte Ansicht ihrer in mehreren Quellen vorhandenen Daten erhalten. Alle Funktionen von Deep Lake, einschließlich Abfragen, Versionskontrolle und Streaming zu Deep-Learning-Frameworks, können mit verknüpften Tensoren verwendet werden. Die Leistung des Datenstreamings ist jedoch nicht so optimal wie bei Standardtensoren. Ein ähnliches Problem besteht bei spärlichen Ansichten, die aufgrund von Abfragen erstellt werden und aufgrund des Chunk-Layouts ineffizient gestreamt würden. Darüber hinaus wandelt die Materialisierung die Datensatzansicht in ein optimales Layout um, um sie in Deep-Learning-Frameworks zu streamen und so schneller zu iterieren. Bei der Materialisierung werden die tatsächlichen Daten aus Links oder Ansichten abgerufen und effizient in Blöcke aufgeteilt. Die Durchführung dieses Schritts gegen Ende von Machine-Learning-Workflows führt zu minimaler Datenduplizierung und gewährleistet gleichzeitig optimale Streaming-Leistung und minimale Datenduplizierung mit vollständiger Datenherkunft.
Wenn Datensätze größer werden, wird das Speichern und Übertragen über das Netzwerk von einem entfernt verteilten Speicher unvermeidlich. Datenstreaming ermöglicht das Trainieren von Modellen, ohne darauf warten zu müssen, dass alle Daten auf eine lokale Maschine kopiert werden. Der Streaming-Dataloader sorgt für das Abrufen und Dekomprimieren von Daten, das Anwenden von Transformationen, das Sortieren und die Datenübergabe an das Trainingsmodell. Deep-Learning-Dataloader delegieren das Abrufen und Transformieren normalerweise an parallel laufende Prozesse, um synchrone Berechnungen zu vermeiden. Anschließend werden die Daten über Interprozesskommunikation (IPC) an den Haupt-Worker übertragen, was zu einem Speicherkopier-Overhead führt oder gemeinsamen Speicher mit einigen Zuverlässigkeitsproblemen verwendet. Im Gegensatz dazu delegiert der Deep-Lake-Dataloader das hochparallele Abrufen und Dekomprimieren vor Ort in C++ pro Prozess, um eine globale Interpretersperre zu vermeiden. Anschließend übergibt er den In-Memory-Zeiger an die benutzerdefinierte Transformationsfunktion und sortiert ihn, bevor er sie der Trainingsschleife im nativen Deep-Learning-Speicherlayout aussetzt. Die Transformation wird gleichzeitig ausgeführt, wenn sie nur native Bibliotheksroutinenaufrufe verwendet und die globale Interpretersperre (GIL) von Python entsprechend freigibt. Als Ergebnis erhalten wir:
• Leistung : Daten werden schnell genug an das Deep-Learning-Modell übermittelt, sodass entweder die GPU vollständig genutzt wird oder es zu einem Engpass bei der Berechnung kommt.
• Intelligenter Scheduler : Dynamische Unterscheidung zwischen der Priorisierung CPU-intensiver Jobs gegenüber weniger intensiven Jobs.
• Effiziente Ressourcenzuweisung : Vorhersage des Speicherverbrauchs, um zu vermeiden, dass der Trainingsprozess aufgrund einer Speicherüberfüllung unterbrochen wird.
Dieses Dokument ist auf Arxiv unter der CC 4.0-Lizenz verfügbar .
[3] Quellcode verfügbar: https://github.com/activeloopai/airbyte im Zweig @feature/connector/deeplake