November 24, 2021

Die Schönheit von effizienten neuronalen Netzen

Mitwirkende
Mats Uytterhoeven
Machine Learning Engineer
Lucas Desard
Machine Learning Engineer
Newsletter abonnieren
Diesen Beitrag teilen

SotA-Modelle für maschinelles Lernen werden so umfangreich, dass die Hardware nicht mehr mithalten kann. Was sind die Symptome für dieses wachsende Problem und gibt es ein Gegenmittel?
In diesem Blogbeitrag werden wir zunächst die Semantik effizienter Modelle erörtern und erläutern, warum Sie diese verwenden sollten. Anschließend werden wir uns eingehend mit den Techniken befassen, die Sie verwenden können, um kleinere, schnellere und nachhaltigere Modelle für maschinelles Lernen zu erstellen.

Quelle: unsplash.com/alina.grubnyak

Effizienz und Modelle des maschinellen Lernens

Ein Modell für maschinelles Lernen ist effizienter, wenn eine oder mehrere der folgenden Bedingungen erfüllt werden können:

  • den Speicherplatzbedarf reduzieren
  • Verringerung der benötigten Rechenleistung

ohne dass es zu einem signifikanten Leistungsabfall kommt. Die Verringerung des Speicherbedarfs oder der Rechenleistung kann zur Trainingszeit, zur Inferenzzeit oder zu beiden Zeiten erfolgen. Es ist wichtig zu beachten, dass diese Verbesserungen nicht immer Hand in Hand gehen. Es ist beispielsweise möglich, dass ein Modell beim Training mehr Rechenleistung benötigt, dafür aber weniger Speicherplatz beansprucht und zur Inferenzzeit schneller ist.

Warum brauchen wir sie?

Ein erster Grund ergibt sich aus einer Beobachtung des Größenwachstums von SotA-Modellen für maschinelles Lernen. Wenn wir GPT mit DeepSpeed vergleichen, sehen wir eine 10.000-fache Zunahme der Anzahl der Parameter eines Modells in nur 2 Jahren.

Größe der SotA NLP-Modelle im Laufe der Zeit(Grafiken aus dem EMNLP-Tutorial über Hochleistungs-NLP)

So werden die Modelle so schnell größer, dass die Hardware nicht mehr mithalten kann. Das hat eine Reihe von Nachteilen. Zum einen stellt dies eine finanzielle Hürde für die Modelle dar, was sie wiederum für Menschen mit normaler Hardware weniger zugänglich macht. Eine kürzlich durchgeführte Umfrage auf Twitter zeigt, dass selbst die meisten promovierten Forscher nur über einfache Hardware verfügen.

Wenn Sie Ihr Modell trainieren, können Sie außerdem davon ausgehen, dass Ihnen sehr leistungsfähige Grafikprozessoren zur Verfügung stehen. In der Produktion werden Sie jedoch oft durch die Grenzen der Zielhardware eingeschränkt. Dies ist besonders wichtig, wenn das Ziel darin besteht, das Modell für maschinelles Lernen vor Ort oder am Rande des Unternehmens einzusetzen.

Es gibt viele Gründe, Zeit in die Optimierung Ihres Modells zu investieren, um die Effizienz zu steigern. Wenn Ihr Modell beispielsweise zu groß für die Zielhardware ist und nicht in den Speicher passt, können Sie Techniken zur Modellkomprimierung einsetzen, um die Größe Ihrer Gewichtungsdatei zu verringern. Dies ist besonders nützlich für On-Premise- und Edge-Setups, denn wenn Sie Ihr Modell erfolgreich komprimieren können, können Sie weiterhin den neuesten Stand der Technik nutzen, ohne die Hardware aufrüsten zu müssen. Ein weiterer Anwendungsfall besteht darin, die Inferenzzeit Ihres Modells zu beschleunigen. Die meisten effizienten Modelltechniken reduzieren die Anzahl der für eine Vorhersage erforderlichen Berechnungen oder machen sie weniger teuer. Schließlich kann der Energieverbrauch eines Modells erheblich gesenkt werden, was die Kosten für den langfristigen Betrieb von Modellen in der Cloud senken oder die Batterielebensdauer von Edge-Geräten deutlich verbessern kann.

Beschneiden

Pruning ist eine Familie von Methoden, die sich darauf konzentriert, überflüssiges Material zu entfernen und dabei die Leistung nur minimal zu beeinträchtigen.

Pruning ist ein ziemlich altes Konzept und wurde bereits in den 80er Jahren verwendet, um die Größe von Entscheidungsbäumen zu reduzieren. Es mag daher nicht überraschen, dass es viele verschiedene Arten des Pruning gibt, die sich unterscheiden lassen:

  • Die Beschneidungskriterien, d. h. wie entscheiden wir, was beschnitten werden soll?

Die Auswahl kann auf einer einfachen oder komplexen Funktion der Gewichte, der Aktivierungen, der Gradienten oder einer Kombination aus diesen basieren. In den letzten Jahren wurde viel zu diesem Thema geforscht. Eine schöne Zusammenfassung zu diesem Thema, die kürzlich von Uber veröffentlicht wurde, finden Sie hier. Doch verlieren wir uns nicht in den Details. Im Allgemeinen besteht das beliebteste Pruning-Kriterium darin, einfach die kleinsten Gewichte in Bezug auf den absoluten Wert zu entfernen.

  • Was wird gestrichen, z. B. Verbindungen, Kanäle oder ganze Schichten?

Das Pruning von Verbindungen, Kanälen und Schichten bezieht sich auf die kleinste Einheit, die in einem einzigen Schritt auf der Grundlage der Pruning-Kriterien beschnitten werden kann. Die Wahl der Beschneidungsmethode ist ein Kompromiss zwischen Größenreduzierung und Geschwindigkeitssteigerung. Beim Pruning von Verbindungen können Sie mehr Verbindungen entfernen, ohne dass die Genauigkeit signifikant sinkt, da Sie nur die Verbindungen entfernen, die minimal zur Vorhersage beitragen. Bei einem strukturierteren Ansatz wie Channel Pruning oder Layer Pruning müssen Sie jeweils die am wenigsten wichtigen Kanäle oder Schichten auswählen, die zwangsläufig auch einige wichtigere Verbindungen enthalten, so dass Sie weniger Verbindungen entfernen können, bevor die Genauigkeit signifikant sinkt.

Andererseits werden durch das Pruning von Verbindungen nur viele 0's in die Matrixmultiplikationen eingeführt, aber da die Multiplikationen immer noch durchgeführt werden müssen, wirken sie sich kaum auf die Inferenzgeschwindigkeit aus. Mit Channel Pruning können ganze Matrixmultiplikationen übersprungen werden, und mit Layer Pruning sogar ganze Schritte des Vorwärtsdurchlaufs. Daher haben die beiden letztgenannten Methoden einen größeren Einfluss auf die Inferenzzeit.

  • Wann die Beschneidung erfolgt, z. B. vor oder nach dem Training.

Der Standardansatz besteht darin, zunächst ein großes neuronales Netz zu trainieren und dann auf der Grundlage der Ergebnisse des Trainingsprozesses überflüssige Komponenten herauszuschneiden. Der heilige Gral des Pruning besteht jedoch darin, diese kleineren Netzstrukturen vor dem Training zu finden, da dies die Trainingskosten erheblich senken kann. Dies ist besser bekannt als die Lotterielos-Hypothese und ist seit ihrer Einführung im Jahr 2018 ein heißes Forschungsthema. Eine verallgemeinerbare und leicht anwendbare Technik muss jedoch noch entwickelt werden, und daher ist Pruning nach dem Training vorerst noch der Weg der Wahl.

  • Wie oft wir beschneiden.

Hier besteht die Wahl zwischen einmaligem und iterativem Vorgehen. Im Allgemeinen liefert der iterative Ansatz mit einem Feinabstimmungsschritt dazwischen die besten Ergebnisse, wie in der Abbildung unten zu sehen ist. Allerdings gibt es nichts umsonst, da dieser Ansatz auch die meiste Zeit und die meisten Berechnungen in Anspruch nimmt.

Pruning-Ergebnisse aus dieser Arbeit, mit oder ohne Umschulung und einmalig oder iterativ.

Praktische Ratschläge beim Beschneiden

Was also, wenn Sie Pruning selbst ausprobieren wollen? Nun, das hängt davon ab, ob Sie TensorFlow oder PyTorch verwenden.
Im Moment unterstützt TensorFlow nur eine Art von Pruning, das Pruning von Verbindungen. Es gibt die Option, nur einige Arten von Schichten zu beschneiden, zum Beispiel nur die dichten Schichten. Die Bereitstellung anderer Pruning-Methoden ist auf ihrer Roadmap, aber im Moment gibt es keine Pruning-Methoden, die Ihnen helfen, Ihr Modell zu beschleunigen.
PyTorch jedoch unterstützt sowohl strukturierte als auch unstrukturierte Pruning-Methoden und bietet eine leicht erweiterbare Pruning-Klasse, die Ihnen die Möglichkeit gibt, Ihre eigenen Pruning-Methoden zu implementieren, wenn Sie das jemals wollen. Zusätzlich zu den Standard-Beschneidungsmethoden, die mit PyTorch geliefert werden, gibt es mehrere Open-Source-Beschneidungs-Toolkits, die noch mehr Optionen bieten. In Bezug auf die Beschneidung ist PyTorch also das Maß aller Dinge.

Quantisierung

Eine zweite bekannte und sehr leistungsfähige Technik ist die Quantisierung. Die Grundidee ist überraschend einfach: Es handelt sich um eine Verringerung der Genauigkeit der Zahlen, die zur Darstellung der Gewichte eines Modells verwendet werden. Angenommen, wir haben ein Modell, bei dem die Gewichte als 32-Bit-Fließkommazahlen gespeichert sind. Wenn wir sie in 8-Bit-Ganzzahlen umwandeln, können wir die Größe bereits um das Vierfache verringern und die Geschwindigkeit um mindestens 50 % steigern. Das ist ziemlich überraschend, wenn man bedenkt, dass man mit 32 Bit 2²⁴ mehr Zahlen darstellen kann als mit 8 Bit. Aber anscheinend ist das für ML-Modelle nicht so wichtig, da wir in den meisten Fällen eine ähnliche Leistung erzielen können.

Man kann zwischen gleichmäßiger und
ungleichmäßiger
Quantisierung unterscheiden. Gleichförmig bedeutet, dass die Quantisierungsebenen gleichmäßig verteilt sind, ungleichförmig, wenn sie ungleich verteilt sind.
Die gleichförmige Quantisierung ist die einfachere von beiden, da man nur einen Freiheitsgrad hat, nämlich die Frage, wie viele Bits man zur Darstellung der Gewichte nach der Quantisierung verwenden will.
Bei der uneinheitlichen Quantisierung hingegen hat man einen zusätzlichen Freiheitsgrad, nämlich die Frage, wie man die Quantisierungsstufen aufteilt.
Ein interessanter Ansatz, der sich in der Forschung bewährt hat, ist die Suche nach k-nahen Nachbarn und die entsprechende Aufteilung der Quantisierungsstufen. Dies hat den Vorteil, dass viele Verbindungen das gleiche Gewicht haben, was eine starke Komprimierung des ursprünglichen Netzes ermöglicht. Aufgrund einiger Optimierungsprobleme ist jedoch noch weitere Forschung erforderlich, damit dieser Ansatz in der Praxis angewendet werden kann.

Ein weiterer cleverer Trick, den wir anwenden können, ist das quantisierungsbewusste Training, das während des Trainings in den Vorwärtspassagen eine Quantisierung während der Inferenzzeit simuliert. Dies führt zu einem gewissen Quantisierungsfehler, der im Gesamtverlust des Modells akkumuliert wird, und es wird versucht, ihn durch entsprechende Anpassung der Parameter zu reduzieren. Dies macht unser Modell später robuster gegenüber Quantisierung.
Sowohl TensorFlow als auch PyTorch unterstützen Quantisierung und quantisierungsbewusstes Training.

Wissensdestillation

Eine der zentralen Überlegungen hinter Wissensdestillation ist, dass es einen Unterschied zwischen den Anforderungen während des Trainings und der Inferenzzeit gibt. In vielen Fällen besteht das Ziel der Trainingszeit darin, aus großen Datenmengen zu lernen und Strukturen zu extrahieren. Hier können große Modelle, die "Lehrer", mit viel Kapazität glänzen. Zur Schlussfolgerungszeit sind diese großen Modelle jedoch schwerfällig zu handhaben (aufgrund der typischerweise strengeren Latenz- und Speicheranforderungen), und kleinere Modelle, die "Schüler", wären viel besser geeignet.

Bei der Wissensdestillation geht es darum, das Beste aus beiden Welten zu kombinieren. Im ersten Schritt wird ein großes Modell mit einer großen Datenmenge trainiert. In einem zweiten Schritt wird das von den großen Modellen erfasste Wissen in ein viel kleineres Modell "destilliert". Aber was verstehen wir unter Wissen? Und wie können wir dieses Wissen in ein kleineres Modell "destillieren"?

Wenn wir im Zusammenhang mit der Wissensdestillation von Wissen sprechen, geht es um die erlernte Beziehung zwischen Eingabe- und Ausgabevektoren. Diese Beziehung kann viel über die Art und Weise aussagen, wie ein Modell auf ungesehene Daten verallgemeinert (einer der Gründe, warum große Modelle in der Regel besser abschneiden als kleinere, ist, dass sie besser verallgemeinern können).
Nehmen wir zum Beispiel die Klassifizierung. Obwohl die Ausgabewahrscheinlichkeit für die Zielklasse bei weitem am höchsten ist, enthalten die Ausgabewahrscheinlichkeiten für die anderen Klassen immer noch eine Menge Informationen. Genau diese relativen Unterschiede zwischen den kleinen Wahrscheinlichkeiten der falschen Klassen können eine Menge Informationen darüber liefern, wie das Modell verallgemeinert.

Schließlich sollte das vom Lehrer erlernte Wissen irgendwie auf den Schüler übertragen werden. Dies geschieht durch Hinzufügen eines zusätzlichen Verlustterms zur üblichen Verlustfunktion, dem Destillationsverlust. Nehmen wir noch einmal das Beispiel der Klassifizierung, so sind wir nicht nur an der harten Kennzeichnung interessiert (d. h. dem kodierten Ein-Hot-Vektor, der die Klasse repräsentiert), sondern auch an der weichen Kennzeichnung, die vom Lehrer erzeugt wird (um die kleinen Unterschiede zwischen den Wahrscheinlichkeiten falscher Klassen zu vergrößern, wird der letzten Softmax-Schicht ein Temperaturparameter hinzugefügt, wobei die Ausgabeverteilung umso glatter ist, je höher die Temperatur ist.

Bei der Wissensdestillation wird ein zusätzlicher Destillationsverlustterm in der Verlustfunktion verwendet (bei der Destillation kamen keine Hunde zu Schaden).

Clevere Optimierungstricks

Die bisherigen Ansätze haben alle gemeinsam, dass sie das Netz in irgendeiner Weise verändern (einige Teile entfernen, die Genauigkeit der Gewichte verringern oder sogar ein kleineres Netz trainieren). Die beiden im Folgenden beschriebenen Techniken verändern das Netz selbst nicht wirklich, aber sie machen das Optimierungsverfahren effizienter in Bezug auf die Menge an Speicher, die zur Trainingszeit benötigt wird.

Gradient Checkpointing

Beim Gradient Checkpointing wird im Grunde genommen der benötigte Speicherplatz auf Kosten eines höheren Rechenaufwands reduziert. Dieser Kompromiss ist besonders nützlich, da es in der Regel viel einfacher ist, etwas länger zu warten, bis das Modell trainiert ist, als etwas mehr VRAM zu bekommen.
Die Funktionsweise des Gradient Checkpointing besteht darin, dass nicht alle Aktivierungen die ganze Zeit im Speicher gehalten werden, sondern nur Kontrollpunkte dazwischen. Wann immer bestimmte Aktivierungen wieder benötigt werden (z. B. bei der Berechnung von Gradienten im Rückwärtsdurchlauf), werden sie einfach vom nächstgelegenen Kontrollpunkt aus neu berechnet.

Ohne Gradient Checkpointing werden alle Aktivierungen im Speicher gehalten (Visualisierung aus diesem Blogpost).
Beim Gradient Checkpointing werden Aktivierungen nur an bestimmten Kontrollpunkten gespeichert und bei Bedarf neu berechnet (Visualisierung aus diesem Blogpost).

Akkumulation von Gradienten

Wenn Sie jemals versucht haben, ein relativ großes transformatorbasiertes Modell (z. B. BERT, T5, ...) auf einem bescheidenen Grafikprozessor fein abzustimmen, sind Sie zweifelsohne auf eine ganze Reihe von "Out-of-Memory"-Ausnahmen gestoßen. Das Problem ist, dass Sie in vielen Fällen eine Feinabstimmung dieser Modelle mit größeren Stapelgrößen vornehmen wollen, als in den Speicher passen. Hier kommt die Gradientenakkumulation ins Spiel. Wie der Name schon sagt, können Sie damit Gradienten für eine Reihe von Trainingsschritten akkumulieren, bevor Sie Gewichtungen aktualisieren. Auf diese Weise können Sie größere Losgrößen simulieren, ohne dass der Speicherbedarf dafür ausreicht.

Steigungen werden akkumuliert und Gewichtungsaktualisierungen werden erst nach einer Reihe von Trainingsschritten durchgeführt, wodurch größere Losgrößen bei geringerem Speicherbedarf simuliert werden.

Über allgemeine Techniken hinaus

Alle in den vorangegangenen Abschnitten erörterten Techniken sind (zumindest theoretisch) allgemein auf jede Architektur neuronaler Netze anwendbar, doch lassen sich zusätzliche Effizienzgewinne erzielen, wenn man sich auf bestimmte Architekturen konzentriert.
Ein sehr relevantes Beispiel ist die Transformer-Architektur, die seit einigen Jahren den Stand der Technik in vielen Bereichen (insbesondere NLP) dominiert und die Grenzen der Modellgröße immer weiter ausreizt.

Das ist alles schön und gut, wenn man für Google oder OpenAI arbeitet, aber für viele Menschen sind die Hardwareanforderungen sehr mühsam. Es sollte Sie daher nicht überraschen, dass sich viele Forschungsarbeiten darauf konzentriert haben, die Transformer-Architektur (und insbesondere den Mechanismus der Selbstaufmerksamkeit) effizienter zu machen. Ein ausführlicher Überblick über diese Techniken würde den Rahmen dieses Blogposts sprengen, aber der Vortrag über hochleistungsfähige natürliche Sprachverarbeitung auf der EMNLP 2020 ist eine hervorragende Quelle, um in dieses Thema einzutauchen.

Verwandte Beiträge

Alle anzeigen
Keine Ergebnisse gefunden.
Es gibt keine Ergebnisse mit diesen Kriterien. Versuchen Sie, Ihre Suche zu ändern.
Stiftung Modelle
Unternehmen
Unser Team
Verantwortungsvolle und ethische KI
Strukturierte Daten
Chat GPT
Nachhaltigkeit
Stimme und Ton
Front-End-Entwicklung
Schutz und Sicherheit von Daten
Verantwortungsvolle/ethische KI
Infrastruktur
Hardware und Sensoren
MLOps
Generative KI
Verarbeitung natürlicher Sprache
Computer Vision