Modern application of Voice AI technology

Image of Voice AI header

With the advancement of technology and the gradually increasing use of artificial intelligence, new markets are developed. One of such is the market of Voice AI which became a commercial success with voice bots such as Alexa or Siri. They were mainly used as digital assistants who could answer questions, set reminders and they could generally tap into various databases to provide the aid and service that they were ask to provide. Although the popular use case seems to be primarily domestic, we have long since experienced other applications for Voice AI in areas such as UI speech control, voice recognition and replication and in use within entertainment media.

Faced with the ever-present but ever-growing interest in artificial intelligence which continue to further their influence on society, industry and the commercial landscape, my post will strive to demonstrate and inspect the technologies surrounding the application of Voice AI but also the concurrent obstacles it needs to overcome. However, before we can dive deeper into the topic, it is important to introduce the concept of Voice AI and its general technological workings.

Continue reading

Die wachsende Macht von Sprachmodellen am Beispiel ChatGPT und Bewertung deren Skalierbarkeit

Blog von Manuel Heim (mh375) und Silas Blumenstock (sb309).

Einleitung

In den letzten Jahren hat sich die Welt der künstlichen Intelligenz (KI) rasend schnell entwickelt. Eine der spannendsten Entwicklungen in diesem Bereich ist die Einführung von Sprachmodellen, die menschenähnliche Gespräche führen können. Eines der bekanntesten und leistungsfähigsten Sprachmodelle ist ChatGPT. ChatGPT basiert auf dem Modell GPT-3, das von der Firma OpenAI entwickelt wurde. Microsoft hat mehrere Milliarden in OpenAI investiert, um Zugang zu diesem und anderen KI-Modellen zu erhalten. In nur zwei Monaten seit seiner Veröffentlichung hat ChatGPT bereits 100 Millionen Benutzer erreicht, von denen die meisten regelmäßige Nutzer sind. Täglich nutzen etwa 13 Millionen Menschen ChatGPT. Diese Zahlen zeigen, wie schnell ChatGPT an Bedeutung gewinnt und wie nützlich es für die Entwicklung von KI-basierten Anwendungen sein kann.

Die Qualität der von ChatGPT generierten Texte ist besonders beeindruckend. Sie sind häufig kaum noch von menschengeschriebenen Texten zu unterscheiden. Der vorherige Abschnitt wurde zum Beispiel vollständig von ChatGPT geschrieben, was Ihnen vermutlich nicht aufgefallen ist. Neben dem Generieren von Texten kann ChatGPT auch für viele weitere Aufgaben genutzt werden. Zum Beispiel für die Beantwortung von Fragen, oder auch für das Schreiben und die Fehlersuche in Code. Es kann auch Bezug auf bereits generierte Texte genommen werden und ChatGPT kann diese umschreiben, übersetzen oder im Stil verändern. Bittet man ChatGPT z.B. darum, den oberen Abschnitt auf Englisch zu übersetzen und als Gedicht umzuformulieren, erhält man die folgende Ausgabe:

In the world of AI, advances are rife
Language models can now talk like human life
ChatGPT is one that's made a great leap
Built on GPT-3, OpenAI's star keep
Microsoft invested billions in the AI game
To access the power of models that became
ChatGPT, in particular, has made waves
In the workplace, where it helps to save
With conversations like a human touch
ChatGPT finds uses in tasks that clutch
Repetitive work, like customer support
It automates and saves time, that's its forte forte
So whether it's sales, marketing, or journalism too
ChatGPT can do it all, with responses anew
The future's bright, and there's more to come
From AI advancements, where possibilities hum.

ChatGPT kann als Meilenstein in der Entwicklung von Sprachmodellen und im Bereich Machine Learning generell gesehen werden, auch wenn die Texte, wie im Gedicht zu erkennen, noch nicht ganz fehlerfrei sind.

In den folgenden Kapiteln erklären wir die technischen Grundlagen, die zum Verständnis der Funktionsweise von ChatGPT nötig sind. Es wird das Konzept der Self-Attention erklärt, welches eine der relevantesten Entwicklung im Bereich von Sprachmodellen ist. Wir gehen auf das Fine-Tuning beim Training von ChatGPT ein. Zusätzlich wird ein Überblick über verschiedene GPT-Modelle gegeben. Da bei Sprachmodellen ein Trend zu immer größeren Modellen existiert, möchten wir auch auf die Skalierung großer Sprachmodelle eingehen und diesen Trend bewerten.

Grundlagen

Sprachmodelle

Das von ChatGPT genutzte Modell GPT-3 ist ein Sprachmodell. Sprachmodelle können für verschiedene Anwendungen eingesetzt werden, z.B. zur automatischen Vervollständigung von Sucheingaben oder zur Textgenerierung. Grundsätzlich werden unter Sprachmodellen Modelle verstanden, die mithilfe verschiedener probabilistischer Techniken Wahrscheinlichkeiten von Wortsequenzen in Sätzen bestimmen, indem sie Textdaten analysieren. Dabei lernt ein Modell Merkmale und Eigenschaften der Sprache und nutzt diese, um neue Sätze zu verstehen oder zu produzieren. Je nach Komplexität der Aufgabe werden unterschiedliche Modelltypen verwendet. GPT-3 ist zum Beispiel ein neuronales Sprachmodell. Diese repräsentieren Wörter als Vektoren auf Grundlage von Gewichten in neuronalen Netzen, diese Vektoren werden als Word-Embeddings bezeichnet. Word-Embeddings werden vor allem bei komplexen Modellen mit großen Datenmengen eingesetzt, hier existieren einzelne Wörter, die selten in Texten vorkommen. Bei einfachen probabilistischen Modelltypen kann es dabei zu Problemen kommen [1]. Da der Blog-Beitrag ChatGPT behandelt, beschäftigen wir uns nur mit neuronalen Sprachmodellen. Ein Überblick weiterer Modelltypen wird in [1] gegeben.

Wie bereits erwähnt, wird ChatGPT zur Textgenerierung eingesetzt. Dabei wird aus einer Sequenz von Word-Embeddings als Eingabe eine Wahrscheinlichkeitsverteilung über Ausgabewörter eines Textkorpus bestimmt. In Texten bestehen dabei zwischen den Word-Embeddings der Eingabesequenz Abhängigkeiten, weshalb Architekturen genutzt werden, die diese Abhängigkeiten berücksichtigen. In den ersten neuronalen Sprachmodellen wurden dafür z.B. rekurrente neuronale Netze (RNNs) verwendet. RNNs sind neuronale Netze, bei denen die Ausgabe eines Neurons im nächsten Zeitschritt Teil der Eingabe in dasselbe Neuron ist. Bei der Textverarbeitung bedeutet dies, dass zusätzlich alle vorherigen Wörter in die Berechnung der Ausgabe mit einfließen und das ein Wort pro Zeitschritt prozessiert wird. RNNs in Sprachmodellen besitzen jedoch zwei entscheidende Nachteile. Zum einen haben sie Schwierigkeiten, Informationen über Wörter, die am Anfang eines langen Textes stehen, in die Verarbeitung von Wörtern am Ende des Textes einzubeziehen. Zum anderen können RNNs nur sequenziell trainiert werden, weshalb kein effizienteres Training durch die Nutzung mehrerer GPUs ermöglicht werden kann.

Durch die Vorstellung einer weiteren Modellarchitektur in dem Paper „Attention is all you need“, wurde eine neue Architektur zur Berücksichtigung von Abhängigkeiten zwischen Eingaben eingeführt. Der als Transformer bezeichnete Modelltyp verwendet dabei sogenannte Self-Attention und gilt als Meilenstein im Bereich Natural Language Processing [2].

Self-Attention

Self-Attention bezeichnet eine Methode, mit der der Einfluss anderer Wörter auf das aktuell zu verarbeitende Wort berücksichtigt wird. Für den folgenden Beispielsatz:

The animal didn't cross the street because it was too tired.

Wird durch Self-Attention zum Beispiel der Einfluss der Wörter animal und street auf das Wort it gelernt, Self-Attention sollte dabei dafür sorgen, dass der Einfluss von animal größer ist als von street. Für einen Menschen scheint dies ein triviales Problem zu sein, während es für einen Algorithmus ein deutlich komplizierteres Problem ist. Bei Self-Attention werden für jedes Wort Attention-Koeffizienten zu allen anderen Eingabewörtern berechnet. Diese definieren die Beziehungsstärken zwischen den Word-Embeddings der Eingabewörter. In einem ersten Schritt werden mithilfe des Word-Embeddings eines Eingabewortes Query, Key und Value Matrizen berechnet. Dies erfolgt durch die Gewichtsmatrizen Wq, Wk und Wv. Die Parameter dieser Gewichtsmatrizen sind veränderbar und werden während des Trainingsprozesses gelernt.

Query, Key und Value haben dabei die folgenden Funktionen:

  • Query: Die Query qi der i-ten Eingabe wird verwendet, um den Einfluss aller Eingaben auf die Eingabe an Stelle i zu berechnen.
  • Key: Der Key kj wird von Queries qi genutzt, um den Einfluss des Elements an der Stelle j für das Element an der Stelle i zu bestimmen.
  • Value: Der Value vj wird für die Berechnung des Gesamtergebnisses zusammen mit dem Attention-Koeffizienten aij verwendet.

Es wird auch die Query auf einen Key der gleichen Eingabe angewandt, um für eine Eingabe den eigenen Einfluss zu bestimmen. Durch Betrachtung des oberen Beispiels wird deutlich, warum dies relevant ist. Bei Verarbeitung des Wortes it ist zum Beispiel der Einfluss von animal größer als das Wort it selbst.

Nach der Berechnung von Query, Key und Value werden die Attention-Koeffizienten aij durch das Skalarprodukt von Query qi und Key kj gebildet. Diese werden normalisiert, anschließend wird die Softmax-Aktivierungsfunktion darauf angewandt. Die Ausgabe yi bei Eingabe xi unter Berücksichtigung der restlichen Eingaben in der Sequenz kann dann durch die Linearkombination der Attention-Koeffizienten mit den jeweiligen Value-Werten berechnet werden [3].

In Abbildung 1 ist die Berechnung für die erste Eingabe abgebildet, dabei werden die Einflüsse aller weiterer Eingaben auf das erste Eingabeelement berücksichtigt.

Abbildung 1: Self-Attention in einem Single-Head eines Transformers [8]

In der obigen Abbildung wird eine sogenannte Single-Head Attention abgebildet. Das heißt, für jedes Paar von Eingaben wird ein einzelner Attention-Koeffizient berechnet. In Modellen wie GPT wird Multi-Head Attention verwendet. Das heißt, für Paare von Eingaben werden mehrere Attention-Koeffizienten in sogenannten Heads berechnet. In jedem Head werden dabei unterschiedliche Gewichtsmatrizen zur Berechnung von Query, Key und Value verwendet, wobei die Startgewichte zufällig initialisiert werden. Alle Ergebnisse der verschiedenen Heads werden verkettet und durch eine erneute lernbare Gewichtsmatrix auf ein Ergebnis projiziert. Die Verwendung von Multi-Head Attention bringt den Vorteil, dass für ein Paar von Eingaben unterschiedliche Gewichtsmatrizen für Query, Key und Value gelernt werden und somit mehrere Attention-Koeffizienten für gleiche Paare von Eingabewörtern gelernt werden können. Dies ist relevant, weil Wortpaare je nach Gesamtkontext eines Textes unterschiedliche Bedeutungen und damit unterschiedliche Beziehungsstärken haben können [3, 4].

Transformer

GPT steht für Generative Pretrained Transformer. Das heißt GPT beruht auf einem Transfomer in dem das Konzept Self-Attention umgesetzt wird. Ein Transformer besteht aus zwei Teilen, einem Encoder und Decoder-Teil. Diese beinhalten, wie in Abbildung 2 zu erkennen, mehrere Encoder- bzw. Decoder-Blöcke, welche neben Self-Attention Schichten auch Schichten zur Normalisierung und reguläre Feed-Forward Neural Networks enthalten. Die Eingabe in den Encoder-Teil eines Transformers sind Sequenzen von Word-Embeddings. In der Eingabe ist zusätzlich eine Information über die Position des Word-Embeddings in der Sequenz enthalten. Diese wird durch den Positional-Encoding Vektor repräsentiert, der auf die Eingabe addiert wird. Positional-Encoding Vektoren sind dabei so aufgebaut, dass weiter entfernte Eingaben eine höhere euklidische Distanz besitzen als benachbarte Eingaben. In den Decoder-Teil wird die Ausgabe des Decoders zum vorherigen Zeitpunkt als Eingabe gegeben. Encoder und Decoder sind über einen Encoder-Decoder Attention-Block verbunden. Die Eingabe in diesen Block sind die Keys und Values des letzten Encoder-Blocks sowie die Queries des vorangeschalteten Decoder-Layers [3].

Abbildung 2: Darstellung eines Transformers. Es wird ein Zeitpunkt während der Verarbeitung einer Eingabe zur Übersetzung abgebildet. (Angepasste Darstellung aus [3])

Durch die Umsetzung der Transformer, wie sie in „Attention is all you need“ vorgestellt wurden, konnten bessere Ergebnisse wie durch andere Modelle bei gängigen NLP-Aufgaben erzielt werden, wobei der Trainingsaufwand signifikant geringer war [4]. In vielen Sprachmodellen werden heutzutage Transformer verwendet, wobei diese zum Teil angepasst werden.

Generative Pre-Trained Transformer (GPT)

In den vorherigen Abschnitten sind wir bereits darauf eingegangen, was ein Sprachmodell ist und wie Transformer funktionieren und aufgebaut sind. Doch wie stehen diese im Zusammenhang mit Generativen Pre-Trained Transformern (GPTs)?

Die ersten GPT-Modelle wurden erstmals im Jahr 2018 von OpenAI als GPT-1 eingeführt [5]. Die Architektur der GPT-Modelle basiert dabei, wie bereits erwähnt, auf der der Transformer. Ein GPT nutzt dabei nur die Decoder-Struktur des Transformers, da nur dieser Teil relevant für die Erzeugung von Text ist. Alle GPT-Varianten stellen dabei sogenannte autoregressive Sprachmodelle dar. Diese sagen für eine Sequenz von Wörtern das nachfolgende Wort vorher. Für diese neue Sequenz wird dann wieder das Wort vorhergesagt, das am wahrscheinlichsten auf diese Sequenz folgt. Durch diese Funktionsweise sind GPT-Modelle für die Generierung von Texten oder jeder Art von Sequence-To-Sequence Transformationen wie Übersetzung, Text-to-Code, etc. geeignet. Sie werden deshalb auch generative Modelle genannt, da sie neuen Text generieren können. GPT-1 wird dabei, wie der Name es verrät, auf einer großen Menge an Daten vortrainiert und dann für jede spezifische Task, die das Modell erfüllen soll, Fine-Tuned (Gezielt abgestimmt). Daher haben Generative Pre-Trained Transformer ihren Namen.

GPT-1 (2018)GPT-2 (2019)GPT-3 (2020)
Autoregressives SprachmodellAutoregressives SprachmodellAutoregressives Sprachmodell
Decoder-OnlyDecoder-OnlyDecoder-Only
12 Layer48 Layer96 Layer
117 Millionen Parameter1.5 Milliarden Parameter175 Milliarden Parameter
Unsupervised Pre-Training + Task-Specific Supervised Fine-TuningTask-Conditioned Training (Unsupervised)Task-Conditioned Training (Unsupervised)
5GB Unsupervised Data40GB Unsupervised Data600GB Unsupervised Data
Tabelle 1: Übersicht der GPT-Modelle

Das Pre-Training erfolgt dabei unüberwacht (unsupervised) und kann auf einer sehr großen Menge an Daten erfolgen, da für unüberwachtes Lernen keine gewünschten Ausgabedaten vorhanden sind. Bei GPT-1 hat sich gezeigt, dass ein umfangreiches Pre-Training auf einem großen Textkorpus die Leistung dieser Modelle in unterschiedlichen Aufgaben verbessert, selbst wenn der Korpus nicht speziell auf die Aufgaben zugeschnitten war. Diese Erkenntnis hat gezeigt, dass ein großer vielfältiger Textkorpus sehr wertvolle Informationen für die Modelle liefert. Für das überwachte Fine-Tuning, bei dem nun eine gewünschte Ausgabe vorhanden ist, benötigt man deshalb nur einen kleinen Datensatz, um das Modell speziell auf eine Aufgabe abzustimmen.  In manchen Bereichen ist jedoch selbst die Beschaffung dieses kleinen Datensatzes nicht sonderlich einfach [5].

Diese Modelle wurde im Jahr 2019 mit GPT-2 [6] und 2020 mit GPT-3 [7] weiter verbessert. Ab GPT-2 wurde dabei das Prinzip des Multi-Task Learning (MTL) angewendet. In GPT-1 musste dabei für jede spezifische NLP-Aufgabe ein eigenes Modell trainiert werden. Im Multi-Task Learning dagegen wird nur ein einziges Sprachmodell für mehrere NLP-Aufgaben trainiert, indem die Trainingsdaten mit Task-spezifischen Beispielen oder Prompts erweitert werden. Da das Modell nicht für eine spezielle Aufgabe trainiert wurde, handelt es sich um ein Beispiel für Few-Shot-, One-Shot- oder Zero-Shot-Learning. Das Konzept der X-Shot-Ansätze ist in der folgenden Abbildung dargestellt.

Abbildung 3: X-Shot Learners [7]

Das Multi-Task Learning wird bei den X-Shot-Ansätzen dabei auf Datenebene integriert, indem, wie in der Abbildung dargestellt, der Eingabe („Cheese“) die Task-Beschreibung („Translate English to French“) hinzugefügt wurde. Beim Few-Shot-Learning werden dem Modell so einige Beispiele beigefügt, die genau die Aufgabe beschreiben. Um Multi-Task Learning / X-Shot-Learning anwenden zu können, muss das Modell natürlich immer noch mit einer sehr großen Menge an Daten vortrainiert werden. Dieser Ansatz hat gezeigt, dass immer größere Sprachmodelle, wie GPT-3, mit immer mehr Parametern eine sehr starke Leistung auf unterschiedlichen NLP-Aufgaben bieten. Die Tatsache, dass wir nun kein Fine-Tuning mehr benötigen, ist ein Schritt in Richtung der „allgemeinen Intelligenz“ [7, 8].

Die obige Tabelle zeigt deutlich, dass die GPT-Modelle im Laufe der Jahre immer größer geworden sind und GPT-3 im Vergleich zu GPT-2 auf deutlich mehr Daten vortrainiert wurde. Es war damals das größte öffentlich verfügbare Sprachmodell der Welt und die Qualität der generierten Texte so hoch, dass es für Menschen schwierig war, festzustellen, ob Texte von GPT-3 oder einem Menschen geschrieben wurden [9]. Obwohl GPT-3 große Fortschritte im Bereich der Verarbeitung natürlicher Sprache erzielt hatte, ist es nur begrenzt in der Lage, sich an den Absichten der Benutzer zu orientieren. So erzeugte GPT-3 Ausgaben die:

  • mangelnde Hilfsbereitschaft enthalten, d.h. sie befolgen nicht die ausdrücklichen Anweisungen des Nutzers.
  • Halluzinationen enthalten, die nichtexistierende oder falsche Fakten widerspiegeln.
  • nicht interpretierbar sind, sodass es für den Menschen schwierig ist, zu verstehen, wie das Modell zu einer bestimmten Entscheidung oder Vorhersage gekommen ist.
  • toxische oder voreingenommene Inhalte enthalten, die schädlich oder beleidigend sind und Fehlinformationen verbreiten [7, 10].

Um diesen Problemen von GPT-3 entgegenzuwirken, entwickelte OpenAI InstructGPT, welches im Januar 2022 veröffentlicht wurde. Dazu wurde GPT-3 als Basismodell mit den gleichen Pre-Training Datensätzen verwendet und das Modell durch einen neuartigen Ansatz zur Einbeziehung von menschlichem Feedback in den Trainingsprozess weiter verbessert. InstructGPT ist durch diesen Ansatz besser an die Absichten der Benutzer angepasst („aligned“) [11].

ChatGPT

Abbildung 4: Übersicht ChatGPT [12]

ChatGPT ist ein großes Sprachmodell, das darauf trainiert wurde, natürliche Sprache zu verstehen und auf verschiedene Arten von Fragen und Anfragen zu antworten. Es wurde am 30. November 2022 von OpenAI ins Leben gerufen. Der Dienst, mit einem ansprechenden Design und einfacher Benutzeroberfläche, ist bisher kostenlos für die Öffentlichkeit verfügbar. Im Januar 2023 erreichte ChatGPT über 100 Millionen Nutzer und war damit die am schnellsten wachsende Verbraucheranwendung überhaupt [12, 13].

ChatGPT stellt ein Geschwister-Modell von InstructGPT dar, welches darauf trainiert ist, einer Instruktion in einem Prompt zu folgen und eine detaillierte Antwort zu geben. Es wurde dabei auf einem Modell der GPT-3.5 Reihe trainiert, zu der InstructGPT zählt. Dabei wurde derselbe Ansatz wie bei InstructGPT gewählt, jedoch mit leichten Unterschieden in der Datenerhebung [14].

Zusätzlich dazu wurde eine Sicherheitsschicht hinzugefügt, um unangemessene und beleidigende Inhalte zu erkennen und herauszufiltern. Wenn ChatGPT eine unangemessene oder beleidigende Eingabe erhält, versucht es, das Thema zu wechseln oder den Benutzer höflich zu bitten, die Konversation fortzusetzen. Diese Sicherheitsmaßnahmen sind auf jeden Fall notwendig, da Sprachmodelle oft dazu neigen, auch unangemessene Antworten zu liefern.

Reinforcement Learning From Human Feedback

Der Ansatz, der bei InstructGPT dabei zum Einsatz kommt, heißt „Reinforcement Learning From Human Feedback“. Diese Technik nutzt die menschlichen Präferenzen als ein Reward-Signal, um das Modell damit zu verbessern. Dieser Ansatz wird im Folgenden mit dem InstructGPT Paper erklärt und besteht aus folgenden drei Schritten:

Abbildung 5: Reinforcement Learning From Human Feedback ChatGPT [14]

1. Supervised Fine-Tuning (SFT) Modell

Im ersten Schritt wird das GPT-3 Modell mithilfe von überwachten Lernen Fine-Tuned. Dazu wurden 40 Personen (Labeler) beauftragt, diesen Trainingsdatensatz zu erstellen, indem für jede Eingabe-Prompt eine Antwort erstellt wird. Die Eingabe-Prompts stammen dabei zum größten Teil aus tatsächlichen Benutzereingaben, die in der OpenAI API gesammelt wurden, aber auch zum Teil aus Eingaben, die die Labeler selbst erstellten, um Kategorien auszufüllen, in denen nur wenige tatsächliche Benutzereingaben vorhanden waren. Die Labeler schrieben dann für diese Eingabe-Prompts eine Antwort und erzeugten so eine Ausgabe für die zugehörige Eingabe. Diese Zusammenstellung der Eingabe-Prompts aus der OpenAI API und den selbsterstellten Prompts ergaben 13.000 Datensätze mit Eingabe und zugehöriger Ausgabe, die für das überwachte Fine-Tuning des Modells verwendet werden konnten [10, 11, 15].

In diesem Schritt wird eine sogenannte überwachte Policy (das SFT-Modell selbst) gelernt. Eine Policy stellt im Reinforcement Learning eine Strategie dar, die ein Agent verfolgt, um Ziele zu erreichen. Die Strategie sagt die Aktionen voraus, die der Agent in Abhängigkeit vom Zustand des Agenten und der Umgebung durchführt [16].

2. Reward Modell (RM)

Das resultierende SFT-Modell zeigte schon eine Verbesserung in Bezug auf die Benutzerabsichten, war jedoch noch nicht gut genug. Das Problem des überwachten Ansatzes aus dem vorherigen Schritt ist außerdem der langsame und kostspielige Prozess für die Erstellung des Datensatzes.

Deshalb wird in diesem Schritt ein sogenanntes Reward Modell trainiert. Dazu werden die Labeler gebeten, die Ausgaben des SFT-Modells (Antworten auf Prompts) zu bewerten. Diese Bewertung drückt aus, wie wünschenswert diese Ausgabe für den Menschen ist. Am Ende dieses Schrittes besitzt man dann ein Reward Modell, das die menschlichen Vorlieben nachahmen soll. Das funktioniert dabei folgendermaßen:

  • Eine Eingabe-Prompt wird ausgewählt und das SFT-Modell generiert mehrere Ausgaben (4-9) für diese Eingabe-Prompt.
  • Die Labeler sortieren die Ausgaben von der besten bis hin zur schlechtesten.
  • Das Ergebnis ist ein neuer Datensatz, bei dem das Ranking das Label darstellt. Dieser Datensatz wird verwendet, um das Reward Modell zu trainieren. Das Reward Modell nimmt dabei als Eingabe mehrere Ausgaben des SFT-Modells und ordnet diese nach der Reihenfolge der Präferenzen.

Da es für die Labeler viel einfacher ist, die Ergebnisse zu bewerten, als sie von Grund auf neu zu erstellen, lässt sich dieser Prozess viel effizienter skalieren [10, 11, 15].

3. Reinforcement Learning Modell

Im letzten Schritt wird das Reward Modell als Reward-Funktion verwendet und das SFT-Modell so Fine-Tuned, um diesen Reward zu maximieren. Dazu wird dem Modell eine zufällige Eingabe-Prompt übergeben und eine Ausgabe dazu vom Modell erzeugt. Diesem Paar an Eingabe und Ausgabe wird vom Reward Modell ein Reward-Wert zugeordnet. Dieser Reward fließt dann wieder in das Modell mit ein, um die Policy, also das Modell zu verbessern. Die Policy wird mit dem sogenannte Proximal Policy Optimization (PPO) Algorithmus angepasst. PPO ist dabei eine Methode, die bei der Aktualisierung der Policy verwendet wird. Er führt dabei einen sogenannten Clipping-Mechanismus ein, um sicherzustellen, dass die Aktualisierungen der Policy innerhalb einer Vertrauensregion liegen. Dadurch wird verhindert, dass die Policy zu stark verändert wird, indem zu viel vergessen wird. PPO verwendet außerdem eine sogenannte Value-Funktion (Reward Modell), um die Varianz der Policy-Gradienten zu verringern und die Lernleistung zu verbessern [10, 11, 15].

Evaluation des Modells

Die Bewertung des Modells erfolgt, indem während des Trainings ein Testdatensatz, den das Modell noch nie gesehen hat, beiseitegelegt wird. Anhand dieses Testdatensatzes wird dann eine Reihe von Bewertungen durchgeführt, um zu überprüfen, ob das Modell besser an die Absichten der Benutzer angepasst ist.

Das Modell wird dabei anhand von drei übergeordneten Kriterien bewertet:

  • Hilfsbereitschaft: Beurteilung der Fähigkeit des Modells, den Anweisungen des Benutzers zu folgen und Anweisungen abzuleiten.
  • Wahrheitsgehalt: Beurteilung der Neigung des Modells zu Halluzinationen (Erfinden von Fakten) bei Aufgaben in geschlossenen Bereichen.
  • Harmlosigkeit: die Fähigkeit des Modells, unangemessene, herabsetzende und verunglimpfende Inhalte zu vermeiden.

Dieser gesamte Ansatz hat natürlich auch gewisse Unzulänglichkeiten, die im InstructGPT Paper von OpenAI noch genauer aufgezählt werden [10, 11, 15].

Limitationen

Es gibt trotzdem noch gewisse Limitationen, die ChatGPT besitzt und die nicht unterschätzt werden dürfen. Dadurch, dass das Modell nur aus Sprache lernt, nimmt es dessen Eigenheiten an und wird so natürlich auch Fehlverhalten annehmen:

  • ChatGPT schreibt manchmal plausibel klingende, aber falsche oder unsinnige Antworten.
  • ChatGPT reagiert empfindlich auf Änderungen der Eingabeformulierung oder auf mehrfache Versuche mit der gleichen Frage.
  • Das Modell ist oft übermäßig wortreich und verwendet bestimmte Phrasen zu oft, wie z. B. den Hinweis, dass es sich um ein von OpenAI trainiertes Sprachmodell handelt.
  • Im Idealfall würde das Modell klärende Fragen stellen, wenn der Benutzer eine mehrdeutige Anfrage stellt. Stattdessen erraten aktuelle Modelle in der Regel, was der Benutzer beabsichtigt.
  • ChatGPT kann gelegentlich schädliche Anweisungen oder voreingenommene Inhalte produzieren.
  • Das Modell besitzt nur ein begrenztes Wissen über die Welt und Ereignisse, die nach 2021 passiert sind, da es auf Daten vor 2022 trainiert wurde.

Doch trotz der Limitationen, die bei ChatGPT bestehen, wurde ein riesiger Hype ausgelöst.

Hype von ChatGPT

ChatGPT ist von der technischen Sicht aus betrachtet keine neue bahnbrechende Erfindung. Die Methodiken, die zum Einsatz kommen, werden in der Forschung bereits in vielen anderen Modellen benutzt. Der Hype um ChatGPT kommt vor allem durch die öffentliche Bereitstellung des Modells für jedermann. Diese kostenlose Testphase mit einer einfachen und schönen Gestaltung des Dialogs macht ChatGPT so erfolgreich. Punkte, die ChatGPT selbst aufzählt, warum es so erfolgreich ist, sind:

  • 24/7-Verfügbarkeit: Als KI benötige ich keine Pausen oder Ruhezeiten, sodass ich zu jeder Tages- und Nachtzeit zur Verfügung stehe, um Menschen bei ihren Fragen und Gesprächen zu helfen.
  • Erreichbarkeit: Die Menschen können mich von überall auf der Welt erreichen, solange sie eine Internetverbindung haben. Das macht es für die Menschen einfach, die benötigten Informationen zu erhalten, egal wo sie sich befinden.
  • Flexibel: Ich kann bei einem breiten Spektrum von Themen und Fragen helfen, von allgemeinem Wissen bis hin zu speziellen technischen Fragen. Das macht mich zu einem vielseitigen Werkzeug für die Menschen.
  • Schnelle Reaktionszeit: Ich kann Anfragen fast sofort bearbeiten und beantworten, was besonders hilfreich für Menschen ist, die schnelle Antworten brauchen.
  • Datenschutz: Als Sprachmodell benötige ich keine persönlichen Informationen der Nutzer. Das bedeutet, dass die Menschen mir Fragen stellen und Hilfe erhalten können, ohne sich Sorgen machen zu müssen, dass ihre Privatsphäre gefährdet wird.

Wenn ChatGPT bereits jetzt so große Wellen schlägt, stellt sich natürlich die Frage, wie es mit dem Nachfolger GPT-4 aussieht.

Ausblick GPT-4

GPT-4, die Weiterentwicklung der GPT-Serie, soll laut Gerüchten der New York Times sogar noch im Jahr 2023 erscheinen. Es soll sich dabei auf jeden Fall um ein noch mächtigeres Modell handeln als die bisherigen veröffentlichten Modelle. Die Gerüchte, dass es sich um ein Modell mit 100 Billionen Parametern handeln soll, wurden vom OpenAI CEO Sam Altman als völliger Blödsinn bezeichnet. Zu diesen Gerüchten sagte er: „Die GPT-4-Gerüchteküche ist eine lächerliche Sache. Ich weiß nicht, woher das alles kommt. Die Leute betteln darum, enttäuscht zu werden, und das werden sie auch.“ Somit kann man nur gespannt sein, wie gut GPT-4 sein wird und wann OpenAI das neue Modell veröffentlicht [17].

Es gab jedoch noch einige Veröffentlichungen von Konkurrenten zu ChatGPT, die ebenfalls neue Modelle ankündigten:

  • Google hat seinen Counterpart Bard veröffentlicht, der jedoch in einer Demo eine falsche Antwort lieferte und deshalb die Aktien des Mutterkonzerns einbrachen und 100 Milliarden Dollar Börsenwert kostete [18].
  • Das chinesische Unternehmen Baidu kündigte im Februar 2023 an, dass es im März 2023 einen ChatGPT-ähnlichen Dienst namens “Wenxin Yiyan” auf Chinesisch oder “Ernie Bot” auf Englisch auf den Markt bringen wird [19].
  • Die südkoreanische Suchmaschinenfirma Naver kündigte im Februar 2023 an, dass sie in der ersten Jahreshälfte 2023 einen ChatGPT-ähnlichen Dienst namens “SearchGPT” in koreanischer Sprache auf den Markt bringen werden [19].

Die Modelle, die in nächster Zeit veröffentlicht werden sollen, werden immer größer. Doch kann die Skalierung immer so weiter gehen und die Anzahl der Parameter immer vergrößert werden? Oder bringt das ganze letztendlich keine Verbesserung der Leistung dieser Modelle? Diese Frage werden wir im nächsten Kapitel klären.

Skalierung von Sprachmodellen

Wie wir festgestellt haben, ist die Anzahl der Parameter sowie die Menge der Trainingsdaten mit jeder Version von GPT angestiegen (siehe Tabelle 1). Zwar ist nicht bekannt, wie groß GPT-4 sein wird, es lässt sich aber vermuten, dass GPT-4 mehr Parameter enthalten wird, auch wenn der Anstieg unter Umständen nicht so stark sein wird wie zwischen vorherigen Versionen von GPT. Aufgrund des Trends zu immer größeren Modellen möchten wir nun auf die Skalierbarkeit von Sprachmodellen eingehen.
OpenAI hat dabei in dem Paper „Scaling Laws for Neural Language Models“ selbst empirische Untersuchungen zur Skalierung in Sprachmodellen aufgestellt. Dabei werden Decoder-Only-Transformer als autoregressive Sprachmodelle evaluiert.

Es wurden Eigenschaften wie Parameteranzahl, Größe des verwendeten Trainingsdatensatzes und Trainingsaufwand sowie die Modellarchitektur untersucht. Die Erkenntnisse der Untersuchungen werden wir hier zusammenfassen.

Es lässt sich feststellen, dass die Performance in starkem Maße von der Skalierung der genannten Parameter abhängt. Das bedeutet, dass durch größere Modelle mit mehr Parametern und mehr Trainingsdaten sowie durch einen höheren Trainingsaufwand die Qualität von Sprachmodellen signifikant verbessert wird. Dieser Zusammenhang ist in Abbildung 6 abgebildet. Der Fehler auf den Testdaten nimmt bei Erhöhung der entsprechenden Größen ab.

Abbildung 6: Einfluss der Parameter Rechenleistung beim Training, Größe des Trainingsdatenset und Parameteranzahl auf den Test Loss [20]

Der Einfluss anderer Modelleigenschaften, wie etwa der Architektur z.B. in Bezug auf Anzahl der Layer hat einen deutlich geringeren Einfluss auf die Qualität des Modells. Bei Erhöhung der Parameteranzahl sollte zwar auch die Menge der Trainingsdaten erhöht werden, in den Experimenten von Open-AI hat sich dabei jedoch gezeigt, dass diese nicht im gleichen Maße erhöht werden müssen. Für eine Erhöhung der Parameteranzahl um den Faktor 8 ist nur eine Erhöhung der Menge der Trainingsdaten um den Faktor 5 nötig, um Overfitting zu vermeiden.

Durch die Experimente wurde auch festgestellt, dass bei größeren Modellen mit mehr Parametern weniger Trainingssamples prozessiert werden müssen, um die gleiche Qualität wie bei einem kleinen Modell zu erreichen (siehe Abbildung 7). Dadurch sollte der Trainingsaufwand größerer Modelle im Vergleich zu kleineren Modellen gering gehalten werden, da nur ein kürzeres Training nötig ist [20].

Abbildung 7: Test-Loss von Modellen verschiedener Größen nach prozessierten Trainingselementen (aus [20])

Dies ist auch bei Betrachtung von Abbildung 8 zu erkennen. Hier sind die gesamten Rechenaufwände verschiedener bekannter Modelle abgebildet. Die hervorgehobenen Modelle GPT-3 2.7B (2.65 Mrd. Parameter) und RoBERTa-Large (355 Mio. Parameter) sind beides Tansformer-Sprachmodelle. Trotz der deutlich höheren Parameteranzahl in GPT-3 2.7B sind die Gesamtkosten des Trainings im Vergleich zu RoBERTa-Large nicht wesentlich größer, was sich dadurch begründen lässt, dass zum Training von GPT-3 2.7B deutlich weniger Trainingselemente prozessiert werden müssen [7].

Abbildung 8: Vergleich des Trainingsaufwands verschiedener bekannter Transformer-Sprachmodelle (aus [7])

Größere Modelle mögen zwar eine bessere Qualität besitzen und nach der Evaluation von weniger Trainingssamples wird bereits die gleiche Qualität wie in kleinen Modellen erreicht, sie haben dennoch auch einige Nachteile. Der Trainingsprozess ist oft aufwendiger und erfordert mehr Speicherplatz. Das Training von Modellen wie GPT-3 ist nur durch verteiltes Training auf verschiedenen GPUs möglich. Grundsätzlich werden dabei die zwei Vorgehen Model-Parallelism und Data-Parallelism unterschieden. Beim Model-Parallelism erfolgt dabei eine Aufteilung des Modells, während beim Data-Parallelism eine Aufteilung der Daten erfolgt [21]. Wir werden in diesem Blog-Artikel nicht auf Details dazu eingehen, diese wurden bereits unter An overview of Large Scale Deep Learning erklärt.

Gerade das Training auf mehreren Grafikkarten führt zu sehr hohen Energiekosten. Bei GPT-3 werden die Energiekosten zum Pre-Training z.B. auf 1287 MWh. geschätzt, was einem Ausstoß von 552 Tonnen CO₂-Äquivalent entspricht [22].

Fazit

Generell sollte die Anzahl der Modellparameter sorgfältig abgewogen werden, eine höhere Anzahl von Parametern, die unter Umständen zu einer besseren Qualität führt, rechtfertigt nicht immer einen Mehraufwand. Eine einfache Nutzung des Sprachmodells als Anwendung z.B. über einen Chat-Bot wie bei ChatGPT ist für Nutzer ebenso relevant wie eine hohe Qualität der Sprachausgabe. GPT-3 ist im Vergleich mit vielen anderen Sprachmodellen nämlich bei Weitem nicht das größte Modell. Dennoch ist GPT-3 durch ChatGPT aktuell mit Abstand am stärksten im Fokus der Aufmerksamkeit. Die Ausgaben von ChatGPT sind bereits sehr gut. Neben einer Verbesserung durch ein größeres Sprachmodell wären vor allem auch Aspekte wie Verfügbarkeit der Anwendung für den Nutzer relevant, diese sollten nicht ignoriert werden.

Insgesamt lässt sich festhalten, dass die Entwicklung von Sprachmodellen wie ChatGPT in den letzten Jahren rasant vorangeschritten ist und die Modelle immer größer und leistungsfähiger geworden sind. Dabei wurde durch die Skalierung der Parameter auch immer wieder die Frage aufgeworfen, ob dies sinnvoll ist und ob es tatsächlich zu einer Verbesserung der Leistung führt. Die Forschungsergebnisse zeigen jedoch, dass eine Skalierung der Parameter tatsächlich zu einer deutlichen Steigerung der Leistungsfähigkeit von Sprachmodellen führen kann. ChatGPT und ähnliche Modelle sind in der Lage, erstaunlich komplexe Aufgaben zu lösen, wie zum Beispiel das Verfassen von Texten, die kaum von menschlicher Schreibweise zu unterscheiden sind.

Im Hinblick auf die Zukunft stehen jedoch noch zahlreiche Herausforderungen bevor, die es in den nächsten Jahren zu meistern gilt. Eine der wichtigsten Aufgaben ist es, die Modellinterpretierbarkeit zu verbessern, um sicherzustellen, dass Entscheidungen auf nachvollziehbare und transparente Weise getroffen werden können. Darüber hinaus müssen neue Methoden entwickelt werden, um die Rechenressourcen effizienter zu nutzen und den Energieverbrauch der Modelle zu reduzieren. Nichtsdestotrotz haben ChatGPT und ähnliche Modelle das Potenzial, die Art und Weise zu revolutionieren, wie wir mit Sprache interagieren und wie wir Informationen verarbeiten und kommunizieren. Angesichts der rasanten Entwicklung dieser Technologien bleibt es spannend zu beobachten, wie sich diese in Zukunft weiterentwickeln werden und welche Forschungsthemen sich ergeben.

Verwendete Quellen:

[1]B. Lutkevich, „Language Modeling,“ März 2020. [Online]. Available: https://www.techtarget.com/searchenterpriseai/definition/language-modeling#:~:text=Language%20modeling%20(LM)%20is%20the,basis%20for%20their%20word%20predictions.
[2]D. Markowitz, „Transformers, Explained: Understand the Model Behind GPT-3, BERT, and T5,“ Medium, 06 Mai 2021. [Online]. Available: https://towardsdatascience.com/transformers-explained-understand-the-model-behind-gpt-3-bert-and-t5-cdbf3fc8a40a.
[3]J. Alammar, „The Illustrated Transformer,“ 27 Juni 2018. [Online]. Available: http://jalammar.github.io/illustrated-transformer/.
[4]A. Vaswani, N. Shazeer, N. Parmar, J. Uszkoreit, L. Jones, A. N. Gomez, L. Kaiser und I. Polosukhin, „Attention Is All You Need,“ Open-AI, 2017. [Online]. Available: http://arxiv.org/abs/1706.03762.
[5]A. Radford und K. Narasimhan, „Improving Language Understanding by Generative Pre-Training,“ 2018. [Online]. Available: https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf.
[6]A. Radford, J. Wu, R. Child, D. Luan, D. Amodei und I. Sutskever, „Language Models are Unsupervised Multitask Learners,“ 2019. [Online]. Available: https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf.
[7]T. B. Brown, B. Mann, N. Ryder, M. Subbiah und J. Kaplan, „Language Models are Few-Shot Learners,“ Open-AI, 28 Mai 2020. [Online]. Available: https://arxiv.org/abs/2005.14165.
[8]Johannes Maucher, „Sequence-To-Sequence, Attention, Transformer — Machine Learning Lecture,“ 2023. [Online]. Available: https://hannibunny.github.io/mlbook/transformer/attention.html#gpt-gpt-2-and-gpt-3.
[9]R. Sagar, „OpenAI Releases GPT-3, The Largest Model So Far,“ 2020. [Online]. Available: https://analyticsindiamag.com/open-ai-gpt-3-language-model/.
[10]M. Ramponi, „How ChatGPT actually works,“ 2022. [Online]. Available: https://www.assemblyai.com/blog/how-chatgpt-actually-works/.
[11]L. Ouyang, J. Wu, X. Jiang, D. Almeida, C. L. Wainwright, P. Mishkin, C. Zhang, S. Agarwal, K. Slama, A. Ray, J. Schulman, J. Hilton, F. Kelton, L. Miller, M. Simens, A. Askell, P. Welinder, P. Christiano, J. Leike und R. Lowe, „Training language models to follow instructions with human feedback,“ 2022. [Online]. Available: https://arxiv.org/pdf/2203.02155.pdf.
[12]Alan D. Thompson, „GPT-3.5 + ChatGPT: An illustrated overview – Dr Alan D. Thompson – Life Architect,“ 2022. [Online]. Available: https://lifearchitect.ai/chatgpt/.
[13]Dan Milmo, „ChatGPT reaches 100 million users two months after launch,“ 2023. [Online]. Available: https://www.theguardian.com/technology/2023/feb/02/chatgpt-100-million-users-open-ai-fastest-growing-app.
[14]OpenAI, „ChatGPT: Optimizing Language Models for Dialogue,“ 2022. [Online]. Available: https://openai.com/blog/chatgpt/.
[15]M. Ruby, „How ChatGPT Works: The Model Behind The Bot – Towards Data Science,“ 2023. [Online]. Available: https://towardsdatascience.com/how-chatgpt-works-the-models-behind-the-bot-1ce5fca96286.
[16]Gabriele De Luca, „What is a Policy in Reinforcement Learning?,“ 2020. [Online]. Available: https://www.baeldung.com/cs/ml-policy-reinforcement-learning.
[17]J. Vincent, „OpenAI CEO Sam Altman on GPT-4: ‘people are begging to be disappointed and they will be’,“ 2023. [Online]. Available: https://www.theverge.com/23560328/openai-gpt-4-rumor-release-date-sam-altman-interview.
[18]tagesschau, „Panne im Werbeclip für “Bard”: Google-Textroboter gibt falsche Antwort,“ 2023. [Online]. Available: https://www.tagesschau.de/wirtschaft/google-ki-chatbot-bard-101.html.
[19]Wikipedia, „ChatGPT,“ 2023. [Online]. Available: https://en.wikipedia.org/w/index.php?title=ChatGPT&oldid=1140902725.
[20]J. Kaplan, T. Henighan, T. B. Brown, R. Child, S. Gray, A. Radford, J. Wu und D. Amodei, „Scaling Laws for Neural Language Models,“ Open-AI, 23 Januar 2020. [Online]. Available: https://arxiv.org/abs/2001.08361.
[21]C. Wolfe, „Language Model Scaling Laws and GPT-3,“ Medium, 10 Dezember 2022. [Online]. Available: https://towardsdatascience.com/language-model-scaling-laws-and-gpt-3-5cdc034e67bb.
[22]D. Patterson, J. Gonzalez, U. Hölzle, Q. Le und C. Liang, „The Carbon Footprint of Machine Learning Training Will Plateau, Then Shrink,“ 11 April 2022. [Online]. Available: https://arxiv.org/abs/2204.05149.

An overview of Large Scale Deep Learning

article by Annika Strauß (as426) and Maximilian Kaiser (mk374)

1. Introduction

One of the main reasons why machine learning did not take off in the 1990s was that the lack of computational power and  the size of data sets, available at that time

Since then, a lot has changed and machine learning methods have found their way into the field of ultra large systems (ULS) like f.e. Google, where they have been used very successfully for quite some time.

Two main areas of application can be distinguished:

  • Learn better ML models faster with very large data sets and very high computing power by parallelizing and distributing different components of the ML computation.
  • Deep Learning methods are developed, trained and applied to control, understand, improve and optimize specific areas within a ULS, e.g. replace multiple overcomplicated subcomponents with a single, machine learned model that still does the same job
Continue reading

About the Robustness of Machine Learning

Glitch

In the past couple of years research in the field of machine learning (ML) has made huge progress which resulted in applications like automated translation, practical speech recognition for smart assistants, useful robots, self-driving cars and lots of others. But so far we only have reached the point where ML works, but may easily be broken. Therefore, this blog post concentrates on the weaknesses ML faces these days. After an overview and categorization of different flaws, we will dig a little deeper into adversarial attacks, which are the most dangerous ones.

Continue reading

Large Scale Deployment for Deep Learning Models with TensorFlow Serving

Image source

Introduction

“How do you turn a trained model into a product, that will bring value to your enterprise?”

In recent years, serving has become a hot topic in machine learning. With the ongoing success of deep neural networks, there is a growing demand for solutions that address the increasing complexity of inference at scale. This article will explore some of the challenges of serving machine learning models in production. After a brief overview of existing solutions, it will take a closer look at Google’s TensorFlow-Serving system and investigate its capabilities. Note: Even though they may be closely related, this article will not deal with the training aspect of machine learning, only inference.

Inference and Serving

Before diving in, it is important to differentiate between the training and inference phases, because they have completely different requirements.

  • Training is extremely compute-intensive. The goal here is to maximize the number of compute operations in a given time. Latency is not of concern.
  • Inference costs only a fraction of the computing power that training does. However, it should be fast. When you query the model, you want the answer immediately. Inference must be optimized for latency and throughput.

There are two ways to deploy a model for inference. Which one to use largely depends on the use case. First, you can push the entire model to client devices and have them do inference there. Lots of ML features are already baked into our mobile devices this way. T­his works well for some applications e.g. for Face-ID or activity-detection on phones, but falls flat for many other, large-scale industrial applications. You probably won’t have latency problems, but you are limited to the client’s compute power and local information. On the other hand, you can serve the model yourself. This would be suitable for industrial-scale applications, such as recommender systems, fraud detection schemes, intelligent intrusion detection systems and so forth. Serving allows for much larger models, direct integration into your own systems and the direct control and insights that come with it.

Serving Machine Learning at Scale

Of course, it’s never that easy. In most “real-world” scenarios, there isn’t really such a thing as a “finished ML model”. Consider the “Cross-industry standard process for data mining”:

Fig. 1 – Back to the basics: the six phases of CRISP-DM. Source

It might be ancient, but it describes a key concept for successful data mining/machine learning: It is a continuous process [12]. Deployment is part of this process, which means: You will replace your productive models, and you will do it a lot! This will happen for a number of reasons:

  • Data freshness: The ML model is trained on historical data. This data can go stale quickly, because new patterns constantly appear in the real world. Model performance will deteriorate, and you must replace the model with one that was trained on more recent data, before performance drops too low.
  • Model revision: With time, retraining the model might just not be enough to keep the performance up. At this point you need to revise the model architecture itself, perhaps even start from scratch.
  • Experiments: Perhaps you want to try another approach to a problem. For that reason you want to load a temporary, new model, but not discontinue your current one.
  • Rollbacks: Something went wrong, and you need to revert to a previous version.

Version control and lifecycle management aren’t exactly new ideas. However, here they come with a caveat: Since artificial neural networks are essentially “clunky, massive databases” [5], loading and unloading them can have an impact on performance. For reference, some of the most impactful deep models of recent years are a few hundreds of megabytes in size (AlexNet: 240MB, VGG-19: 574MB, ResNet-200: 519MB). But as model performance tends to scale with depth, model size can easily go to multiple gigabytes. That might not be much in terms of “Big Data”, but it’s still capable of causing ugly latency spikes when implemented poorly. Besides ML performance metrics, the primary concerns are latency and throughput. Thus, the serving solution should be able to [4]:

  • quickly replace a loaded model with another,
  • have multiple models loaded at the same time, in the same process,
  • cope with differences in model size and computational complexity,
  • avoid latency spikes when new models are loaded into RAM,
  • if possible, be optimized for GPUs and TPUs to accelerate inference,
  • scale out inference horizontally, depending on demand.

Serving Before “Model Servers”

Until some three years ago, you basically had to build your ML serving solution yourself. A popular approach was (and still is) using Flask or some other framework to serve requests against the model, some WSGI server to handle multiple requests at once and have it all behind some low-footprint web-server like Nginx.

Fig. 2 – An exemplary serving solution architecture. Source: [8]

However, while initially simple, these solutions are not meant to perform at “ultra large” scale on their own. They have difficulty benefiting from hardware acceleration and can become complex fast. If you needed scale, you had to create your own solution, like Facebook’s “FBLearnerPredictor” or Uber’s “Michelangelo”. Within Google, initially simple solutions would often evolve into sophisticated, complex pieces of software, that scaled but couldn’t be repurposed elsewhere [1].

The Rise of Model Servers

Recent years have seen the creation of various different model serving systems, “model servers”, for general machine learning purposes. They take inspiration from the design principles of web application servers and interface through standard web APIs (REST/RPC), while hiding most of their complexity. Among simpler deployment and customization, model servers also offer machine learning-specific optimizations, e.g. support for Nvidia GPUs or Google TPUs. Most model servers have some degree of interoperability with other machine learning platforms, especially the more popular ones. That said, you may still restrict your options, depending on your choice of platform.

Fig. 3 – Exemplary model server for an image recognition task. Source: [10]

A selection of popular model serving and inference solutions includes:

  • TensorFlow Serving (Google)
  • TensorRT (Nvidia)
  • Model Server for Apache MXNet (Amazon)
  • Clipper
  • MLflow
  • DeepDetect
  • Skymind Intelligence Layer for Deeplearning4j

TensorFlow-Serving

By far the most battle-tested model serving system out there is Google’s own TensorFlow-Serving. It is used in Google’s internal model hosting service TFS², as part of their TFX general purpose machine learning platform [2]. It drives services from the Google PlayStore’s recommender system to Google’s own, fully hosted “Cloud Machine Learning Engine”. TensorFlow-Serving natively uses gRPC, but it also supports RESTful APIs. The software can be downloaded as a binary, Docker image or as a C++ library.

Architecture

The core of TensorFlow-Serving is made up of four elements: Servables, Loaders, Sources and Managers. The central element in TensorFlow Serving is the servable [3]. This is where your ML model lives. Servables are objects, that TensorFlow-Serving uses for inference. For example, one servable could correspond to one version of your model. Servables can be simplistic or complicated, anything from lookup-tables to multi-gigabyte deep neural networks. The lifecycles of servables are managed by loaders, which are responsible for loading servables to RAM and unloading them again. Sources provide the file system, where saved models are stored. They also provide a list of the specific servables, that should be loaded and used in production, the aspired versions. Managers are the broadest class. Their job is to handle the full life cycle of servables, i.e. loading, serving and unloading the aspired versions. They try to fulfill the requests from sources with respect the specified version policy.

Fig. 4 – TensorFlow-Serving architecture overview. Source: [3]

When a servable is elevated to an aspired version, its source creates a loader object for it. This object only contains metadata at first, not the complete (potentially large) servable. The manager listens for calls from loaders, that inform it of new aspired versions. According to its version policy, the manager then executes the requested actions, such as loading the aspired version and unloading the previous one. Loading a servable can be temporarily blocked if resources are not available yet. Unloading a servable can be postponed while there are still active requests to it. Finally, clients interface with the TensorFlow-Serving core through the manager. Both requests and responses are JSON objects.

Simple Serving Example

Getting started with a minimal setup is as simple as pulling the tensorflow/serving Docker image and pointing it at the saved model file [16]. Here I’m using a version of ResNet v2, a deep CNN for image recognition, that has been pretrained on the ImageNet dataset. The image below is encoded in Base64 and sent to the manager as a JSON object.

Fig. 5 – Some random image to predict. Source

The prediction output of this model consists of the estimated probabilities for each of the 1000 classes in the ImageNet dataset, and the index of the most likely class.

Fig. 6 – Model output, class 771 corresponds to “running_shoe”.

Performance

Implementing and hosting a multi-model serving solution for an industrial-scale web application with millions of users, just for benchmarks, is slightly out of scope for now. However, Google provides some numbers that should give an idea of what you can expect TensorFlow-Serving to do for you.

Latency

A strong point of TensorFlow-Serving is multi-tenancy, i.e. serving multiple models in the same process concurrently. The key problem with this is avoiding cross-model interference, i.e. one model’s performance characteristics affecting those of another. This is especially challenging while models are being loaded to RAM. Google’s solution is to provide a separate thread-pool for model-loading. They report that even under heavy load, while constantly switching between models, the 99th percentile inference request latency stayed in the range from ~75 to ~150 milliseconds in their own TFX benchmarks [2].

Throughput

Google claims that the serving system on its own can handle around 100,000 requests per second per core on a 16 vCPU Intel Xeon E5 2.6 GHz machine [1]. That is however ignoring API overhead and model complexity, which may significantly impact throughput. To accelerate inference on large models with GPUs or TPUs, requests can be batched together and processed jointly. They do not disclose whether this affects request latency. Since late February (TensorFlow-Serving v1.13), TensorFlow-Serving can now work directly in conjunction with TensorRT [14], Nvidia’s high-performance deep learning inference platform, which claims a 40x increase in throughput compared to CPU-only methods [15].

Usage and Adoption

In their paper on TFX (TensorFlow Extended), Google presents their own machine learning platform, that many of its services use [2]. TFX’ serving component, TFS², uses TensorFlow-Serving. As of November 2017, TensorFlow-Serving is handling tens of millions of inferences per second for over 1100 of Google’s own projects [13]. One of the first deployments of TFX is the recommender system for Google Play, which has millions of apps and over a billion active users (over two billion if you count devices). Furthermore, TensorFlow-Serving is also used by companies like IBM, SAP and Cloudera in their respective multi-purpose machine learning and database platforms [2].

Limitations

Today’s machine learning applications are very much capable of smashing all practical limits: DeepMind’s AlphaGo required 1920 CPUs and 280 GPUs running concurrently in real-time, for inference, for a single “client” [6]. That example might be excessive, but the power of deep ML models does scale with their size and compute complexity. Deep learning models today can become so large that they don’t fit on a single server node anymore (Google claims that they can already serve models up to a size of one terabyte in production, using a technique called model sharding [13]). Sometimes it is worth investing the extra compute power, sometimes you just need to squeeze that extra 0.1 percent accuracy out of your model, but often there are diminishing returns,. To wrap it up, there may be a trade-off between the power of your model versus latency, throughput and runtime cost.

Conclusion

When you serve ML models, your return on investment is largely determined by two factors: How easily you can scale out inference and how fast you can adapt your model to change. Model servers like TensorFlow-Serving address the lifecycle of machine learning models, without making the process disruptive in a productive environment. A good serving solution can reduce both runtime and implementation costs by a significant margin. While building a productive machine learning system at scale has to integrate a myriad different steps from data preparation to training, validation and testing, a scalable serving solution is the key to making it economically viable.

References and Further Reading

  1. Olston, C., Fiedel, N., Gorovoy, K., Harmsen, J., Lao, L., Li, F., Rajashekhar, V., Ramesh, S., and Soyke, J. (2017). Tensorflow-serving: Flexible, high-performance ML serving.CoRR, abs/1712.06139
  2. Baylor, D., Breck, E., Cheng, H.-T., Fiedel, N., Foo, C. Y., Haque, Z., Haykal, S., Ispir, M., Jain, V., Koc, L., Koo, C. Y., Lew, L., Mewald, C., Modi, A. N., Polyzotis, N., Ramesh, S., Roy, S., Whang, S. E., Wicke, M., Wilkiewicz, J., Zhang, X., and Zinkevich, M. (2017). Tfx: A tensorflow-based production-scale machine learning platform. In Proceedings of the 23rd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, KDD ’17, pages 1387–1395, New York, NY, USA. ACM.
  3. TensorFlow-Serving documentation – https://www.tensorflow.org/tfx/guide/serving (accessed 11.03.2019)
  4. Serving Models in Production with TensorFlow Serving (TensorFlow Dev Summit 2017) – https://www.youtube.com/watch?v=q_IkJcPyNl0 (accessed 11.03.2019)
  5. Difference Inference vs. Training – https://blogs.nvidia.com/blog/2016/08/22/difference-deep-learning-training-inference-ai/ (accessed 11.03.2019)
  6. Challenges of ML Deployment – https://www.youtube.com/watch?v=JKxIiSfWtjI (accessed 11.03.2019)
  7. Lessons Learned from ML deployment – https://www.youtube.com/watch?v=-UYyyeYJAoQ (accessed 11.03.2019)
  8. https://hackernoon.com/a-guide-to-scaling-machine-learning-models-in-production-aa8831163846 (accessed 11.03.2019)
  9. https://medium.com/@maheshkkumar/a-guide-to-deploying-machine-deep-learning-model-s-in-production-e497fd4b734a (accessed 11.03.2019)
  10. https://medium.com/@vikati/the-rise-of-the-model-servers-9395522b6c58 (accessed 11.03.2019)
  11. https://blog.algorithmia.com/deploying-deep-learning-cloud-services/ (accessed 11.03.2019)
  12. https://the-modeling-agency.com/crisp-dm.pdf (accessed 11.03.2019)
  13. https://ai.googleblog.com/2017/11/latest-innovations-in-tensorflow-serving.html (accessed 12.03.2019)
  14. https://developer.nvidia.com/tensorrt (accessed 12.03.2019)
  15. https://medium.com/tensorflow/optimizing-tensorflow-serving-performance-with-nvidia-tensorrt-6d8a2347869a (accessed 12.03.2019)
  16. https://medium.com/tensorflow/serving-ml-quickly-with-tensorflow-serving-and-docker-7df7094aa008 (accessed 12.03.2019)
  17. https://www.slideshare.net/shunyaueta/tfx-a-tensor-flowbased-productionscale-machine-learning-platform (accessed 12.03.2019)

Improved Vulnerability Detection using Deep Representation Learning

Today’s software is more vulnerable to cyber attacks than ever before. The number of recorded vulnerabilities has almost constantly increased since the early 90s. The strong competition on the software market along with many innovative technologies getting released every year forces modern software companies to spend more resources on development and less resources on software quality and testing. In 2017 alone, 14.500 new vulnerabilities were recorded by the CVE (Common Vulnerability and Exposures) database, compared to the 6.000 from the previous year. This will continue in the years to come. [1]

Continue reading

Federated Learning

The world is enriched daily with the latest and most sophisticated achievements of Artificial Intelligence (AI). But one challenge that all new technologies need to take seriously is training time. With deep neural networks and the computing power available today, it is finally possible to perform the most complex analyses without need of pre-processing and feature selection. This makes it possible to apply new models to numerous applications. The only thing needed is tons of training data, a good model and a lot of patience during training.

Continue reading

About using Machine Learning to improve performance of Go programs

Gophers

This Blogpost contains some thoughts on learning the sizes arrays, slices or maps are going to reach using Machine Learning (ML) to increase  programs’ performances by allocating the necessary memory in advance instead of reallocating every time new elements are appended.

What made me write this blogpost?

Well first of all I had to because it is part of the lecture Ultra Largescale Systems (ULS) I attended past winter term. But as an introduction I’ll tell you what made me choose this topic: I started to learn Golang and coming from mainly Java, Python and JavaScript the concept of Arrays with fixed sizes and Slices wrapped around them for convenience was new to me. When I understood that initializing them with the correct capacity is good for performance and memory usage I always tried to so. Until I came to some use case where I could not know the capacity in advance. At almost the same time we talked about “ML for Systems” in the ULS-lecture. There the power of ML is used to speed up Databases, loadbalance Elastic Search Queries and other things. So I came up with the idea of ML for programming languages in this case for learning capacities in Golang. By the way I wanted to try out ML in Go, which is said to bring some performance advantages compared to python and is easier to deliver. But neither ML in Go (go for ML) nor ML on Go is topic of this post, though both appear at some parts.

The goal in more detail

As explained in various blogposts like here and there, arrays have fixed sizes in Go. For convenient manipulation anyway they can be wrapped by slices. Thus appending to a slice that reached its capacity needs to create a new slice with a larger underling array, copy the contents of the old slice to the new one and then replace the old one by the new one. This is what the append method does. That this process is more time consuming than appending to a slice that has a sufficient capacity can be shown with some very simple code that just appends 100 times to a test slice in a loop. Once the slice is initialized with a capacity of zero and once with 100. For both cases we calculate the durations it takes and compare them. Since those durations can vary for the same kind of initialization we run this 1000 times each and calculate the average duration to get more meaningful results. The averages are calculated by the method printSummary which is left out here in order to keep track of things. However the whole code can be found on GitHub.

func main() {
times := 1000
results := make([]time.Duration, 0, times)
for t := 0; t < times; t++ {
start := time.Now()
// initialize either with capacity of 0
// test := make([]int, 0)
// or initialize with final capacity of 100
test := make([]int, 0, 100)
for i := 0; i < 100; i++ {
// uncomment to see how the capacity grows in larger steps
// fmt.Println(cap(test), len(test))
test = append(test, i)
}
elapsed := time.Now().Sub(start)
results = append(results, elapsed)
}
printSummary(results)
}

As expected the correct initialized version runs with an average of 1714ns faster than the other one with an average of 2409ns. Of course those durations are still just samples and vary if the code runs multiple times. But in over 20 runs each there is only one average value of the bad initialized slice lower than some of the good ones.

If we also take a look at the capacity the slower version ends up with, we see that this is 128 instead of the required 100. This is because append always doubles the capacity if it reaches the limit.

So we can see that it is worth setting the capacity correct in advance for performance and resource consumption reasons. But this is not always as easy as in the example we just saw and sometimes it is not even possible to know the length a slice will grow up to in advance. In those cases it might make sense to let the program learn the required capacities. It could be helpful at initialization with make as well as for growing with append.

A basic example

Setup

To check out feasibility I created a basic example that is a bit more complex than the first one but still possible to calculate as well. It iterates over index j and value s of a slice of random integer samples and for each of them the test slice is created. Then we append s times three values and one value j times. So the final length (and required capacity) of test can be calculated as s*3+j.

Also in this loop training data gets gathered. One sample consists of s and j as input and len(test) as label. Since the main goal of this scenario is to check if it’s worth using a trained ML model to predict the required capacity, this data is collected always to create equal conditions for every test case. Ways to avoid the time expensive training and data collection at runtime are discussed later.

func appendInBasicLoop(kind string) training.Examples {
samp := getSamples(1000)
data := make([]training.Example, 0, len(samp))
times := 1000
results := make([]time.Duration, 0, times)
for trys := 0; trys < times; trys++ {
start := time.Now()
for j, s := range samp {
var test []int
switch kind {
case "zero":
test = make([]int, 0)
case "calc":
test = make([]int, 0, s*3+j)
case "func":
test = make([]int, 0, getCap(s, j))
case "model":
test = make([]int, 0, getCapFromModel(s, j))
case "model+1":
test = make([]int, 0, getCapFromModel(s, j)+1)
}
for i := 0; i < s; i++ {
test = append(test, i)
test = append(test, j)
test = append(test, s)
}
for k := 0; k < j; k++ {
test = append(test, k)
}
data = append(data,
training.Example{
Input: []float64{float64(s), float64(j)},
Response: []float64{float64(len(test))}})
}
elapsed := time.Now().Sub(start)
results = append(results, elapsed)
}
printSummary(results)
return data
}

As implementation for the ML part I chose go-deep. I picked it from this list because it looked well documented, easy to use and sufficient for my needs, though not perfect.

I used the collected training data to train a MLP (Multi Layer Perceptron) with two hidden layers containing two and five neurons. Of course I configured RegressionMode to use Identity as activation function in the output layer and MSE (Mean Square Error) as loss function. I also played around with some other hyperparameters but kept a lot from the examples provided as well, because the MSE already decreased very fast and became 0.0000 after three training-iterations. This is not surprising since the function to learn is very simple. Also there is no need to avoid overfitting in this basic example. I kept some of the belonging hyperparameters with low values anyway. In a real world use case one would probably try to keep the model as small as possible to get quickest responses.

var net *deep.Neural
func init() {
net = deep.NewNeural(&deep.Config{
Inputs: 2,
Layout: []int{2, 5, 1},
Activation: deep.ActivationReLU,
Mode: deep.ModeRegression,
Weight: deep.NewUniform(0.1, 0.0),
Bias: true,
})
}
func trainModel(data training.Examples) {
optimizer := training.NewAdam(0.02, 0.9, 0.999, 1e-8)
trainer := training.NewBatchTrainer(optimizer, 1, 200, 8)
training, heldout := data.Split(0.75)
trainer.Train(net, training, heldout, 7)
}
func getCapFromModel(s, j int) int {
p := net.Predict([]float64{float64(s), float64(j)})
return int(p[0])
}

Results

The following table shows the test cases I compared along with the average durations in nanoseconds calculated over 1000 tries each. Since those averages vary again from run to run the table contains three of them.

Test caseAvg ns run1Avg ns run2Avg ns run3
Initialize capacity with
zero
12.790.50114.267.92514.321.735
Use s*3+j directly in make5.679.5956.067.9685.943.731
Use a function to
calculate s*3+j
5.242.1826.012.9205.515.661
Use the prediction of the
learned model
10.898.4376.361.9119.056.003
The model’s prediction +16.069.7765.714.3486.144.386
The model’s prediction
on new random data
10.165.7646.096.9299.296.384

Even though the durations vary the results show that not initializing the capacity is worst. Also usually it is best to calculate the capacity, if possible. It does not really matter if the calculation happens in a function or directly. When I took a closer look at the model’s predictions I saw that they are quite often exactly one less than the actual capacity. This is why I also added the prediction+1 test case, which is almost as good as the direct calculations. So investigating a bit deeper in what the model predicts is worth it. Maybe some finetuning on the hyperparameters could also fix the problem instead of adding 1 manually. The results also show that the learned model works on completely new random data as well as on partly known data from the training.

Conclusion

Of course creating such a model for a small performance optimization is heavy overengineered and thus not worth it. It could be worth in cases where you know you have a bottleneck at this place (because your profiler told you) and you cannot calculate the required capacity in any other way in advance. In the introduction I already mentioned that I had a use case where it is not possible to do so. In this case the length of the slice depends on a sql.rows object which doesn’t tell you how many rows it contains in advance. Other examples might be conditional appends where you cannot know how many elements fulfill the condition to be appended to a slice or something else. But also in those cases the required capacity might depend on something else. For example the current time, the size of an HTTP request that caused this action or the length this slice reached the last time. In those cases using a ML model might be helpful to avoid a performance bottleneck. With dependencies to previous lengths especially RNNs (Recurrent Neural Networks) might be helpful. At least they probably could give a better guess than a developer himself.

Looking ahead

As stated above in examples like this the engineering effort is too high. So ways for automating would be desirable. First I thought about a one-size-fits-all solution meaning one pretrained model that predicts for various makes the required capacity. But it would be difficult to find good features because they could change from make to make and just using all sorts of possible features would create very sparse matrices and require larger models if they could work at all.

So we should stick to use case specific models that can be smaller and use meaningful features depending on their environment like lengths of arrays, slices, maps or strings “close” to them or values of specific bools or integers. The drawback is that individual models need individual training maybe with production like data. Training during runtime would cause an overhead that might destroy the benefit the model could bring and slow the program down at least for a while until training can be stopped or paused because the ML model’s performance is good enough. So if possible pure online learning should be avoided and training on test stages or at times with low traffic should be preferred. If the length of a slice depends on the current traffic this is of course not possible. Then one should at least make use of dumping a model’s weights from time to time to the logs to be able to reuse them when starting a new node.

Still we need to solve the overengineering issue and try to build a model automatically at compile time, if the developer demands to do so for example using an additional argument in the call to make. I think that this might be another use case for ML on code: Finding good features and parameters to build a ML model by inspecting the code. Unfortunately I’m not sure what such an ML model on code could look like and what it would require to train it. Using a GAN (Generative adversarial network) to generate the models would probably require already existing ones to train the discriminator. If the automation could be realized the use case also could get broader because then calculating the capacity would be more effort than just saying “learn it”.

Some final thoughts

Using ML would not magically boost performance. It would require developers to remeasure and double check if it’s worth using it. For example it is not only important how often the program needs to allocate memory but also where. So stack allocation is cheap and heap allocation is expensive as explained in this blog post. If using ML to predict the capacity requires the program to allocate on the heap it might be slower even when the predictions are correct. In the test scenario above all the cases instead of initializing with zero escaped to the heap. There it was worth it but it needs to be measured. So the performance should be compared with and without learning for short and for longer running applications. As another example sometimes the required capacities might not be learnable because they are almost random or depend on things that cannot be used as features in an efficient way.

Another drawback of using ML is that your code behaves less predictable. You won’t know what capacity will be estimated for a slice in advance anymore and it will be much harder to figure out why the program estimated exactly what it did afterwards.

I also thought about to train the model to reduce a mix of performance and required memory instead of using the final length as labels. But then it is not that easy anymore to get the training data. In some cases however it might also be difficult to get the “final” length of a slice as well.

The last thing to remember is that it is always helpful to set a learned model some borders. In this case a minimum and a maximum. My test model for example predicted a negative capacity before I got the hyperparameters right, what made my program crash. So if the model for some reason thinks this could be a great idea a fixed minimum of zero should prevent the worst. Also such borders make a program a bit more predictable again.