Bei statworx befassen wir uns intensiv damit, wie wir von großen Sprachmodellen (LLMs) die bestmöglichen Resultate erhalten. In diesem Blogbeitrag stelle ich fünf Ansätze vor, die sich sowohl in der Forschung als auch in unseren eigenen Experimenten mit LLMs bewährt haben. Während sich dieser Text auf das manuelle Design von Prompts zur Textgenerierung beschränkt, werden Bildgenerierung und automatisierte Promptsuche das Thema zukünftiger Beiträge sein.

Mega-Modelle läuten neues Paradigma ein

Die Ankunft des revolutionären Sprachmodells GPT-3 stellte nicht nur für das Forschungsfeld der Sprachmodellierung (NLP) einen Wendepunkt dar, sondern hat ganz nebenbei einen Paradigmenwechsel in der KI-Entwicklung eingeläutet: Prompt-Learning. Vor GPT-3 war der Standard das Fine-Tuning von mittelgroßen Sprachmodellen wie BERT, was dank erneutem Training mit eigenen Daten das vortrainierte Modell an den gewünschten Anwendungsfall anpassen sollte. Derartiges Fine-Tuning erfordert exemplarische Daten für die gewünschte Anwendung, sowie die rechnerischen Möglichkeiten das Modell zumindest teilweise neu zu trainieren.

Die neuen großen Sprachmodelle wie OpenAIs GPT-3 und BigSciences BLOOM hingegen wurden von ihren Entwicklerteams bereits mit derart großen Mengen an Ressourcen trainiert, dass diese Modelle ein neues Maß an Unabhängigkeit in ihrem Anwendungszweck erreicht haben: Diese LLMs benötigen nicht länger aufwändiges Fine-Tuning, um ihren spezifischen Zweck zu erlernen, sondern erzeugen bereits mithilfe von gezielter Instruktion („Prompt“) in natürlicher Sprache beeindruckende Resultate.

Wir befinden uns also inmitten einer Revolution in der KI-Entwicklung: Dank Prompt-Learning findet die Interaktion mit Modellen nicht länger über Code statt, sondern in natürlicher Sprache. Für die Demokratisierung der Sprachmodellierung bedeutet dies einen gigantischen Schritt vorwärts. Texte zu generieren oder neustens sogar Bilder zu erstellen, erfordert dadurch nicht mehr als rudimentäre Sprachkenntnisse. Allerdings heißt das nicht, dass damit auch überzeugende oder beeindruckende Resultate allen zugänglich sind. Hochwertige Outputs verlangen nach hochwertigen Inputs. Für uns Nutzer:innen bedeutet dies, dass die technische Planung in NLP nicht mehr der Modellarchitektur oder den Trainingsdaten gilt, sondern dem Design der Anweisungen, die Modelle in natürlicher Sprache erhalten. Willkommen im Zeitalter des Prompt-Engineerings.

Abbildung 1: Vom Prompt zur Prognose mit einem großen Sprachmodell

Prompts sind mehr als nur Textschnippsel

Templates erleichtern den häufigen Umgang mit Prompts

Da LLMs nicht auf einen spezifischen Anwendungsfall trainiert wurden, liegt es am Promptdesign dem Modell die genaue Aufgabenstellung zu bestimmen. Dazu dienen sogenannte „Prompt Templates“. Ein Template definiert die Struktur des Inputs, der an das Modell weitergereicht wird. Dadurch übernimmt das Template die Funktion des Fine-Tunings und legt den erwarteten Output des Modells für einen bestimmten Anwendungsfall fest. Am Beispiel einer einfachen Sentiment-Analyse könnte ein Prompt-Template so aussehen:

The expressed sentiment in text [X] is: [Z]

Das Modell sucht so nach einem Token z der, basierend auf den trainierten Parametern und dem Text in Position [X], die Wahrscheinlichkeit des maskierten Tokens an Position [Z] maximiert. Das Template legt so den gewünschten Kontext des zu lösenden Problems fest und definiert die Beziehung zwischen dem Input an Stelle [X] und dem zu vorhersagenden Output an Stelle [Z]. Der modulare Aufbau von Templates ermöglicht die systematische Verarbeitung einer Vielzahl von Texten für den erwünschten Anwendungsfall.

Abbildung 2: Prompt Templates definieren die Struktur eines Prompts.

Prompts benötigen nicht zwingend Beispiele

Das vorgestellte Template ist ein Beispiel eines sogenannten , da ausschließlich eine Anweisung, ohne jegliche Demonstration mit Beispielen im Template, vorhanden ist. Ursprünglich wurden LLMs von den Entwickler:innen von GPT-3 als „Few-Shot Learners“ bezeichnet, also Modelle, deren Leistung mit einer Auswahl von gelösten Beispielen des Problems maximiert werden kann (Brown et al., 2020). Eine Folgestudie konnte aber zeigen, dass mit strategischem Promptdesign auch 0-Shot Prompts, ohne einer Vielzahl von Beispielen, vergleichbare Leistung erzielen können (Reynolds & McDonell, 2021). Da also auch in der Forschung mit unterschiedlichen Ansätzen gearbeitet wird, stellt der nächste Abschnitt 5 Strategien für effektives Design von Prompt Templates vor.

5 Strategien für effektives Promptdesign

Task Demonstration

Im herkömmlichen Few-Shot Setting wird das zu lösende Problem durch die Bereitstellung von mehreren Beispielen eingegrenzt. Die gelösten Beispielsfälle sollen dabei eine ähnliche Funktion einnehmen wie die zusätzlichen Trainingssamples während des Fine-Tuning Prozesses und somit den spezifischen Anwendungsfall des Modells definieren. Textübersetzung ist ein gängiges Beispiel für diese Strategie, die mit folgendem Prompt Template repräsentiert werden kann:

French: „Il pleut à Paris“

German: „Es regnet in Paris“

French: „Copenhague est la capitale du Danemark“

German: „Kopenhagen ist die Hauptstadt von Dänemark“

[…]

French: [X]
German: [Z]

Die gelösten Beispiele sind zwar gut dazu geeignet das Problemsetting zu definieren, können aber auch für Probleme sorgen. „Semantische Kontamination“ bezeichnet das Problem, dass die Inhalte der übersetzten Sätze als relevant für die Vorhersage interpretiert werden können. Beispiele im semantischen Kontext der Aufgabe produzieren bessere Resultate – und solche außerhalb des Kontexts können dazu führen, dass die Prognose Z inhaltlich „kontaminiert“ wird (Reynolds & McDonell, 2021). Verwendet man das obige Template für die Übersetzung komplexer Sachverhalte, so könnte das Modell in unklaren Fällen wohl den eingegebenen Satz als Aussage über eine europäische Großstadt interpretieren.

Task Specification

Jüngste Forschung zeigt, dass mit gutem Promptdesign auch der 0-Shot Ansatz kompetitive Resultate liefern kann. So wurde demonstriert, dass LLMs gar keine vorgelösten Beispiele benötigen, solange die Problemstellung im Prompt möglichst genau definiert wird (Reynolds & McDonell, 2021). Diese Spezifikation kann unterschiedlich Formen annehmen, ihr liegt aber immer den gleichen Gedanken zugrunde: So genau wie möglich zu beschreiben was gelöst werden soll, aber ohne zu demonstriere wie.

Ein einfaches Beispiel für den Übersetzungsfall wäre folgender Prompt:

Translate from French to German [X]: [Z]

Dies mag bereits funktionieren, die Forscher empfehlen aber den Prompt so deskriptiv wie möglich zu gestalten und auch explizit die Übersetzungsqualität zu nennen:

A French sentence is provided: [X]. The masterful French translator flawlessly translates the sentence to German: [Z]

Dies helfe dem Modell dabei die gewünschte Problemlösung im Raum der gelernten Aufgaben zu lokalisieren.

Abbildung 3: Ein klarer Aufgabenbeschrieb kann die Prognosegüte stark erhöhen.

Auch in Anwendungsfällen ausserhalb von Übersetzungen ist dies empfehlenswert. Ein Text lässt mit einem einfachen Befehl zusammenfassen:

Summarize the following text: [X]: [Z]

Mit konkreterem Prompt sind aber bessere Resultate zu erwarten:

Rephrase this sentence with easy words so a child understands it,
emphasize practical applications and examples: [X]: [Z]

Je genauer der Prompt, desto grösser die Kontrolle über den Output.

Prompts als Einschränkungen

Zu Ende gedacht bedeutet der Ansatz von Kontrolle des Modells schlicht die Einschränkung des Modellverhaltens durch sorgfältiges Promptdesign. Diese Perspektive ist nützlich, denn während dem Training lernen LLMs viele verschiedene Texte fortzuschreiben und können dadurch eine breite Auswahl an Problemen lösen. Mit dieser Designstrategie verändert sich das grundlegende Herangehen ans Promptdesign: vom Beschrieb der Problemstellung zum Ausschluss unerwünschter Resultate durch die Einschränkung des Modellverhaltens. Welcher Prompt führt zum gewünschten Resultat und ausschliesslich zum gewünschten Resultat? Folgender Prompt weist zwar auf eine Übersetzungsaufgabe hin, beinhaltet aber darüber hinaus keine Ansätze zur Verhinderung, dass der Satz durch das Modell einfach zu einer Geschichte fortgesetzt wird.

Translate French to German Il pleut à Paris

Ein Ansatz diesen Prompt zu verbessern ist der Einsatz von sowohl semantischen als auch syntaktischen Mitteln:

Translate this French sentence to German: “Il pleut à Paris.”

Durch die Nutzung von syntaktischen Elementen wie dem Doppelpunkt und den Anführungszeichen wird klar gemacht, wo der zu übersetzende Satz beginnt und endet. Auch drückt die Spezifikation durch sentence aus, dass es nur um einen einzelnen Satz geht. Diese Mittel verringern die Wahrscheinlichkeit, dass dieser Prompt missverstanden und nicht als Übersetzungsproblem behandelt wird.

Nutzung von “memetic Proxies”

Diese Strategie kann genutzt werden, um die Informationsdichte in einem Prompt zu erhöhen und lange Beschreibungen durch kulturell verstandenen Kontext zu vermeiden. Memetic Proxies können in Taskbeschreibungen genutzt werden und nutzen implizit verständliche Situationen oder Personen anstelle von ausführlichen Anweisungen:

A primary school teacher rephrases the following sentence: [X]: [Z]

Dieser Prompt ist weniger deskriptiv als das vorherige Beispiel zur Umformulierung in einfachen Worten. Allerdings besitzt die beschriebene Situation eine viel höhere Dichte an Informationen: Die Nennung eines impliziert bereits, dass das Resultat für Kinder verständlich sein soll und erhöht dadurch hoffentlich auch die Wahrscheinlichkeit von praktischen Beispielen im Output. Ähnlich können Prompts fiktive Gespräche mit bekannten Persönlichkeiten beschreiben, so dass der Output deren Weltbild oder Sprechweise widerspiegelt:

In this conversation, Yoda responds to the following question: [X]

Yoda: [Z]

Dieser Ansatz hilft dabei einen Prompt durch implizit verstandenen Kontext kurz zu halten und die Informationsdichte im Prompt zu erhöhen.  Memetic Proxies finden auch im Promptdesign für andere Modalitäten Verwendung. Bei Modellen zur Bildgenerierung wie DALL-e 2 führt das Suffix „Trending on Artstation“ häufig zu Ergebnissen von höherer Qualität, obwohl semantisch eigentlich keine Aussagen über das darzustellende Bild gemacht werden.

Metaprompting

Als Metaprompting beschreibt das Forscherteam einer Studie den Ansatz Prompts durch Anweisungen anzureichern, die auf die jeweilige Aufgabe zugeschnitten sind. Dies beschreiben sie als Weg ein Modell durch klarere Anweisungen einzuschränken, sodass die gestellte Aufgabe besser gelöst werden kann (Reynolds & McDonell, 2021). Folgendes Beispiel kann dabei helfen mathematische Probleme zuverlässiger zu lösen und den Argumentationsweg nachvollziehbar zu machen:

[X]. Let us solve this problem step-by-step: [Z]

Ähnlich lassen sich Multiple Choice Fragen mit Metaprompts anreichern, sodass das Modell im Output auch tatsächlich eine Option wählt, anstatt die Liste fortzusetzen:

[X] in order to solve this problem, let us analyze each option and choose the best: [Z]

Metaprompts stellen somit ein weiteres Mittel dar Modellverhalten und Resultate einzuschränken.

Abbildung 4: Mithilfe von Metaprompts lassen sich Vorgehensweisen zur Problemlösung festlegen.

Ausblick

Prompt Learning ist ein noch sehr junges Paradigma und das damit eng verbundene Prompt Engineering befindet sich noch in den Kinderschuhen. Allerdings wird die Wichtigkeit von fundierten Fähigkeiten zum Schreiben von Prompts zweifellos nur noch zunehmen. Nicht nur Sprachmodelle wie GPT-3, sondern auch neuste Modelle zur Bildgenerierung verlangen von ihren User:innen solide Kenntnisse im Designen von Prompts, um gute Ergebnisse zu kreieren. Die vorgestellten Strategien sind sowohl in der Forschung als auch in der Praxis erprobte Ansätze zum systematischen Schreiben von Prompts, die dabei helfen, bessere Resultate von großen Sprachmodellen zu erhalten.

In einem zukünftigen Blogbeitrag nutzen wir diese Erfahrungen mit Textgenerierung, um Best Practices für eine weitere Kategorie generativer Modelle zu erschliessen: modernste Diffusionsmodelle zur Bildgenerierung, wie DALL-e 2, Midjourney und Stable Diffusion.

 

Quellen

Brown, Tom B. et al. 2020. “Language Models Are Few-Shot Learners.” arXiv:2005.14165 [cs]. http://arxiv.org/abs/2005.14165 (March 16, 2022).

Reynolds, Laria, and Kyle McDonell. 2021. “Prompt Programming for Large Language Models: Beyond the Few-Shot Paradigm.” http://arxiv.org/abs/2102.07350 (July 1, 2022).

Oliver Guggenbühl Oliver Guggenbühl Oliver Guggenbühl Oliver Guggenbühl

Im Trend: Künstliche Verbesserung von Gesichtsbildern

Was trägt künstliche Intelligenz dazu bei?

In den letzten Jahren sind Filter in den sozialen Medien extrem beliebt geworden. Mit diesen Filtern kann jede Person ihr Gesicht und die Umgebung auf unterschiedlichste Weise anpassen, was zu unterhaltsamen Ergebnissen führt. Oftmals verstärken die Filter aber auch Gesichtszüge, die einem bestimmten Schönheitsstandard zu entsprechen scheinen. Als KI-Expert:innen haben wir uns gefragt, was wir mit unseren Tools im Bereich der Gesichtsdarstellung erreichen können. Ein Thema, das unser Interesse geweckt hat, ist die Darstellung von Geschlechtern. Wir wurden neugierig: Wie stellt die KI bei der Erstellung dieser Bilder Geschlechterunterschiede dar? Und darüber hinaus: Können wir geschlechtsneutrale Versionen von bestehenden Gesichtern erzeugen?

Verwendung von StyleGAN auf bestehenden Bildern

Als wir darüber nachdachten, welche vorhandenen Bilder wir untersuchen wollten, haben wir uns überlegt: Wie würden unsere eigenen Gesichter bearbeitet aussehen? Außerdem beschlossen wir, auch mehrere Prominente als Input zu verwenden – wäre es nicht faszinierend, weltberühmte Gesichter dabei zu beobachten, wie sie sich in verschiedene Geschlechter verwandeln?

Gegenwärtig stehen textbasierte Bilderzeugungsmodelle wie DALL-E häufig im Mittelpunkt des öffentlichen Diskurses. Die KI-gesteuerte Erstellung fotorealistischer Gesichtsbilder ist jedoch schon seit langem ein Forschungsschwerpunkt, da es offensichtlich eine Herausforderung ist, natürlich aussehende Bilder von Gesichtern zu erzeugen. Auf der Suche nach geeigneten KI-Modellen für unsere Idee haben wir uns für die StyleGAN-Architekturen entschieden, die für die Erzeugung realistischer Gesichtsbilder bekannt sind.

Anpassung von Gesichtsmerkmalen mit StyleGAN

Ein entscheidender Aspekt der Architektur dieser KI ist die Verwendung eines so genannten latenten Raums, aus dem wir die Eingaben des neuronalen Netzes auswählen. Du kannst dir diesen latenten Raum wie eine Landkarte vorstellen, auf der jedes mögliche generierte Gesicht eine bestimmte Koordinate hat. Normalerweise würden wir einfach einen Dartpfeil auf diese Karte werfen und uns darüber freuen, dass die KI ein realistisches Bild erzeugt. Aber wie sich herausstellt, erlaubt uns dieser latente Raum, noch weitere Aspekte der Erzeugung künstlicher Gesichter zu untersuchen. Wenn Du dich von der Position eines Gesichts auf dieser Karte zur Position eines anderen Gesichts bewegst, kannst Du Mischungen der beiden Gesichter erzeugen. Und wenn Du dich in eine zufällige Richtung bewegst, wirst Du auch zufällige Veränderungen im generierten Bild sehen.
Dies macht die StyleGAN-Architektur zu einem vielversprechenden Ansatz für die Erforschung der Geschlechterdarstellung in der KI.

Können wir eine geschlechtsspezifische Richtung isolieren?

Gibt es also Wege, die es uns erlauben, bestimmte Aspekte des erzeugten Bildes zu verändern? Könnte man sich einer geschlechtsneutralen Darstellung eines Gesichts auf diese Weise nähern? In früheren Arbeiten wurden semantisch interessante Richtungen gefunden, die zu faszinierenden Ergebnissen führten. Eine dieser Richtungen kann ein generiertes Gesichtsbild so verändern, dass es ein weiblicheres oder männlicheres Aussehen erhält. Auf diese Weise können wir die Geschlechterdarstellung in Bildern untersuchen.

Der Ansatz, den wir für diesen Artikel gewählt haben, bestand darin, mehrere Bilder zu erstellen, indem wir kleine Schritte in die Richtung des jeweiligen Geschlechts machten. Auf diese Weise können wir verschiedene Versionen der Gesichter vergleichen, und die Leser:innen können zum Beispiel entscheiden, welches Bild einem geschlechtsneutralen Gesicht am nächsten kommt. Außerdem können wir so die Veränderungen genauer untersuchen und unerwünschte Merkmale in den bearbeiteten Versionen ausfindig machen.

Wir stellen der KI unsere eigenen Gesichter vor

Die beschriebene Methode kann verwendet werden, um jedes von der KI erzeugte Gesicht in eine weiblichere oder männlichere Version zu verändern. Es bleibt jedoch eine entscheidende Herausforderung: Da wir unsere eigenen Bilder als Ausgangspunkt verwenden möchten, müssen wir in der Lage sein, die latente Koordinate (in unserer Analogie den richtigen Ort auf der Landkarte) für ein gegebenes Gesichtsbild zu finden. Das hört sich zunächst einfach an, aber die verwendete StyleGAN-Architektur erlaubt uns nur den Weg in eine Richtung, nämlich von der latenten Koordinate zum generierten Bild, nicht jedoch den weg zurück. Glücklicherweise haben sich bereits Forschende mit genau diesem Problem beschäftigt. Unser Ansatz stützt sich daher stark auf das Python-Notebook, das hier zu finden ist. Die Forschenden haben eine weitere „Encoder“-KI entwickelt, die ein Gesichtsbild als Eingabe erhält und die entsprechende Koordinate im latenten Raum findet.

Somit haben wir endlich alle Teile, die wir brauchen, um unser Ziel zu erreichen: die Erforschung verschiedener Geschlechterdarstellungen innerhalb einer KI. In den Fotosequenzen unten ist das mittlere Bild jeweils das ursprüngliche Eingabebild. Auf der linken Seite erscheinen die generierten Gesichter eher weiblich, auf der rechten Seite eher männlich. Ohne weitere Umschweife präsentieren wir die von der KI generierten Bilder unseres Experiments.

Ergebnisse: Fotoserie von weiblich zu männlich

Abbildungen 1-6, v.o.: Marilyn Monroe, Schauspielerin; Drake, Sänger; Kim Kardashian, Unternehmerin & Reality-Star; Harry Styles, Sänger; Isabel Hermes, Co-Autorin dieses Artikels; Alexander Müller; Co-Autor dieses Artikels

Unbeabsichtigter Bias

Nachdem wir die entsprechenden Bilder im latenten Raum gefunden hatten, erzeugten wir künstliche Versionen der Gesichter. Wir haben sie dann auf Grundlage der gewählten Geschlechterrichtung verändert und so „feminisierte“ und „maskulinisierte“ Gesichter erzeugt. Die Ergebnisse zeigen ein unerwartetes Verhalten der KI: Sie scheint klassische Geschlechterstereotypen nachzubilden.

Breites Lächeln vs. dicke Augenbrauen

Sobald wir ein Bild so bearbeitet haben, dass es weiblicher aussieht, sehen wir allmählich einen sich öffnenden Mund mit einem stärkeren Lächeln und umgekehrt. Zudem werden die Augen in der weiblichen Richtung größer und weiter geöffnet. Die Beispiele von Drake und Kim Kardashian veranschaulichen eine sichtbare Veränderung des Hauttons von dunkler zu heller, wenn man sich entlang der Bildreihe von feminin zu maskulin bewegt. Die gewählte Geschlechterrichtung scheint die Locken in der weiblichen Richtung (im Gegensatz zur männlichen Richtung) zu entfernen, wie die Beispiele von Marylin Monroe und der Co-Autorin dieses Artikels, Isabel Hermes, zeigen.

Wir haben uns auch gefragt, ob eine drastischere Haarverlängerung in Drakes weiblicher Richtung eintreten würde, wenn wir seine Fotoserie nach links erweitern würden. Betrachtet man die allgemeinen Extreme, so sind die Augenbrauen auf der weiblichen Seite ausgedünnt und gewölbt und auf der männlichen Seite gerader und dicker. Augen- und Lippen-Make-up nehmen bei Gesichtern, die sich in die weibliche Richtung bewegen, stark zu, wodurch der Bereich um die Augen dunkler wird und die Augenbrauen dünner werden. Dies könnte der Grund dafür sein, dass wir die von uns erstellten männlichen Versionen als natürlicher empfunden haben als die weiblichen Versionen.

Abschließend möchten wir dich auffordern, die obige Fotoserie genau zu betrachten. Versuche zu entscheiden, welches Bild Du als geschlechtsneutral empfindest, d. h. als ebenso männlich wie weiblich. Warum hast Du dich für dieses Bild entschieden? Hat eines der oben beschriebenen stereotypen Merkmale Deine Wahrnehmung beeinflusst?
Eine Frage, die sich bei Bildserien wie diesen natürlich stellt, ist, ob die Gefahr besteht, dass die KI gängige Geschlechterstereotypen verstärkt.

Ist die KI schuld an der Rekonstruktion von Stereotypen?

Angesichts der Tatsache, dass die angepassten Bilder bestimmte geschlechtsspezifische Stereotypen wiedergeben, wie z. B. ein ausgeprägteres Lächeln bei weiblichen Bildern, könnte eine mögliche Schlussfolgerung sein, dass der Trainingsdatensatz der KI einen Bias aufgewiesen hat. Und in der Tat wurden für das Training des zugrunde liegenden StyleGAN Bilddaten von Flickr verwendet, die die Verzerrungen von der Website übernehmen. Das Hauptziel dieses Trainings war es jedoch, realistische Bilder von Gesichtern zu erstellen. Und obwohl die Ergebnisse vielleicht nicht immer so aussehen, wie wir es erwarten oder wünschen, würden wir behaupten, dass die KI genau das in allen unseren Tests erreicht hat.

Um die Bilder zu verändern, haben wir jedoch die zuvor erwähnte latente Richtung verwendet. Im Allgemeinen ändern diese latenten Richtungen selten nur einen einzigen Aspekt des erzeugten Bildes. Stattdessen werden, wie beim Bewegen in eine zufällige Richtung auf unserer latenten Landkarte, normalerweise viele Elemente des erzeugten Gesichts gleichzeitig verändert. Die Identifizierung einer Richtung, die nur einen einzigen Aspekt eines generierten Bildes verändert, ist alles andere als trivial. Für unser Experiment wurde die gewählte Richtung in erster Linie zu Forschungszwecken erstellt, ohne die genannten Verzerrungen zu berücksichtigen. Sie kann daher neben den beabsichtigten Veränderungen auch unerwünschte Artefakte in die Bilder einbringen. Dennoch kann angenommen werden, dass eine latente Richtung existiert, die es uns ermöglicht, das Geschlecht eines vom StyleGAN erzeugten Gesichts zu verändern, ohne andere Gesichtsmerkmale zu beeinträchtigen.

Insgesamt verwenden die Implementierungen, auf denen wir aufbauen, unterschiedliche KI und Datensätze, und das komplexe Zusammenspiel dieser Systeme erlaubt es uns daher nicht, die KI als einzige Ursache für diese Probleme zu identifizieren. Nichtsdestotrotz legen unsere Beobachtungen nahe, dass es von größter Wichtigkeit ist, bei der Erstellung von Datensätzen die nötige Sorgfalt walten zu lassen, um die Repräsentation verschiedener ethnischer Hintergründe sicherzustellen und Verzerrungen zu vermeiden.

Abb. 7: Beispielbild aus der Studie „A Sex Difference in Facial Contrast and its Exaggeration by Cosmetics“ von Richard Russel

Unbewusste Voreingenommenheit: Blick auf uns selbst

Eine Studie von Richard Russel befasst sich mit der menschlichen Wahrnehmung des Geschlechts in Gesichtern. Welchem Geschlecht würdest Du die beiden Bilder oben intuitiv zuordnen? Es zeigt sich, dass die meisten Menschen die linke Person als männlich und die rechte Person als weiblich wahrnehmen. Schau noch einmal hin. Was unterscheidet die Gesichter? Es gibt keinen Unterschied in der Gesichtsstruktur: Nur die dunkleren Augen- und Mundpartien unterscheiden sich. So wird deutlich, dass ein erhöhter Kontrast ausreicht, um unsere Wahrnehmung zu beeinflussen. Nehmen wir an, unsere Meinung über das Geschlecht kann durch das Auftragen von „Kosmetika“ auf ein Gesicht beeinflusst werden. In diesem Fall müssten wir unser menschliches Verständnis von Geschlechterdarstellungen in Frage stellen und uns damit befassen, ob sie nicht einfach das Produkt unserer lebenslangen Exposition gegenüber stereotypen Bildern sind. Der Studienautor bezeichnet dies als „Illusion des Geschlechts“.
Diese Verzerrung bezieht sich auf die Auswahl der latenten „Geschlechts“-Dimension: Um die latente Dimension zu finden, die das wahrgenommene Geschlecht eines Gesichts verändert, wurden die von StyleGAN generierten Bilder nach ihrem Aussehen in Gruppen eingeteilt. Obwohl dies auf der Grundlage einer anderen KI implementiert wurde, könnte sich die menschliche Voreingenommenheit bei der Geschlechterwahrnehmung durchaus auf diesen Prozess ausgewirkt haben und zu den oben dargestellten Bildreihen durchgesickert sein.

Schluss

Die Geschlechtertrennung überwinden mit StyleGANs

Auch wenn ein StyleGAN an und für sich keine geschlechtsspezifischen Vorurteile verstärkt, so sind Menschen doch unbewusst mit Geschlechterstereotypen behaftet. Geschlechtsspezifische Vorurteile beschränken sich nicht nur auf Bilder – Forscher:innen fanden die Allgegenwart weiblicher Sprachassistenten Grund genug, einen neuen Sprachassistenten zu entwickeln, der weder männlich noch weiblich ist: GenderLess Voice.

Ein Beispiel für einen neueren gesellschaftlichen Wandel ist die Debatte über das Geschlecht, das nicht mehr binär, sondern als Spektrum dargestellt werden kann. Die Idee ist, dass es ein biologisches Geschlecht und ein soziales Geschlecht gibt. Für eine Person, die sich mit einem Geschlecht identifiziert, das sich von dem unterscheidet, mit dem sie geboren wurde, ist es wichtig, in die Gesellschaft aufgenommen zu werden, so wie sie ist.
Eine Frage, die wir als Gesellschaft im Auge behalten müssen, ist, ob der Bereich der KI Gefahr läuft, Menschen jenseits der zugewiesenen binären Geschlechterordnung zu diskriminieren. Tatsache ist, dass in der KI-Forschung das Geschlecht oft binär dargestellt wird. Bilder, die in Algorithmen eingespeist werden, um diese zu trainieren, werden entweder als männlich oder weiblich gekennzeichnet. Geschlechtserkennungssysteme, die auf einer deterministischen Geschlechtszuordnung basieren, können auch direkten Schaden anrichten, indem sie Mitglieder der LGBTQIA+-Gemeinschaft falsch kennzeichnen. Derzeit müssen in der ML-Forschung noch weitere Geschlechtsbezeichnungen berücksichtigt werden. Anstatt das Geschlecht als binäre Variable darzustellen, könnte es als Spektrum kodiert werden.

Erforschung der Geschlechterdarstellung von Frauen und Männern

Wir haben StyleGAN angewandt, um zu untersuchen, wie KI Geschlechterunterschiede darstellt. Konkret haben wir eine Geschlechterrichtung im latenten Raum verwendet. Forscher:innen haben diese Richtung vorher bestimmt, um das männliche und weibliche Geschlecht darzustellen. Wir haben gesehen, dass die generierten Bilder gängige Geschlechterstereotypen wiedergaben – Frauen lächeln mehr, haben größere Augen, längeres Haar und tragen viel Make-up – konnten aber nicht feststellen, dass das StyleGAN-Modell allein diese Verzerrung verbreitet. Erstens wurden die StyleGANs in erster Linie entwickelt, um fotorealistische Gesichtsbilder zu erzeugen und nicht, um die Gesichtszüge vorhandener Fotos nach Belieben zu verändern. Zweitens: Da die von uns verwendete latente Richtung ohne Korrektur für Verzerrungen in den StyleGAN-Trainingsdaten erstellt wurde, sehen wir eine Korrelation zwischen stereotypen Merkmalen und Geschlecht.

Nächste Schritte und Geschlechtsneutralität

Auch haben wir uns gefragt, welche Gesichter wir in den von uns generierten Bildsequenzen als geschlechtsneutral wahrnehmen. Bei Originalbildern von Männern mussten wir in die künstlich erzeugte weibliche Richtung schauen und umgekehrt. Dies war eine subjektive Entscheidung. Wir sehen es als logischen nächsten Schritt an, zu versuchen, die Generierung von geschlechtsneutralen Versionen von Gesichtsbildern zu automatisieren, um die Möglichkeiten der KI im Bereich Geschlecht und Gesellschaft weiter zu erforschen. Dazu müssten wir zunächst das Geschlecht des zu bearbeitenden Gesichts klassifizieren und uns dann bis zu dem Punkt, an dem der Klassifikator keine eindeutige Zuordnung mehr vornehmen kann, dem anderen Geschlecht annähern. Daher können interessierte Leserinnen und Leser die Fortsetzung unserer Reise in einem zweiten Blogartikel in nächster Zeit verfolgen.

Wenn Du dich für unsere technische Umsetzung dieses Artikels interessierst, kannst Du den Code hier finden und ihn mit deinen eigenen Bildern ausprobieren.

Quellen

Bildnachweise
Abb. 1: © Alfred Eisenstaedt / Life Picture Collection
Abb. 2: https://www.pinterest.com/pin/289989663476162265/
Abb. 3: https://www.gala.de/stars/starportraets/kim-kardashian-20479282.html
Abb. 4: © Charles Sykes / Picture Alliance
Abb. 7: Richard Russel, „A Sex Difference in Facial Contrast and its Exaggeration by Cosmetics“ Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller Isabel Hermes, Alexander Müller

Bei all dem Hype um KI in den letzten Jahren darf man nicht außer Acht lassen, dass ein Großteil der Unternehmen bei der erfolgreichen Implementierung von KI-basierten Anwendungen noch hinterherhinken. Dies ist gerade in vielen Industrien, wie z.B. in produzierenden Gewerben, recht offensichtlich (McKinsey).

Eine von Accenture 2019 durchgeführte Studie zum Thema Implementierung von KI in Unternehmungen zeigt, dass über 80% aller Proof of Concepts (PoCs) es nicht in Produktion schaffen. Außerdem gaben nur 5% aller befragten Unternehmen an, eine unternehmensweite KI-Strategie implementiert zu haben.

Diese Erkenntnisse regen zum Nachdenken an: Was genau läuft schief und warum schafft künstliche Intelligenz anscheinend noch nicht die ganzheitliche Transition von erfolgreichen, akademischen Studien zu der realen Welt?

1. Was ist data-centric AI?

„Data-centric AI is the discipline of systematically engineering the data used to build an AI system.“
Zitat von Andrew Ng, data-centric AI Pionier

Der data-centric Ansatz fokussiert sich auf eine stärkere Daten-integrierenden KI (data-first) und weniger auf eine Konzentration auf Modelle (model-first), um die Schwierigkeiten von KI mit der „Realität“ zu bewältigen. Denn, die Trainingsdaten, die meist bei Unternehmen als Ausgangspunkt eines KI-Projekts stehen, haben relativ wenig gemeinsam mit den akribisch kurierten und weit verbreiteten Benchmark Datensets wie MNIST oder ImageNet.

Das Ziel dieses Artikels ist, data-centric im KI-Workflow und Projektkontext einzuordnen, Theorien sowie relevante Frameworks vorzustellen und aufzuzeigen, wie wir bei statworx eine data-first KI-Implementierung angehen.

2. Welche Gedankengänge stecken hinter data-centric?

Vereinfacht dargestellt bestehen KI-Systeme aus zwei entscheidenden Komponenten: Daten und Modell(-Code). Data-centric fokussiert sich mehr auf die Daten, model-centric auf das Modell – duh!

Bei einer stark model-centric lastigen KI werden Daten als ein extrinsischer, statischer Parameter behandelt. Der iterative Prozess eines Data Science Projekts startet praktisch erst nach dem Erhalt der Daten bei den Modell-spezifischen Schritten, wie Feature Engineering, aber vor allem exzessives Trainieren und Fine tunen verschiedener Modellarchitekturen. Dies macht meist das Gros der Zeit aus, das Data Scientists an einem Projekt aufwenden. Kleinere Daten-Aufbereitungsschritte werden meist nur einmalig, ad-hoc am Anfang eines Projekts angegangen.

Model Centric Grafik

Im Gegensatz dazu versucht data-centric (automatisierte) Datenprozesse als zentralen Teil jedes ML Projekts zu etablieren. Hierunter fallen alle Schritte die ausgehend von den Rohdaten nötig sind, um ein fertiges Trainingsset zu generieren. Durch diese Internalisierung soll eine methodische Überwachbarkeit für verbesserte Qualität sorgen.

Data Centric Grafik

Man kann dabei data-centric Überlegungen in drei übergeordnete Kategorien zusammenfassen. Diese beschreiben lose, welche Aufgabenbereiche bei einem data-centric Ansatz bedacht werden sollten. Im Folgenden wurde versucht, diese bekannte Buzzwords, die im Kontext von data-centric immer wieder auftauchen, thematisch einer Kategorie zuzuordnen.

2.1. Integration von SMEs in den Development Prozess als wichtiges Bindeglied zwischen Data- und Model-Knowledge.

Die Einbindung von Domain Knowledge ist ein integraler Bestandteil von data-centric. Dies hilft Projektteams besser zusammenwachsen zu lassen und so das Wissen der Expert:innen, auch Subject Matter Experts (SMEs) genannt, bestmöglich im KI-Prozess zu integrieren.

  • Data Profiling:
    Data Scientists sollten nicht als Alleinkämpfer:innen die Daten analysieren und nur ihre Befunde mit den SMEs teilen. Data Scientists können ihre statistischen und programmatischen Fähigkeiten gezielt einsetzen, um SMEs zu befähigen, die Daten eigenständig zu untersuchen und auszuwerten.
  • Human-in-the-loop Daten & Model Monitoring:
    Ähnlich wie beim Profiling soll hierbei durch das Bereitstellen eines Einstiegpunktes gewährleistet werden, das SMEs Zugang zu den relevanten Komponenten des KI-Systems erhalten. Von diesem zentralen Checkpoint können nicht nur Daten sondern auch Modell-relevante Metriken überwacht werden oder Beispiele visualisiert und gecheckt werden. Gleichzeit gewährt ein umfängliches Monitoring die Möglichkeit, nicht nur Fehler zu erkennen, sondern auch die Ursachen zu untersuchen und das möglichst ohne notwendige Programmierkenntnisse.

2.2. Datenqualitätsmanagement als agiler, automatisierter und iterativer Prozess über (Trainings-)Daten

Die Datenaufbereitung wird als Prozess verstanden, dessen kontinuierliche Verbesserung im Vordergrund eines Data Science Projekts stehen sollte. Das Modell, anders als bisher, sollte hingegen erstmal als (relativ) fixer Parameter behandelt werden.

  • Data Catalogue, Lineage & Validation:
    Die Dokumentation der Daten sollte ebenfalls keine extrinsische Aufgabe sein, die oft nur gegen Ende eines Projekts ad-hoc entsteht und bei jeder Änderung, z.B. eines Modellfeatures, wieder obsolet sein könnte. Änderungen sollen dynamisch reflektiert werden und so die Dokumentation automatisieren. Data Catalogue Frameworks bieten hier die Möglichkeit, Datensätze mit Meta-Informationen anzureichern.
    Data Lineage soll im Weiteren dabei unterstützen, bei diversen Inputdaten, verschiedenen Transformations- und Konsolidierungsschritten zwischen roh- und finalem Datenlayer den Überblick zu behalten. Je komplexer ein Datenmodell, desto eher kann ein Lineage Graph Auskunft über das Entstehen der finalen Spalten geben (Grafik unten), beispielsweise ob und wie Filterungen oder bestimmte join Logiken benutzt wurden. Die Validierung (neuer) Daten hilft schließlich eine konsistente Datengrundlage zu gewährleisten. Hier helfen die Kenntnisse aus dem Data Profiling um Validierungsregeln auszuarbeiten und im Prozess zu integrieren.

Lineage Graph

  • Data & Label Cleaning:
    Die Notwendigkeit der Datenaufbereitung ist selbsterklärend und als Best Practice ein fester Bestandteil in jedem KI-Projekt. Eine Label-Aufbereitung ist zwar nur bei Klassifikations-Algorithmen relevant, wird aber hier selten als wichtiger pre-processing Schritt mitbedacht. Aufbereitungen können aber mit Hilfe von Machine Learning automatisiert werden. Falsche Labels können es nämlich für Modelle erschweren, exakte patterns zu erlernen.
    Auch sollte man sich bewusst machen, dass solange sich die Trainingsdaten ändern, die Datenaufbereitung kein vollkommen abgeschlossener Prozess sein kann. Neue Daten bedeuten oft auch neue Cleaning-Schritte.
  • Data Drifts in Produktion:
    Eine weit verbreitete Schwachstelle von KI-Applikationen tritt meist dann auf, wenn sich Daten nicht so präsentieren, wie es beim Trainieren der Fall war, beispielweise im Zeitverlauf ändern (Data Drifts). Um die Güte von ML Modellen auch langfristig zu gewährleisten, müssen Daten in Produktion kontinuierlich überwacht werden. Hierdurch können Data Drifts frühzeitig ausfindig gemacht werden, um dann Modelle neu auszurichten, wenn z.B. bestimmte Inputvariablen von ihrer ursprünglichen Verteilung zu stark abweichen.
  • Data Versioning:
    GitHub ist seit Jahren der go to Standard für Code Versionierungen, um mehr Übersicht und Kontrolle zwischen Codeständen zu haben. Aber auch Daten können versioniert werden und so eine ganzheitliche Prozesskontrolle bieten. Ebenfalls können so Code- mit Datenständen verknüpft werden. Dies sorgt nicht nur für bessere Überwachbarkeit, sondern hilft auch dabei, automatisierte Prozesse anzustoßen.

Data/Code Versionierung Grafik

2.3. Generieren von Trainingsdatensätzen als programmatischer Task.

Gerade das Erzeugen von (gelabelten) Trainingsdaten ist einer der größten Roadblocker für viele KI-Projekte. Gerade bei komplexen Problemen, die große Datensätze benötigen, ist der initiale, manuelle Aufwand enorm.

  • Data Augmentation:
    Bei vielen datenintensiven Deep Learning Modellen wird diese Technik schon seit längerem eingesetzt, um mit bestehenden Daten, artifizielle Daten zu erzeugen. Bei Bilddaten ist dies recht anschaulich erklärbar. Hier werden beispielsweise durch Drehen eines Bildes verschiedene Perspektiven desselben Objektes erzeugt. Aber auch bei NLP und bei „tabularen“ Daten (Excel und Co.) gibt es Möglichkeiten neue Datenpunkte zu erzeugen.

Data Augmentation Grafik

  • Automated Data Labeling:
    Normalerweise ist Labeling ein sehr arbeitsintensiver Schritt, in dem Menschen Datenpunkte einer vordefinierten Kategorie zuordnen. Einerseits ist dadurch der initiale Aufwand (Kosten) sehr hoch, andererseits fehleranfällig und schwierig zu überwachen. Hier kann ML durch Konzepte wie semi- oder weak supervison Automatisierungshilfe leisten, was den manuellen Aufwand erheblich reduziert.
  • Data Selection:
    Arbeiten mit großen Datensätzen sind im lokalen Trainingskontext schwierig zu handhaben. Gerade dann, wenn diese nicht mehr in den Arbeitsspeicher des Laptops passen. Und selbst wenn, dann dauern Trainingsläufe meist sehr lange. Data Selection versucht die Größe durch ein aktives Subsampling (ob gelabelt oder ungelabelt) zu reduzieren. Aktiv werden hier die „besten“ Beispiele mit der höchsten Vielfalt und Repräsentativität ausgewählt, um die bestmögliche Charakterisierung des Inputs zu gewährleisten – und das automatisiert.

Selbstverständlich ist es nicht in jedem KI-Projekt sinnvoll, alle aufgeführten Frameworks zu bedenken. Es ist Aufgabe eines jedes Development Teams, die nötigen Tools und Schritte im data-centric Kontext zu analysieren und auf Relevanz und Übertragbarkeit zu prüfen. Hier spielen neben datenseitigen Überlegungen auch Business Faktoren eine Hauptrolle, da neue Tools meist auch mehr Projektkomplexität bedeuten.

3. Integration von data-centric bei statworx

Data-centric Überlegungen spielen bei unseren Projekten gerade in der Übergangsphase zwischen PoC und Produktivstellen des Modells vermehrt eine führende Rolle. Denn auch in einigen unserer Projekte ist es schon vorgekommen, dass man nach erfolgreichem PoC mit verschiedenen datenspezifischen Problemen zu kämpfen hatte; meist hervorgerufen durch unzureichende Dokumentation und Validierung der Inputdaten oder ungenügende Integration von SMEs im Datenprozess und Profiling.

Generell versuchen wir daher unseren Kunden die Wichtigkeit des Datenmanagements für die Langlebigkeit und Robustheit von KI-Produkten in Produktion aufzuzeigen und wie hilfreiche Komponenten innerhalb einer KI-Pipeline verknüpft sind.

Gerade unser Data Onboarding – ein Mix aus Profiling, Catalogue, Lineage und Validation, integriert in ein Orchestrations-Framework – ermöglicht uns mit den oben genannten Problemen besser umzugehen und so hochwertigere KI-Produkte bei unseren Kunden zu integrieren.

Zusätzlich hilft dieses Framework dem ganzen Unternehmen, bisher ungenutzte, undokumentierte Datenquellen für verschiedene Use Cases (nicht nur KI) verfügbar zu machen. Dabei ist die enge Zusammenarbeit mit den SMEs auf Kundenseite essenziell, um so effektive und robuste Datenqualitäts-Checks zu implementieren. Die resultierenden Datentöpfe und -prozesse sind somit gut verstanden, sodass Validierungs-Errors vom Kunden verstanden und behoben werden können, was so zu einem langlebigen Einsatz des Service beiträgt.

Data & AI Pipeline von statworx Grafik

In einer abgespeckten, kundenspezifischen Data Onboarding Integration haben wir mit Hilfe verschiedener Open und Closed Source Tools eine für den Kunden einfach skalierbare und leicht verständliche Plattform geschaffen.

So haben wir beispielsweise Validationchecks mit Great Expectations (GE), einem Open Source Framework, umgesetzt. Dieses Tool bietet neben Python-basierter Integration diverser Tests auch eine Reporting Oberfläche, die nach jedem Durchlauf einen einfach verständlichen Einstiegspunkt in die Resultate bietet.

Data Validation Grafik

Diese Architektur kann dann in verschiedenen Kontexten laufen, ob in der Cloud, mit einem Closed Source Software wie Azure Data Factory oder on premises mit Open Source Tools wie Airflow – und kann um weitere Tools jederzeit ergänzt werden.

4. Data-centric im Status Quo von KI

Sowohl model- als auch data-centric beschreiben Handlungsansätze, wie man an ein KI-Projekt herangehen kann.

Model-centric ist in den letzten Jahren recht erwachsen geworden und es haben sich dadurch einige Best Practices in verschiedenen Bereichen entwickelt, auf denen viele Frameworks aufbauen.

Dies hat auch damit zu tun, dass in der akademischen Welt der Fokus sehr stark auf Modellarchitekturen und deren Weiterentwicklung lag (und noch liegt) und diese stark mit führenden KI-Unternehmen korreliert. Gerade im Bereich Computer Vision und Natural Langue Processing konnten kommerzialisierte Meta-Modelle, trainiert auf gigantischen Datensets, die Tür zu erfolgreichen KI Use Cases öffnen. Diese riesigen Modelle können auf kleineren Datenmengen für Endanwendungen gefinetuned werden, bekannt unter Transfer Learning.

Diese Entwicklung hilft allerdings nur einem Teil der gescheiterten Projekte, da gerade im Kontext von industriellen Projekten fehlende Kompatibilität oder Starrheit der Use Cases die Anwendungen von Meta-Modellen erschwert. Die Nicht-Starrheit findet sich häufig in maschinenlastigen Produktionsindustrien, wo sich das Umfeld, in dem Daten produziert werden, stetig ändert und sogar der Austausch einer einzelnen Maschine große Auswirkungen auf ein produktives KI-Modell haben kann. Wenn diese Problematik nicht richtig im KI-Prozess bedacht wurde, entsteht hier ein schwer kalkulierbares Risiko, auch bekannt unter Technical Debt [Quelle: https://proceedings.neurips.cc/paper/2015/file/86df7dcfd896fcaf2674f757a2463eba-Paper.pdf].

Zu guter Letzt stellen die Distributionen bei einigen Use Cases ein inhärentes Problem für ML dar. Modelle haben grundsätzlich Schwierigkeiten mit edge cases, sehr seltene und ungewöhnliche Beobachtungspunkte (die long tails [Quelle: https://medium.com/codex/machine-learning-the-long-tail-paradox-1cc647d4ba4b] einer Verteilung). Beispielweise ist es nicht ungewöhnlich, dass bei Fault Detection das Verhältnis von fehlerhaften zu einwandfreien Bauteilen eins zu mehreren Tausend beträgt. Die Abstraktionsfähigkeit bei ungesehenen, abseits der Norm liegenden Fehlern ist hier meist schlecht.

5. Schluss – Paradigmenwechsel in Sicht?

Diese Probleme zu bewältigen, ist zwar Teil des Versprechens von data-centric, aber präsentiert sich im Moment noch eher unausgereift.

Das lässt sich auch an der Verfügbarkeit und Maturität von Open Source Frameworks darlegen. Zwar gibt es schon vereinzelte, produktionsfertige Anwendungen, aber keine, die die verschiedenen Teilbereiche von data-centric zu vereinheitlichen versucht. Dies führt unweigerlich zu längeren, aufwendigeren und komplexeren KI-Projekten, was für viele Unternehmen eine erhebliche Hürde darstellt. Außerdem sind kaum Datenmetriken vorhanden, die Unternehmen ein Feedback geben, was sie denn genau gerade „verbessern“. Und zweitens, viele der Tools (bsp. Data Catalogue) haben einen eher indirekten, verteilten Nutzen.

Einige Start-ups, die diese Probleme angehen wollen, sind in den letzten Jahren entstanden. Dadurch, dass diese aber (ausschließlich) paid tier Software vermarkten, ist es eher undurchsichtig, inwiefern diese Produkte wirklich die breite Masse an Problemen von verschiedenen Use Cases abdecken können.

Obwohl die Aufführungen oben zeigen, dass Unternehmen generell noch weit entfernt sind von einer ganzheitlichen Integration von data-centric, wurden robuste Daten Strategien in der letzten Zeit immer wichtiger (wie wir bei statworx an unseren Projekten sehen konnten).

Mit vermehrtem akademischem Research in Daten Produkte wird sich dieser Trend sicherlich noch verstärken. Nicht nur weil dadurch neue, robustere Frameworks entstehen, sondern auch weil durch Uni-Absolvent:innen den Unternehmen mehr Wissen in diesem Gebiet zufließt.

Bild-Quellen:

Model-centric arch: eigene
Data-centric arch: eigene
Data lineage: https://www.researchgate.net/figure/Data-lineage-visualization-example-in-DW-environment-using-Sankey-diagram_fig7_329364764
Historisierung Code/Data: https://ardigen.com/7155/
Data Augmentation: https://medium.com/secure-and-private-ai-writing-challenge/data-augmentation-increases-accuracy-of-your-model-but-how-aa1913468722
Data & AI pipeline: eigene
Validieren mit GE: https://greatexpectations.io/blog/ge-data-warehouse/

 

Benedikt Müller Benedikt Müller Benedikt Müller Benedikt Müller Benedikt Müller Benedikt Müller Benedikt Müller Benedikt Müller

Heute feiern wir den jährlichen Christopher Street Day – das europäische Äquivalent zu Gay Pride oder Pride Parades, um für die Rechte von LGBTQIA+ Menschen und gegen Diskriminierung und Ausgrenzung zu kämpfen.

Seit 1969, als die erste Demonstration auf der Christopher Street in New York City stattfand, haben wir bereits viele Fortschritte gemacht: Heute ist die gleichgeschlechtliche Ehe in 30 Ländern rechtlich vollzogen und anerkannt, und das „unbestimmte“ Geschlecht ist in 20 Ländern rechtlich anerkannt.

Allerdings steht Homosexualität in vielen Ländern immer noch unter Strafe und selbst in fortschrittlicheren Ländern kommt es immer noch zu Gewalt gegen queere Menschen. Trotz der bereits erzielten Fortschritte ist es also noch ein weiter Weg bis zur Gleichstellung queerer Menschen. Der Christopher Street Day hat also nach wie vor seine Berechtigung: Als Protest gegen Ungerechtigkeit und als Zeichen für eine bunte, vielfältige und tolerante Gesellschaft.

Vorurteile in der KI – Ein sehr reales Problem

In den letzten Jahren haben die Themen Diskriminierung und Vorurteile noch an Relevanz gewonnen, denn mit der Digitalisierung schleichen sich diese Vorurteile auch in die Schlüsseltechnologie unserer Zukunft ein: Künstliche Intelligenz. Intelligente Computersysteme, die aus Daten lernen und unsere Gesellschaft verändern werden, wie wir es noch nie erlebt haben. Es ist von entscheidender Bedeutung, dass sie mit unterschiedlichen Datensätzen und unter Mitwirkung einer Vielzahl von Entwickler:innen programmiert werden. Andernfalls besteht die Gefahr, dass sie voreingenommene und diskriminierende KI-Systeme entwickeln.

Die Kontroverse um die Veröffentlichung von Googles Chatbot „Allo“ ist ein Paradebeispiel für diese potenzielle Falle. Google veröffentlichte Allo, seine neue Messaging-App, im Jahr 2016 mit großem Tamtam. Die App enthielt einen Chatbot namens „Smart Reply“, der auf der Grundlage früherer Interaktionen Antworten auf Nachrichten vorschlägt. Es stellte sich jedoch schnell heraus, dass der Bot gegenüber Frauen voreingenommen war und dazu neigte, abfällige und sexuell eindeutige Antworten auf Nachrichten von Nutzerinnen vorzuschlagen. Dieser Vorfall unterstreicht die Notwendigkeit für Unternehmen, bei der Entwicklung von KI stärker auf die potenziellen Risiken von Voreingenommenheit zu achten. Diversität muss in jeder Phase des Prozesses berücksichtigt werden, von der Datenerfassung über die Entwicklung von Algorithmen bis hin zu Nutzertests.

In der Tat gab es viele weitere Vorfälle von KI-Diskriminierung gegenüber Frauen und People of Color, wie z. B. Amazons Rekrutierungstool, das systematisch männliche Bewerber bevorzugte, oder Facebooks Kennzeichnungssystem für Bilder, das einen dunkelhäutigen Mann fälschlicherweise als Primaten identifizierte. Aber nicht nur Frauen und People of Color leiden unter Vorurteilen in der KI, auch die queere Community ist davon betroffen.

Case Study: DALL-E 2

Werfen wir dazu einen Blick auf DALL-E 2, das von OpenAI entwickelt wurde. Es ist eine der neuesten und bahnbrechendsten KI-Technologien, die es gibt. DALL-E 2 ist eine KI, die auf der Grundlage von Textbeschreibungen realistische Bilder und Kunstwerke erzeugt.

Um zu prüfen, wie voreingenommen oder gleichberechtigt diese KI-Lösung gegenüber queeren Menschen ist, habe ich DALL-E 2 angewiesen, Bilder auf der Grundlage des Eingabetextes „ein glückliches Paar“ mit verschiedenen Kunststilanweisungen (z. B. Ölgemälde oder digitale Kunst) zu erzeugen.

Wenn Ihr Euch die Ergebnisse anseht, seht Ihr, dass nur Bilder von heterosexuellen Paaren erzeugt wurden. Auch die Bilder, die auf dem Text „eine glückliche Familie“ basieren, unterscheiden sich in dieser Hinsicht nicht – es sind keine gleichgeschlechtlichen Eltern auf den Bildern zu sehen.

Um also ein Bild eines homosexuellen Paares zu erhalten, versuche ich, dem KI-Modell eine spezifischere Beschreibung zu geben: „ein glückliches queeres Paar“. Wie Ihr sehen könnt, hat DALL-E 2 schließlich einige Bilder von gleichgeschlechtlichen Paaren erzeugt. Aber auch hier scheint das System voreingenommen zu sein – es wurde kein einziges Bild eines lesbischen Paares erzeugt.

Die Ursachen der Diskriminierung bei Technologien wie DALL-E 2

Haben wir jetzt also die Bestätigung, dass KI homophob ist? Nicht so ganz. Es geht hier nicht um Homophobie oder Sexismus auf Seiten von DALL-E oder GPT-3. Diese Systeme reproduzieren die Strukturen und Hierarchien unserer Gesellschaft. Sie wiederholen nur, was sie in der Vergangenheit gelernt haben. Wenn wir diese Vorurteile ändern und Chancengleichheit schaffen wollen, müssen wir diese Systeme auf eine integrative Weise trainieren.

Warum genau sind KI-Systeme wie DALL-E 2 also voreingenommen und was können wir dagegen tun? Die Antwort auf diese Frage besteht aus drei Teilen:

  • den Daten,
  • dem Ziel,
  • und den Entwickler:innen.

#1 Daten

Erstens: KI-Systeme lernen nur das, was in den Daten enthalten ist. Wenn die Trainingsdaten verzerrt sind, ist auch die KI verzerrt. DALL-E 2 wurde mit Tausenden von Online-Bildbeschreibungspaaren aus dem Internet trainiert. Aufgrund historischer, sozialer und ethnischer Gegebenheiten, gibt es viel mehr heterosexuelle Paarbilder mit der Beschreibung „ein glückliches Paar“ als homosexuelle Paarbilder im Internet. DALL-E 2 hat also herausgefunden, dass die Beschreibung „ein glückliches Paar“ mit größerer Wahrscheinlichkeit mit heterosexuellen Paaren auf einem Bild assoziiert wird.

#2 Ziel

Zweitens: Damit ein KI-Algorithmus wie DALL-E 2 aus Daten lernen kann, braucht er ein Ziel zur Optimierung, eine Definition von Erfolg und Misserfolg. Genauso wie Ihr in der Schule gelernt habt, indem Ihr Eure Noten optimiert habt. Eure Noten haben Euch gezeigt, ob Ihr erfolgreich wart oder nicht, und was Ihr noch lernen müsst oder nicht.

In ähnlicher Weise lernt auch der Algorithmus, indem er sich die Daten ansieht und herausfindet, was mit Erfolg verbunden ist. Welche Situation führt zum Erfolg? Wenn wir also eine unvoreingenommene und faire künstliche Intelligenz schaffen wollen, müssen wir auch darüber nachdenken, welche Zielsetzung wir ihr geben. Wir müssen ihr sagen, dass sie sich vor Voreingenommenheit, Vorurteilen und Diskriminierung in Acht nehmen muss. Für DALL-E 2 könnte man zum Beispiel eine bestimmte Diversitätskennzahl in die Leistungsbewertungskriterien aufnehmen.

#3 Entwickler:innen

Drittens ist es die Entwickler:innengemeinschaft, die direkt oder indirekt, bewusst oder unbewusst ihre eigenen Vorurteile in die KI-Technologie einbringt. Sie wählen die Daten aus, sie definieren das Optimierungsziel und sie gestalten die Nutzung von KI. Meistens bringen sie ihre Voreingenommenheit nicht aktiv in diese Systeme ein. Wir alle leiden jedoch unter Vorurteilen, derer wir uns nicht bewusst sind. Diese Voreingenommenheit ist ein Versuch unseres Gehirns, die unglaublich komplexe Welt um uns herum zu vereinfachen. Die derzeitige Gemeinschaft der KI-Entwickler:innen besteht zu über 80 % aus weißen Cis-Männern. KI wird von einer sehr homogenen Gruppe entworfen, entwickelt und bewertet. Die Werte, Ideen und Vorurteile, die sich in KI-Systeme einschleichen, sind daher buchstäblich engstirnig.

Mögliche Lösungen für das Problem

Der entscheidende Schritt zu einer gerechteren und unvoreingenommeneren KI ist also eine vielfältige und integrative KI-Entwicklungsgemeinschaft. Unterschiedliche Menschen können die blinden Flecken und Vorurteile der anderen besser überprüfen.

Wenn wir über unsere eigenen Vorurteile nachdenken und gemeinsam daran arbeiten, die Vergangenheit nicht nur zu extrapolieren, sondern vorsichtig und kritisch aus ihr zu lernen, können wir die Welt zu einem viel vielfältigeren, integrativeren und gleichberechtigteren Ort machen. Nur dann können wir hoffen, KI-Technologien zu entwickeln, die wirklich inklusiv und fair sind.

Unsere Bemühungen um Diversität in der Entwicklung und am Arbeitsplatz

Wir bei statworx versuchen auch unser Bestes, um uns weiterzubilden und unseren Horizont zu erweitern. Wir engagieren uns aktiv für die Aufklärung der Gesellschaft im Bezug auf künstliche Intelligenz, z.B. in unserer Initiative AI & Society. Erst kürzlich habe ich im Namen der Initaitive zum Thema „Vorurteile in KI abbauen“ einen Blogartikel veröffentlicht und bei der Konferenz „Unfold“ in Bern einen Vortrag dazu gehalten.

Darüber hinaus haben wir uns entschlossen, die Charta der Vielfalt zu unterzeichnen. Die Charta der Vielfalt ist eine Arbeitgebendeninitiative zur Förderung von Vielfalt in Unternehmen und Institutionen. Ziel der Initiative ist es, die Anerkennung, Wertschätzung und Einbeziehung von Vielfalt in der Arbeitswelt in Deutschland voranzubringen. Für uns bei statworx ist dies ein Weg, um unseren Werten als Unternehmen gerecht zu werden, die auf Vielfalt, Inklusivität und Teamarbeit beruhen.

FYI: 20% dieses Artikels wurden vom KI Text Generator von neuroflash geschrieben. Livia Eichenberger Livia Eichenberger Livia Eichenberger Livia Eichenberger Livia Eichenberger

Ob bewusst oder unbewusst, Vorurteile in unserer Gesellschaft erschweren die Verwirklichung einer geschlechtergerechten Welt, die frei von Stereotypen und Diskriminierung ist. Leider schleichen sich diese geschlechtsspezifischen Vorurteile auch in die KI-Technologien ein, die sich in allen Bereichen unseres täglichen Lebens rasant weiterentwickeln und unsere Gesellschaft in nie gekanntem Maße verändern werden. Daher ist die Entwicklung fairer und unvoreingenommener KI-Systeme für eine vielfältige, gerechte und inklusive Zukunft unerlässlich. Es ist nicht nur wichtig, dass wir uns dieses Problems bewusst sind, sondern auch, dass wir jetzt handeln, bevor diese Technologien unsere geschlechtsspezifischen Vorurteile noch mehr verstärken, auch in Bereichen unseres Lebens, in denen wir sie bereits beseitigt haben.

Lösung beginnt mit Verständnis: Um an Lösungen zur Beseitigung geschlechtsspezifischer Vorurteile und aller anderen Formen von Vorurteilen in der KI zu arbeiten, müssen wir zunächst verstehen, was sie sind und woher sie kommen. Daher werde ich im Folgenden zunächst einige Beispiele für geschlechtsspezifische KI-Technologien vorstellen und Euch dann einen strukturierten Überblick über die verschiedenen Gründe für Vorurteile in der KI geben. In einem zweiten Schritt werde ich die notwendigen Maßnahmen für fairere und unvoreingenommenere KI-Systeme vorstellen.

Sexistische KI

Geschlechtsspezifische Vorurteile in der KI haben viele Gesichter und schwerwiegende Auswirkungen auf die Gleichstellung von Frauen. Während Youtube meinem ledigen Freund (männlich, 28) Werbung für die neuesten technischen Erfindungen oder die neuesten Automodelle zeigt, muss ich, ebenfalls ledig und 28, Werbung für Fruchtbarkeits- oder Schwangerschaftstests ertragen. Aber KI wird nicht nur eingesetzt, um Entscheidungen darüber zu treffen, welche Produkte wir kaufen oder welche Serien wir als nächstes sehen wollen. KI-Systeme werden auch eingesetzt, um zu entscheiden, ob Ihr ein Vorstellungsgespräch bekommt oder nicht, wie viel Ihr für Eure Autoversicherung zahlt, wie gut Eure Kreditwürdigkeit ist oder sogar, welche medizinische Behandlung Ihr bekommt. Und hier beginnt die Voreingenommenheit solcher Systeme wirklich gefährlich zu werden.

Im Jahr 2015 lernte das Rekrutierungstool von Amazon beispielsweise fälschlicherweise, dass Männer bessere Programmierer seien als Frauen. Daraufhin bewertete das Tool Bewerber:innen für Softwareentwicklerstellen und andere technische Stellen nicht geschlechtsneutral.

Im Jahr 2019 beantragte ein Paar dieselbe Kreditkarte. Obwohl die Ehefrau eine etwas bessere Kreditwürdigkeit und die gleichen Einnahmen, Ausgaben und Schulden wie ihr Ehemann hatte, setzte das Kreditkartenunternehmen ihr Kreditkartenlimit viel niedriger an, was der Kundendienst des Kreditkartenunternehmens nicht erklären konnte.

Wären diese sexistischen Entscheidungen von Menschen getroffen worden, wären wir empört. Zum Glück gibt es für uns Menschen Gesetze und Vorschriften gegen sexistisches Verhalten. Dennoch steht die künstliche Intelligenz mittlerweile über dem Gesetz, weil eine vermeintlich rationale Maschine die Entscheidung getroffen hat. Wie kann also eine vermeintlich rationale Maschine befangen, voreingenommen und rassistisch werden? Es gibt drei miteinander verknüpfte Gründe für Vorurteile in KI: Daten, Modelle und die AI Gemeinschaft.

Daten sind unser Schicksal

Erstens sind Daten ein Spiegel unserer Gesellschaft, mit all unseren Werten, Annahmen und leider auch Vorurteilen. Es gibt keine neutralen oder unbearbeiteten Daten. Daten werden immer von Menschen erzeugt, gemessen und gesammelt. Daten wurden schon immer durch kulturelle Vorgänge erzeugt und zu kulturellen Kategorien geformt. So werden beispielsweise die meisten demografischen Daten auf der Grundlage vereinfachter, binärer Frau-Mann-Kategorien etikettiert. Wenn die Geschlechterklassifizierung das Geschlecht auf diese Weise zusammenfasst, sind die Daten nicht in der Lage, Geschlechterfluidität und die eigene Geschlechtsidentität aufzuzeigen. Auch „Rasse“ ist ein soziales Konstrukt, ein Klassifizierungssystem, das wir Menschen vor langer Zeit erfunden haben, um physische Unterschiede zwischen Menschen zu definieren, und das immer noch in Daten vorhanden ist.

Der zugrundeliegende mathematische Algorithmus in KI-Systemen ist selbst nicht sexistisch. KI lernt aus Daten mit all ihren möglichen geschlechtsspezifischen Verzerrungen. Nehmen wir zum Beispiel an, ein Gesichtserkennungsmodell hat noch nie eine transsexuelle oder nicht-binäre Person gesehen, weil es kein solches Bild im Datensatz gab. In diesem Fall wird es eine transgender oder nicht-binäre Person nicht korrekt klassifizieren (Selection Bias).

Oder, wie im Fall von Google Translate, wird der Ausdruck „eine Ärztin“ in geschlechtsspezifisch flektierten Sprachen durchweg in die männliche Form übersetzt, weil das KI-System auf Tausenden von Online-Texten trainiert wurde, in denen die männliche Form von „Arzt“ aufgrund historischer und sozialer Umstände stärker verbreitet war (Historical Bias). Laut Invisible Women gibt es bei Big Data im Allgemeinen eine große Kluft zwischen den Geschlechtern, die zu Lasten der Frauen geht. Wenn wir also nicht darauf achten, mit welchen Daten wir diese Algorithmen füttern, werden sie den Gender Gap in den Daten übernehmen und Frauen systematisch diskriminieren.

Modelle brauchen Bildung

Zweitens sind unsere KI-Modelle leider nicht intelligent genug, um die Vorurteile in den Daten zu überwinden. Da die derzeitigen KI-Modelle nur Korrelationen und keine kausalen Strukturen analysieren, lernen sie blind, was in den Daten steht. Diesen Algorithmen wohnt ein systematischer Strukturkonservatismus inne, da sie darauf ausgelegt sind, bestimmte Muster in den Daten zu reproduzieren.

Um dies zu veranschaulichen, werde ich ein fiktives und sehr vereinfachtes Beispiel verwenden: Stellt euch einen sehr stereotypen Datensatz mit vielen Bildern von Frauen in Küchen und Männern in Autos vor. Anhand dieser Bilder soll ein Bildklassifikationsalgorithmus lernen, das Geschlecht einer Person auf einem Bild vorherzusagen. Aufgrund der Datenselektion gibt es in dem Datensatz eine hohe Korrelation zwischen Küchen und Frauen und zwischen Autos und Männern – eine höhere Korrelation als zwischen einigen charakteristischen Geschlechtsmerkmalen und dem jeweiligen Geschlecht. Da das Modell keine kausalen Strukturen erkennen kann (was geschlechtsspezifische Merkmale sind), lernt es also fälschlicherweise, dass eine Küche im Bild auch bedeutet, dass Frauen im Bild sind, und dasselbe gilt für Autos und Männer. Wenn also auf einem Bild eine Frau in einem Auto zu sehen ist, würde die KI die Person als Mann identifizieren und vice versa.

Dies ist jedoch nicht der einzige Grund, warum KI-Systeme die Vorurteile in Daten nicht überwinden können. Es liegt auch daran, dass wir den Systemen nicht „sagen“, dass sie darauf achten sollen. KI-Algorithmen lernen, indem sie ein bestimmtes, von den Entwicklern festgelegtes Ziel optimieren. In der Regel handelt es sich bei dieser Leistungsmessung um eine durchschnittliche Genauigkeitsmetrik, die keinerlei ethische oder faire Beschränkungen enthält. Das ist so, als ob ein Kind lernen soll, so viel Geld wie möglich zu bekommen, ohne zusätzliche Einschränkungen, wie z. B. die Konsequenzen von Diebstahl, Ausbeutung oder Betrug. Wenn wir wollen, dass KI-Systeme lernen, dass geschlechtsspezifische Vorurteile falsch sind, müssen wir dies in ihr Training und ihre Leistungsbewertung einbeziehen.

Der Gemeinschaft fehlt es an Diversität

Schließlich ist es die Entwickler:innen-Community, die direkt oder indirekt, bewusst oder unbewusst ihre eigenen geschlechtsspezifischen und anderen Vorurteile in KI-Technologien einbringt. Sie wählen die Daten aus, definieren das Optimierungsziel und gestalten die Nutzung von KI.

Auch wenn in einigen Fällen möglicherweise böswillige Absichten vorliegen, würde ich behaupten, dass Entwickler:innen ihre eigenen Vorurteile oft unbewusst in KI-Systeme einbringen. Wir alle erliegen unbewussten Vorurteilen, d. h. unbewussten Denkfehlern, die aus Problemen mit dem Gedächtnis, der Aufmerksamkeit und anderen mentalen Fehlern resultieren. Mit anderen Worten: Diese Verzerrungen resultieren aus dem Bestreben, die unglaublich komplexe Welt, in der wir leben, zu vereinfachen.

So fällt es unserem Gehirn beispielsweise leichter, stereotypes Denken anzuwenden, d. h. Vorstellungen über eine Person auf der Grundlage dessen zu entwickeln, wie Menschen aus einer ähnlichen Gruppe „typischerweise“ sein könnten (z. B. ein Mann eignet sich besser für die Position eines Geschäftsführers), als alle Informationen zu sammeln, um eine Person und ihre Eigenschaften vollständig zu verstehen. Oder, gemäß dem Affinitäts-Bias, mögen wir die Menschen am meisten, die so aussehen und denken wie wir, was ebenfalls eine vereinfachte Art ist, die Menschen um uns herum zu verstehen und zu kategorisieren.

Wir alle haben solche unbewussten Vorurteile, und da wir alle unterschiedliche Menschen sind, variieren diese Vorurteile von Person zu Person. Da jedoch die derzeitige Gemeinschaft der KI-Entwickler:innen zu über 80 % aus weißen, Cis-Männern besteht, sind die Werte, Ideen und Vorurteile, die sich in KI-Systeme einschleichen, sehr homogen und damit buchstäblich engstirnig. Angefangen bei der Definition von KI: Die Gründerväter der KI im Jahr 1956 waren allesamt weiße, männliche Ingenieure, eine sehr homogene Gruppe von Menschen, was zu einer engen Vorstellung davon führte, was Intelligenz ist, nämlich die Fähigkeit, Spiele wie Schach zu gewinnen. Aus der Psychologie wissen wir jedoch, dass es viele verschiedene Arten von Intelligenz gibt, z. B. emotionale oder soziale Intelligenz. Wenn heute ein Modell von einer sehr homogenen Gruppe von Menschen ohne besondere Aufmerksamkeit und Verfahren entwickelt und überprüft wird, sind sie aufgrund unbewusster Voreingenommenheit nicht in der Lage, Diskriminierung zu erkennen, die sich von ihnen selbst unterscheidet. In der Tat ist diese homogene Gemeinschaft tendenziell die Gruppe von Menschen, die in der KI kaum unter Voreingenommenheit leidet.

Stellen Sie sich vor, alle Kinder auf der Welt würden von 30-jährigen weißen Cis-Männern aufgezogen und erzogen. So sieht unsere KI heute aus. Sie wird von einer sehr homogenen Gruppe entworfen, entwickelt und bewertet und vermittelt so eine einseitige Perspektive auf Werte, Normen und Ideen. Die Entwickler:innen sind der Kern dieser Entwicklung. Sie bringen der KI bei, was richtig oder falsch, was gut oder schlecht ist.

Die Vorurteile in der Gesellschaft aufbrechen

Ein entscheidender Schritt auf dem Weg zu einer fairen und unvoreingenommenen KI ist also eine vielfältige und integrative KI-Entwicklungsgemeinschaft. Inzwischen gibt es einige technische Lösungen für die genannten Probleme der Daten- und Modellverzerrung (z. B. Datendiversifizierung oder Kausalmodellierung). Doch all diese Lösungen sind nutzlos, wenn die Entwickler:innen nicht von vornherein über Probleme mit Vorurteilen nachdenken. Unterschiedliche Menschen können die blinden Flecken und die Vorurteile der jeweils anderen besser überprüfen. **Viele Studien zeigen, dass die Vielfalt in Informatikteams entscheidend dazu beiträgt, Vorurteile in der KI zu verringern.

Außerdem müssen wir unsere Gesellschaft über KI, ihre Risiken und Chancen aufklären. Wir müssen die Ausbildung von KI-Entwickler:innen überdenken und umstrukturieren, denn sie brauchen ebenso viel ethisches Wissen wie technisches Wissen, um faire und unvoreingenommene KI-Systeme zu entwickeln. Wir müssen die breite Bevölkerung darüber aufklären, dass auch wir alle Teil dieses massiven Wandels durch KI werden können, um unsere Ideen und Werte in die Gestaltung und Entwicklung dieser Systeme einzubringen.

Wenn wir die Vorurteile der KI überwinden wollen, müssen wir letztlich auch die Vorurteile in unserer Gesellschaft überwinden. Vielfalt ist die Lösung für eine faire und unvoreingenommene KI, nicht nur in den KI-Entwicklungsteams, sondern in unserer gesamten Gesellschaft. KI wird von Menschen gemacht, von uns, von unserer Gesellschaft. Unsere Gesellschaft mit ihren Strukturen bringt Vorurteile in die KI: durch die Daten, die wir produzieren, die Ziele, die wir von den Maschinen erwarten, und die Gemeinschaft, die diese Systeme entwickelt. Im Kern sind Vorurteile in der KI kein technisches Problem – sie sind ein soziales Problem.

Positive Verstärkung von KI

Schließlich müssen wir uns fragen, ob wir wollen, dass die KI die heutige Gesellschaft widerspiegelt oder eine gleichberechtigtere Gesellschaft von morgen? Nehmen wir an, wir verwenden Machine Learning Modelle, um die Welt von heute abzubilden. In diesem Fall werden wir keinen sozialen Fortschritt erzielen. Wenn wir nicht handeln, könnten wir einige soziale Fortschritte, wie z. B. mehr Gleichberechtigung zwischen den Geschlechtern, verlieren, da die KI Vorurteile verstärkt und in unser Leben zurückbringt. Die KI soll zukunftsorientiert sein. Aber gleichzeitig basiert sie auf Daten, und Daten spiegeln unsere Geschichte und Gegenwart wider. So wie wir also die Voreingenommenheit in der Gesellschaft überwinden müssen, um die Voreingenommenheit in KI-Systemen zu überwinden, brauchen wir unvoreingenommene KI-Systeme für den sozialen Fortschritt in unserer Welt.

Nach all dem bin ich hoffnungsvoll und optimistisch. Durch diesen Verstärkungseffekt hat die KI das Bewusstsein für alte Fairness- und Diskriminierungsprobleme in unserer Gesellschaft auf einer viel breiteren Ebene geschärft. Vorurteile in KI zeigen uns einige der dringendsten gesellschaftlichen Herausforderungen. Ethische und philosophische Fragen werden immer wichtiger. Und weil KI diesen Verstärkungseffekt auf die Gesellschaft hat, können wir sie auch zum Positiven nutzen. Wir können diese Technologie für das Gute nutzen. Wenn wir alle zusammenarbeiten, haben wir die Chance, die Welt zu einem wesentlich vielfältigeren, inklusiveren und gleichberechtigteren Ort umzugestalten. Livia Eichenberger Livia Eichenberger

Einleitung

Jeder Data-Science- und KI-Experte wird Ihnen sagen: Reale Data Science und KI-Initiativen bringen verschiedene Herausforderungen mit sich, auf die weder praktische Programmierwettbewerbe noch theoretische Vorlesungen vorbereiten können. Und manchmal – erschreckend oft [1, 2] – führen diese Probleme in der Praxis dazu, dass vielversprechende KI-Projekte oder ganze KI-Initiativen scheitern. Seit geraumer Zeit wird eine rege Diskussion über die eher technischen Fallstricke und mögliche Lösungen geführt. Zu den bekannteren Problemen gehören z. B. isolierte Daten, schlechte Datenqualität, zu unerfahrene oder unterbesetzte DS & KI-Teams, unzureichende Infrastruktur für das Training und die Bereitstellung von Modellen. Ein weiteres Problem ist, dass zu viele Lösungen aufgrund organisatorischer Probleme nie in die Produktion überführt werden.

Erst in letzter Zeit hat sich der Fokus des Diskurses mehr auf strategische Fragen verlagert. Meiner Meinung nach wird diesen Aspekten jedoch immer noch nicht die Aufmerksamkeit zuteil, die sie verdienen.

Deshalb möchte ich in diesem Beitrag meine Meinung zu den wichtigsten (nicht-technischen) Gründen für das Scheitern von DS & KI-Initiativen darlegen. Darüber hinaus werde ich Ihnen verschiedene Ansätze zur Lösung dieser Probleme vorstellen. Ich bin Data & Strategy Consultant bei STATWORX und ich bin sicher, dass dieser Artikel eher subjektiv ist. Er spiegelt meine persönlichen Erfahrungen mit den Problemen und Lösungen wider, auf die ich gestoßen bin. 

Problem Nr. 1: Mangelnde Verknüpfung von Projektumfang und tatsächlichem Business-Problem Problem 1

Ein Problem, das viel häufiger auftritt, als man denken würde, ist die Fehlanpassung der entwickelten Data Science und KI-Lösungen an die tatsächlichen Geschäftsbedürfnisse. Das fertige Produkt erfüllt vielleicht genau die Aufgabe, die das DS- und KI-Team lösen wollte, aber die Anwender:innen suchen eventuell nach einer Lösung für eine ähnliche, aber deutlich andere Aufgabe.

Zu wenig Austausch durch indirekte Kommunikationskanäle oder das Fehlen einer gemeinsamen Sprache und eines gemeinsamen Referenzrahmens führt oft zu grundlegenden Missverständnissen. Das Problem ist, dass ironischerweise nur eine extrem detaillierte, effektive Kommunikation solche subtilen Probleme aufdecken kann.

Die Einbeziehung zu weniger oder selektiver Perspektiven kann zu einem bösen Erwachen führen

In anderen Fällen unterscheiden sich einzelne Teilprozesse oder die Arbeitsweisen einzelner Nutzenden sehr stark. Oft sind sie so unterschiedlich, dass eine Lösung, die für einen der Anwender:innen/Prozesse von großem Nutzen ist, für alle anderen kaum Vorteile bringt (die Entwicklung von Lösungsvarianten ist zwar manchmal eine Option, aber bei weitem nicht so kosteneffizient).

Wenn Sie Glück haben, stellen Sie dies bereits zu Beginn eines Projekts bei der Erhebung der Anforderungen fest. Wenn man Pech hat, kommt das böse Erwachen erst beim breiteren Nutzertest oder gar bei der Einführung, wenn sich herausstellt, dass die Nutzer:innen oder Expert:innen, die die bisherige Entwicklung beeinflusst haben, keinen allgemeingültigen Input geliefert haben und das entwickelte Werkzeug daher nicht allgemein einsetzbar ist.

Wie Sie diesem Problem entgegenwirken können:

  • Führen Sie ein strukturiertes und gründliches Requirements Engineering durch. Nehmen Sie sich die Zeit, mit so vielen Expert:innen und Nutzer:innen wie möglich zu sprechen, und versuchen Sie, alle impliziten Annahmen so explizit wie möglich zu machen. Obwohl das Requirements Engineering aus dem Wasserfall-Paradigma stammt, kann es leicht für die agile Entwicklung angepasst werden. Die ermittelten Anforderungen dürfen einfach nicht als endgültige Produktmerkmale verstanden werden, sondern als Elemente für Ihr anfängliches Backlog, die ständig (neu) bewertet und (neu) priorisiert werden müssen.
  • Definieren Sie unbedingt Erfolgsmessungen. Tun Sie dies vor Projektbeginn, am besten in Form von objektiv quantifizierbaren KPIs und Benchmarks. Dies trägt wesentlich dazu bei, das Geschäftsproblem bzw. den Geschäftswert, der der angestrebten Lösung zugrunde liegt, zu ermitteln.
  • Erstellen Sie, wann immer möglich und so schnell wie möglich, Prototypen, Mock-ups oder sogar Storyboards. Präsentieren Sie diese Lösungsentwürfe so vielen Testnutzern wie möglich. Diese Methoden erleichtern das Einholen von offenem und präzisem Nutzerfeedback, das in die weitere Entwicklung einfließt. Achten Sie darauf, dass Sie eine für die Gesamtheit der Nutzer repräsentative Stichprobe einbeziehen.

Problem Nr. 2: Effizienz- und Ressourcenverluste durch nicht strukturierte Data Science- und KI-Maßnahmen Problem 2

Dezentralisierte Data Science- & KI-Teams entwickeln ihre Anwendungsfälle oft mit wenig bis gar keinem Austausch oder Abgleich zwischen den aktuellen Anwendungsfällen und Backlogs der Teams. Dies kann dazu führen, dass verschiedene Teams versehentlich und unbemerkt (Teile) der gleichen (oder sehr ähnlichen) Lösung entwickeln.

In den meisten Fällen wird, wenn eine solche Situation entdeckt wird, eine der redundanten DS & KI-Lösungen eingestellt oder es werden keine zukünftigen Mittel für die weitere Entwicklung oder Wartung bereitgestellt. So oder so, die redundante Entwicklung von Anwendungsfällen führt immer zu einer direkten Verschwendung von Zeit und anderen Ressourcen ohne oder mit nur minimalem Zusatznutzen.

Problematisch ist auch die fehlende Abstimmung des Use Case Portfolios eines Unternehmens auf die allgemeine Geschäfts- oder KI-Strategie. Dies kann hohe Opportunitätskosten verursachen: Anwendungsfälle, die nicht zur allgemeinen KI-Vision beitragen, können unnötigerweise wertvolle Ressourcen blockieren. Außerdem werden potenzielle Synergien zwischen strategisch wichtigeren Anwendungsfällen (Use Cases) möglicherweise nicht voll ausgeschöpft. Und schließlich könnte der Aufbau von Kompetenzen in Bereichen erfolgen, die von geringer oder gar keiner strategischen Bedeutung sind.

Wie Sie diesem Problem entgegenwirken können:

  • Kommunikation ist der Schlüssel. Deshalb sollte es immer eine Reihe von Möglichkeiten für die Data-Science-Expert:innen innerhalb eines Unternehmens geben, sich zu vernetzen und ihre Erfahrungen und Best Practices auszutauschen – insbesondere bei dezentralen DS & KI-Teams. Damit dies funktioniert, ist es wichtig, eine Arbeitsatmosphäre der Zusammenarbeit zu schaffen. Der freie Austausch von Erfolgen und Misserfolgen und damit die interne Verbreitung von Kompetenzen kann nur ohne Konkurrenzdenken gelingen.
  • Eine weitere Möglichkeit, das Problem zu entschärfen, ist die Einrichtung eines zentralen Ausschusses, der mit der Verwaltung des DS und KI Use Case Portfolios der Organisation betraut ist. Diesem Ausschuss sollten Vertreter:innen aller (dezentralen) Data Science und KI-Abteilungen sowie der Geschäftsleitung angehören. Gemeinsam überwacht der Ausschuss die Abstimmung von Use Cases und der KI-Strategie, um Redundanzen zu vermeiden und Synergien voll auszuschöpfen.

Problem Nr. 3: Unrealistisch hohe Erwartungen an den Erfolg von Data Science und KI Problem 3

Es mag paradox klingen, aber ein zu großer Optimismus in Bezug auf die Möglichkeiten und Fähigkeiten von Data Science und KI kann dem Erfolg abträglich sein. Denn zu optimistische Erwartungen führen oft dazu, dass die Anforderungen unterschätzt werden, wie z. B. die für die Entwicklung benötigte Zeit oder der Umfang und die Qualität der benötigten Datenbasis.

Gleichzeitig sind die Erwartungen in Bezug auf die Modellgenauigkeit oft zu hoch, ohne dass man die Grenzen des Modells und die grundlegenden Mechanismen von Machine Learning kennt. Diese Unerfahrenheit kann dazu führen, dass viele wichtige Tatsachen nicht erkannt werden, einschließlich, aber nicht beschränkt auf die folgenden Punkte: die unvermeidliche Extrapolation historischer Muster auf die Zukunft; die Tatsache, dass externe Paradigmenwechsel oder Schocks die Generalisierbarkeit und Leistung von Modellen gefährden; die Komplexität der Harmonisierung von Vorhersagen mathematisch nicht verwandter Modelle; die geringe Interpretierbarkeit naiver Modelle oder die Dynamik der Modellspezifikationen aufgrund von Umschulungen.

DS & KI sind einfach keine Wunderwaffe, und zu hohe Erwartungen können dazu führen, dass die Begeisterung in tiefe Ablehnung umschlägt. Die anfänglichen Erwartungen werden fast zwangsläufig nicht erfüllt und weichen daher oft einer tiefgreifenden und undifferenzierten Ablehnung von DS & KI. Dies kann in der Folge dazu führen, dass weniger auffällige, aber nützliche Anwendungsfälle keine Unterstützung mehr finden.

Wie Sie diesem Problem entgegenwirken können:

  • Versuchen Sie in Ihrer Kommunikation mit Stakeholdern stets realistische Perspektiven zu vermitteln. Achten Sie darauf, eindeutige Botschaften und objektive KPIs zu verwenden, um Erwartungen zu steuern und Bedenken so offen wie möglich anzusprechen.
  • Die Weiterbildung der Stakeholder und des Managements in den Grundlagen von Machine Learning und KI versetzt sie in die Lage, realistischere Einschätzungen und damit sinnvollere Entscheidungen zu treffen. Technisch fundiertes Wissen ist oft nicht notwendig. Konzeptuelles Fachwissen auf einem relativ hohen Abstraktionsniveau ist ausreichend (und glücklicherweise viel leichter zu erlangen).
  • Schließlich sollte, wann immer möglich, ein PoC vor einem vollwertigen Projekt durchgeführt werden. Dies ermöglicht es, empirische Hinweise auf die Durchführbarkeit des Use Cases zu sammeln und hilft bei der realistischen Einschätzung der erwarteten Leistung, die anhand relevanter (vordefinierter!) KPIs gemessen wird. Wichtig ist es auch, die Ergebnisse solcher Tests ernst zu nehmen. Bei einer negativen Prognose sollte nie einfach davon ausgegangen werden, dass sich mit mehr Zeit und Aufwand alle Probleme des PoC in Luft auflösen werden.

Problem Nr. 4: Ressentiments und grundsätzliche Ablehnung von Data Science und KI Problem 4

Eine unsichtbare, aber nicht zu unterschätzende Hürde liegt in den Köpfen der Menschen. Dies gilt sowohl für die Belegschaft als auch für das Management. Oft werden vielversprechende Data Science und KI-Initiativen aufgrund von tief verwurzelten, aber undifferenzierten Vorbehalten ausgebremst. Das richtige Mindset ist entscheidend.

Obwohl DS und KI in aller Munde sind, fehlt es in vielen Unternehmen noch an echtem Management-Engagement. Häufig werden zwar Lippenbekenntnisse zu DS & KI abgegeben und erhebliche Mittel investiert, aber die Vorbehalte gegenüber KI bleiben bestehen.

Begründet wird dies oft mit den inhärenten Verzerrungen und Unsicherheiten von KI-Modellen und ihrer geringen direkten Interpretierbarkeit. Hinzu kommt manchmal eine generelle Abneigung, Erkenntnisse zu akzeptieren, die nicht mit der eigenen Intuition übereinstimmen. Die Tatsache, dass die menschliche Intuition oft viel stärkeren – und im Gegensatz zu KI-Modellen nicht quantifizierbaren – Verzerrungen unterliegt, wird in der Regel ignoriert.

Data Science & KI-Initiativen brauchen die Akzeptanz und Unterstützung der Belegschaft

Dies führt dazu, dass (Entscheidungs-)Prozesse und Organisationsstrukturen (z.B. Rollen, Verantwortlichkeiten) nicht so angepasst werden, dass DS & KI-Lösungen ihren (vollen) Nutzen entfalten können. Dies wäre aber notwendig, denn Data Science & KI ist nicht einfach eine weitere Softwarelösung, die sich nahtlos in bestehende Strukturen integrieren lässt.

DS & KI ist eine disruptive Technologie, die unweigerlich ganze Branchen und Organisationen umgestalten wird. Unternehmen, die sich diesem Wandel verweigern, werden auf lange Sicht wahrscheinlich genau an diesem Paradigmenwechsel scheitern. Die Ablehnung des Wandels beginnt bei scheinbaren Kleinigkeiten, wie der Umstellung des Projektmanagements von der Wasserfallmethode auf eine agile, iterative Entwicklung. Ungeachtet der allgemein positiven Aufnahme bestimmter Veränderungsmaßnahmen wird manchmal eine völlig irrationale Ablehnung der Reform bestehender (noch) funktionierender Prozesse festgestellt. Dabei wäre genau das notwendig, um – zugegebenermaßen erst nach einer Phase der Neujustierung – langfristig wettbewerbsfähig zu sein.

Während Vision, Strategie und Strukturen von oben nach unten verändert werden müssen, kann das operative Tagesgeschäft nur von unten nach oben, durch die Mitarbeitenden, revolutioniert werden. Das Engagement des Managements und das beste Werkzeug der Welt sind nutzlos, wenn die Endnutzer:innen nicht in der Lage oder willens sind, es anzunehmen. Die allgemeine Unsicherheit über die langfristige KI-Roadmap und die Angst, durch Maschinen ersetzt zu werden, schüren Ängste, die dazu führen, dass DS & KI-Lösungen nicht in den Arbeitsalltag integriert werden. Dies ist natürlich mehr als problematisch, da nur die (richtige) Anwendung von KI-Lösungen einen Mehrwert schafft.

Wie Sie diesem Problem entgegenwirken können:

  • Es überrascht nicht, dass ein solides Change Management der beste Ansatz ist, um die KI-feindliche Denkweise zu entschärfen. Dies sollte nicht nur ein nachträglicher Gedanke, sondern ein integraler Bestandteil jeder DS & KI-Initiative und es sollten Verantwortlichkeiten für diese Aufgabe zugewiesen werden. Eine frühzeitige, umfassende, detaillierte und klare Kommunikation ist unerlässlich. Welche Schritte werden voraussichtlich wann und wie genau umgesetzt? Denken Sie daran, dass es schwer ist, einmal verlorenes Vertrauen wiederzugewinnen. Daher sollten alle Unklarheiten in der Planung angesprochen werden. Entscheidend ist es, bei allen Beteiligten ein Grundverständnis für die Sache zu schaffen und die Notwendigkeit der Veränderung zu verdeutlichen (z.B. weil sonst die Wettbewerbsfähigkeit gefährdet ist, Erfolgsgeschichten oder Misserfolge der Konkurrenz). Darüber hinaus ist der Dialog mit den Betroffenen von großer Bedeutung. Feedback sollte frühzeitig eingeholt und nach Möglichkeit umgesetzt werden. Bedenken sollten immer gehört und respektiert werden, auch wenn sie nicht berücksichtigt werden können. Falsche Versprechungen sind jedoch strikt zu vermeiden; stattdessen sollte man versuchen, die Vorteile von DS & KI in den Vordergrund zu stellen.
  • Neben der Einsicht in die Notwendigkeit von Veränderungen ist auch die grundsätzliche Fähigkeit zur Veränderung wichtig. Die Angst vor dem Unbekannten oder Unverständlichen ist uns Menschen inhärent. Daher kann Bildung – nur auf dem für die jeweilige Rolle notwendigen Abstraktions- und Tiefenniveau – einen großen Unterschied machen. Entsprechende Schulungsmaßnahmen sind keine einmalige Angelegenheit; der Aufbau von aktuellem Wissen und die Ausbildung im Bereich Data Science & KI müssen langfristig sichergestellt werden. Die allgemeine Datenkompetenz der Belegschaft muss ebenso sichergestellt werden, wie die Auf- oder Umschulung von technischen Expert:innen. Die Mitarbeitenden müssen eine realistische Chance erhalten, neue und attraktivere Beschäftigungsmöglichkeiten zu erhalten, indem sie sich weiterbilden und sich mit DS & KI beschäftigen. Das wahrscheinlichste Ergebnis sollte niemals sein, dass sie durch DS & KI ihren alten Arbeitsplatz (teilweise) verlieren, sondern muss als Chance und nicht als Gefahr wahrgenommen werden; Data Science & KI müssen Perspektiven schaffen und dürfen sie nicht verderben.
  • Übernehmen oder adaptieren Sie die Best Practices von DS & KI-Führungskräften in Bezug auf die Definition von Rollen- und Kompetenzprofilen, die Anpassung von Organisationsstrukturen und Wertschöpfungsprozessen. Bewährte Ansätze können als Blaupause für die Reformierung Ihrer Organisation dienen und so sicherstellen, dass Sie auch in Zukunft wettbewerbsfähig bleiben.

Schlussbemerkungen

Wie Sie vielleicht bemerkt haben, bietet dieser Blogbeitrag keine einfachen Lösungen. Das liegt daran, dass die Probleme, um die es hier geht, komplex und mehrdimensional sind. Dieser Artikel hat high-level Ansätze zur Entschärfung der angesprochenen Probleme geliefert, aber es muss betont werden, dass diese Probleme einen ganzheitlichen Lösungsansatz erfordern. Dies erfordert eine klare KI-Vision und eine daraus abgeleitete solide KI-Strategie, nach der die Vielzahl der notwendigen Maßnahmen koordiniert und gesteuert werden kann.

Deshalb muss ich betonen, dass wir das Stadium, in dem experimentelle und unstrukturierte Data Science und KI-Initiativen erfolgreich sein können, längst verlassen haben. DS & KI darf nicht als technisches Thema behandelt werden, das ausschließlich in Fachabteilungen stattfindet. Es ist an der Zeit, KI als strategisches Thema anzugehen. Wie bei der digitalen Revolution werden nur Organisationen, in denen KI das Tagesgeschäft und die allgemeine Geschäftsstrategie vollständig durchdringt und reformiert, langfristig erfolgreich sein. Wie oben beschrieben, birgt dies zweifelsohne viele Fallstricke, stellt aber auch eine unglaubliche Chance dar.

Wenn Sie bereit sind, diese Veränderungen zu integrieren, aber nicht wissen, wo Sie anfangen sollen, helfen wir von STATWORX Ihnen gerne. Besuchen Sie unsere Website und erfahren Sie mehr über unser Angebot im Bereich AI Strategy!

Quellen

[1] https://www.forbes.com/sites/forbestechcouncil/2020/10/14/why-do-most-ai-projects-fail/?sh=2f77da018aa3 [2] https://blogs.gartner.com/andrew_white/2019/01/03/our-top-data-and-analytics-predicts-for-2019/

Lea Waniek

Lea Waniek Lea Waniek

Dieser Artikel ist am 28. August 2021 in der Zeitung DIE WELT erschienen.

WELT_Menschzentrierte KI
 

Künstliche Intelligenz (KI) ist einer der zentralen Treiber der digitalen Transformation. Über die vergangene Dekade hinweg haben sich bahnbrechende Anwendungen der Technologie regelmäßig aneinandergereiht und sich dabei regelmäßig selbst überholt. Angetrieben durch den immer weiter voranschreitenden Erfolg von KI-Technologie diffundiert diese stetig in alle wesentlichen Bereiche des menschlichen Lebens hinein. Neben der Arbeitswelt schließt dies insbesondere auch das breitere gesellschaftliche Leben ein. Dabei sind sich KI-Experten alle einig, dass der aktuelle Entwicklungsstand von KI nur die Spitze eines riesigen Eisbergs ist, dessen Freilegung gerade erst begonnen hat. Die dadurch entstehenden Veränderungen werden eine neue Ära unserer Gesellschaft entstehen lassen, in der Menschen mit Maschinen Seite an Seite arbeiten und leben werden.

Mit der wachsenden Bedeutung von KI für die Gesellschaft nimmt auch die Sorge der Menschen zu, dass die Technologie, die ohnehin schon so viel verändert, in einigen Jahren dazu führen wird, dass Menschen „wie Roboter“ handeln. Während Künstliche Intelligenz heute noch als Werkzeug dient – so wie Maschinen oder Computer früher – wird sie sich in Zukunft zunehmend in die Gedanken und Handlungen der Menschen einbringen. Dazu wird sie das Verhalten von Personen und das Zusammenspiel mit anderen Menschen analysieren, um daraus abzulesen, welche Handlungsoptionen für ihre Nutzer in einem bestimmten Moment am besten sind.

Menschenzentrierte KI ist ein Teilbereich der KI-Forschung, der sich auf die Entwicklung von KI-Systemen konzentriert, die sich menschenähnlich verhalten. Im Gegensatz zur traditionellen KI-Forschung, die sich auf die Entwicklung von KI-Systemen konzentriert, die sich rational und ohne menschenähnliche Eigenschaften verhalten sollen, zielt die menschenzentrierte KI darauf ab, den Menschen und die menschliche Intelligenz zu studieren, um KI-Systeme mit ähnlichen Eigenschaften zu entwickeln.

Die menschenzentrierte KI ist durch den Wunsch motiviert, KI-Systeme zu schaffen, die mit Menschen auf natürliche Weise interagieren können. Rationale KI-Systeme können zwar intelligent handeln, verhalten sich aber nicht wie Menschen, was ein Hindernis für ihre Akzeptanz durch Menschen sein kann. Während sich die herkömmliche KI-Forschung auf die Überwindung dieser Barriere konzentriert hat, zielt die menschenzentrierte KI-Forschung darauf ab, KI-Systeme zu schaffen, die sich auf natürliche Weise verhalten, so dass sie für den Menschen besser nachvollziehbar und akzeptabel sind. Es ist wichtig, dass wir uns im Vorfeld vergewissern, dass die Technologie im Einklang mit unserer Menschlichkeit steht und den Menschen in der Arbeitswelt nicht nur unterstützt, sondern ihn auch nicht „überholt“. Eine solche menschenzentrierte KI kann dabei helfen, menschliche und nicht-menschliche Intelligenz in einem gesunden Verhältnis miteinander zu integrieren. Der Fokus liegt dabei auf den Bedürfnissen der Nutzer, die als die wichtigsten Zielgruppen der Technologie betrachtet werden.

Die zentrale Herausforderung der künstlichen Intelligenz ist daher nicht die Technologie selbst, sondern vielmehr der Umgang des Menschen mit dieser Technologie. Die technische Entwicklung wird in Zukunft weitergehen und damit immer intelligentere, autonome Systeme hervorbringen. Die Systeme und ihre Entscheidungsprozesse werden den Menschen zunehmend hinter sich lassen, „maschinelles Lernen“ wird das Gebot der Stunde sein. Dabei ist es wichtig, dass die Menschen die KI-Technologie als einen Schritt in eine bessere Zukunft begreifen und nicht als Bedrohung verkörpert. Die Entwicklung der KI ist ein Prozess, der nur durch den Dialog zwischen Menschen und Technologien bewältigt werden kann. Die unzureichende Aufklärung der Gesellschaft über die Technologie und die unzureichende Kommunikation zwischen den Nutzern und der Industrie spielen hierbei eine große Rolle. Dabei sollte der Mensch immer im Vordergrund stehen und nicht nur als ein Werkzeug der KI.

Genese

Der vorstehende Text wurde mithilfe der KI „GPT-3“ verfasst. Das Akronym GPT steht für „Generative Pretrained Transformer“ (in der Version 3), einer KI, die in 2020 durch das Amerikanische Forschungsunternehmen OpenAI entwickelt wurde. Bei GPT-3 handelt es sich um ein sogenanntes generatives Sprachmodell, das auf einer extrem großen Menge an diversen Texten aus dem Internet trainiert wurde.

Das Training von GPT-3 erfolgt mittels Deep Learning, einer Gruppe von Methoden aus dem maschinellen Lernen, die grobe Ähnlichkeiten zur Informationsverarbeitung und -weitergabe im menschlichen Gehirn aufweisen (Nervenzellen bzw. Neuronen geben die zu verarbeitenden Informationen an andere Neuronen und Hirnareale weiter). Im Rahmen des Modelltrainings passen sich die rund 175 Milliarden Parameter von GPT-3 an die zugrundeliegenden Trainingsdaten an und erlernen den Zusammenhang zwischen dem zuvor beobachteten Text eines Satzes/Abschnittes und dem nächsten, wahrscheinlich auftauchenden Wort. Hierdurch generiert die KI während des Lernvorgangs ein generelles und umfassendes Verständnis über die Verwendung von Worten im jeweiligen Kontext.

So geschah es auch in diesem Artikel. Als Ausgangsbasis der Textgenerierung dienten lediglich die ersten fünf Sätze des ersten Absatzes. Hierin wurde der Kontext definiert, in dem die KI operieren soll. Alle darauffolgenden Abschnitte wurden eigenständig durch die KI generiert und inhaltlich nicht modifiziert (Anmerkung: es wurden einzelne Absätze wiederholt erzeugt und anschließend zu einem Artikel zusammengefügt).

Der Schlüssel zum Erfolg liegt also in der geschickten Definition des Kontextes, der die KI im Prozess der Generierung anleitet. Bahnbrechend ist hierbei, dass die Kontextdefinition über natürliche Sprache funktioniert und nicht manuell in die KI „einprogrammiert“ werden muss. Die KI „versteht“ somit eigenständig den Kontext, in dem sie sich bewegen soll.

Wir hoffen, Ihnen mit diesem Beispiel einen Eindruck von der Mächtigkeit solcher KI-Systeme geben zu können. Es ist zu erwarten, dass bereits in naher Zukunft neue Versionen dieser und ähnlicher KI-Systeme entstehen, die in der Lage sein werden, noch bessere Ergebnisse erzeugen zu können.

Sebastian Heinz Sebastian Heinz

Management Summary

Mit Kubernetes steht uns eine Technologie zur Verfügung, welche in vielerlei Hinsicht die Bereitstellung und Wartung von Anwendungen und Rechenlasten, insbesondere das Training und Hosten von Machine Learning Modellen, enorm vereinfacht. Gleichzeitig ermöglicht sie uns, die benötigten Hardware-Ressourcen dazu an den Bedarf anzupassen, und bietet damit eine skalierbare und kostentransparente Lösung.

Dieser Artikel behandelt zuerst den Weg vom Server hin zu dem Management und der Orchestrierung von Containern: isolierte Anwendungen oder Modelle, welche mit all ihren Anforderungen einmal verpackt werden und im Anschluss fast überall ausgeführt werden können. Unabhängig vom Server können diese mit Kubernetes beliebig repliziert werden und ermöglichen somit aufwandslos und schier nahtlos eine durchgehende Erreichbarkeit ihrer Dienste auch unter hoher Last. Ebenfalls kann ihre Anzahl bis auf einen Mindeststand reduziert werden, wenn die Nachfrage vorübergehend oder periodisch schwindet, um Rechenressourcen anderweitig zu nutzen oder unnötige Kosten zu vermeiden.

Aus den Möglichkeiten dieser Infrastruktur geht ein nützliches Architektur-Paradigma hervor, die Microservices. Ehemals zentralisierte Anwendungen werden so in ihre Funktionalitäten heruntergebrochen, welche ein hohes Maß an Wiederverwendbarkeit bieten. Diese können von unterschiedlichen Diensten angesprochen und verwendet werden und skalieren einzeln je nach internem Bedarf. Ein Beispiel hierfür sind große und komplexe Sprachmodelle im Natural Language Processing, welche den Kontext eines Textes unabhängig von dessen weiterer Verwendung erfassen können, und damit vielen downstream Zwecken zugrunde liegen. Andere Microservices (Modelle), wie zur Text-Klassifikation oder Zusammenfassung, können diese aufrufen und die Teilergebnisse weiterverarbeiten.

Nach einer kurzen Einführung der allgemeinen Begrifflichkeiten und Funktionsweise von Kubernetes, sowie mögliche Anwendungsfälle, richtet sich das Augenmerk auf die am weitesten verbreitete Form Kubernetes zu nutzen: mit Cloud Anbietern wie Google GCP, Amazon AWS oder Microsoft Azure. Diese erlauben sog. Kubernetes Clustern, dynamisch mehr oder weniger Ressourcen zu beanspruchen, wenn gleich die entstehenden Kosten auf pay-per-use Basis absehbar bleiben. Auch weitere gängige Dienste wie Datenspeicher, Versionierung und Networking können von den Anbietern einfach eingebunden werden. Letztlich gibt der Beitrag noch einen Ausblick über Tools und Weiterentwicklungen, welche entweder die Nutzung von Kubernetes noch effizienter machen oder das Verfahren hin zu Serverless Architekturen weiter abstrahieren und vereinfachen.

Einleitung

Über die letzten 20 Jahre sind Unmengen neuer Technologien in der Softwareentwicklung und -Bereitstellung zu Tage gekommen, welche nicht nur die Auswahl an Diensten, Programmiersprachen, Bibliotheken oder ähnliches vervielfacht und diversifiziert haben, sondern gar auch bei vielen Anwendungsfällen oder -Gebieten bis hin zu einem Paradigmenwechsel geführt haben.

Abb. 1: Google Trends Chart, die den zuvor genannten Paradigmenwechsel verdeutlicht.

Betrachtet man so auch die Art und Weise der Bereitstellung von Softwarelösungen, Modellen oder Rechen- und Arbeitslasten über die Jahre, lässt sich erkennen wie auch in diesem Bereich die Neuerungen u.a. zu mehr Flexibilität, Skalierbarkeit und Ressourceneffizienz geführt haben.

Zu Beginn wurden diese als lokale Prozesse direkt auf einem (von mehreren Anwendungen geteilten) Server betrieben, was einige Einschränkungen und Probleme aufwarf: zum einen ist man bei der Auswahl der technischen Werkzeuge an die Begebenheiten der Server und deren Betriebssystem gebunden, zum anderen sind alle Anwendungen, welche auf dem Server gehostet werden, durch dessen Speicher- und Prozessorkapazitäten begrenzt. Somit teilen sie sich nicht nur in Summe die Ressourcen, sondern auch eine eventuelle Prozess-übergreifende Fehleranfälligkeit.

Als erste Weiterentwicklung können Virtuelle Maschinen daraufhin eine weitere Abstraktionsebene bieten: durch das auf dem Server aufgesetzte Emulieren („Virtualisieren“) einer eigenständigen Maschine entsteht für die Entwicklung und das Deployment Modularität und damit größere Freiheit: zum Beispiel in der Wahl des Betriebssystems oder der verwendeten Programmiersprachen und -Bibliotheken. Aus Sicht des „echten“ Servers können die Ressourcen, welche der Anwendung zustehen sollen, besser beschränkt bzw. garantiert werden. Jedoch sind deren Anforderungen auch bedeutend höher, da die Virtuelle Maschine auch das virtuelle Betriebssystem unterhalten muss.

Letztendlich wurde dieses Prinzip durch die Verbreitung von Containern, vor allem Docker, wesentlich verschlankt und vereinfacht. Vereinfacht gesagt baut/konfiguriert man für eine Anwendung oder ein Machine Learning Modell einen eigenen virtuellen, abgegrenzten Server. So enthält jeder Container sein eigenes Dateisystem und gewisse Systembibliotheken, aber nicht das Betriebssystem. Damit wird er technisch zu einem Sandkasten, dessen andere Konfiguration, Code-Abhängigkeiten oder Fehler sich nicht auf den Host-Server auswirken, aber gleichzeitig als relativ „leichtgewichtige“ Prozesse direkt auf diesem laufen können.

_Vergleich virtuelle Maschine und Docker Container Architektur
Abb. 2: Vergleich zwischen Virtueller Maschine und Docker Container Systemarchitektur, Quelle: https://i1.wp.com/www.docker.com/blog/wp-content/uploads/Blog.-Are-containers-..VM-Image-1-1024×435.png?ssl=1

Es besteht also die Möglichkeit, alles für die gewünschte Anwendung zu kopieren, installieren, usw., und dies in einem verpackten Container überall in einem einheitlichen Format bereitzustellen. Dies ist nicht nur für das Produktionsumfeld extrem nützlich, sondern findet bei STATWORX auch gerne in der Entwicklung von komplizierteren Projekten oder der Proof-of-Concept Phase Gebrauch. Zwischenschritte oder -Ergebnisse, wie beispielsweise die Extraktion von Text aus Bildern, können als Container wie ein kleiner Webserver von denjenigen verwendet werden, die an der Weiterverarbeitung des Textes interessiert sind, etwa die Extraktion gewisser zentraler Informationen, oder die Bestimmung von dessen Stimmung oder Absicht.

Diese Unterteilung in sogenannte „Microservices“ mit Hilfe von Containern hilft ungemein bei der Wiederverwendbarkeit der einzelnen Module, bei der Planung und Entwicklung der Architektur komplexer Systeme; sie befreit gleichzeitig die einzelnen Arbeitsschritte von technischen Abhängigkeiten gegenübereinander und erleichtert die Wartungs- und Update-Prozeduren.

Nach diesem kleinen Überblick über die mächtigen und vielseitigen Möglichkeiten der Bereitstellung von Software wird sich der folgende Text damit beschäftigen, wie man diese Container (sprich Anwendungen oder Modelle) verlässlich und skalierbar für Kunden, andere Anwendungen, interne Dienste oder Berechnungen mit Kubernetes bereitstellen kann.

Kubernetes – 8 wesentliche Komponenten

Kubernetes wurde 2014 von Google als open-source Container-Management Software (auch Container-Orchestrierung genannt) vorgestellt. Intern benutzte man bereits seit Jahren eigens entwickelte Tools, um Arbeitslasten und Anwendungen zu verwalten, und sah in der Entwicklung von Kubernetes nicht nur das Zusammenkommen von best practises und lessons learned, sondern auch die Möglichkeit damit ein neues Geschäftsfeld im Cloud Computing zu erschließen.

Der Name Kubernetes (griechisch für Steuermann) wurde angeblich in Bezug auf ein symbolisches Containerschiff ausgewählt, für dessen optimalen Betrieb jener verantwortlich ist.

1.    Nodes

Spricht man von einer Kubernetes-Instanz, wird sie als (Kubernetes) Cluster bezeichnet: dieses besteht aus mehreren Servern, genannt Nodes. Eine davon, die sogenannte Master-Node, ist komplett für den administrativen Betrieb zuständig, und ist die Schnittstelle, welche vom Entwickler angesprochen wird. Alle weiteren, genannt Worker-Nodes, sind zu Beginn unbelegt und damit flexibel einsetzbar. Während Nodes tatsächlich physische Instanzen sind, meist in Rechenzentren, sind die nun folgenden Begrifflichkeiten Konzepte von Kubernetes.

2.    Pods

Soll eine Anwendung auf dem Cluster bereitgestellt werden, wird im einfachsten Fall der gewünschte Container angegeben, und daraufhin (automatisch) ein sogenannter Pod erstellt und einer Node zugewiesen. Der Pod ähnelt hier einfach einem laufenden Container. Sollen gleich mehrere Instanzen der gleichen Anwendung parallel laufen, etwa um bessere Verfügbarkeit zu bieten, kann die Anzahl der Replicas angegeben werden. Hierbei wird die spezifizierte Anzahl an Pods mit jeweils derselben Anwendung auf die Nodes verteilt. Sollte der Bedarf nach der Anwendung trotz Replicas die Kapazitäten übersteigen, können mit dem Horizontal Autoscaler automatisch noch mehr Pods erstellt werden. Besonders bei Deep Learning Modellen mit verhältnismäßig langer Inferenzzeit können hier Metriken wie CPU- oder GPU-Auslastung überwacht werden, und die Anzahl der Pods vergrößert oder verringert werden, um sowohl Kapazitäten als auch Kosten zu optimieren.

Illustration des Autoscaling und der Belegung der Nodes
Abb. 3: Illustration des Autoscaling und der Belegung der Nodes. Die Breite der Balken entspricht dem Ressourcenbedarf der Pods bzw. der Kapazität der Nodes.

Um nicht zu verwirren: Letztlich ist jeder laufende Container, also jede Arbeitslast, ein Pod. Im Falle der Bereitstellung einer Anwendung geschieht das technisch über ein Deployment, zeitlich begrenzte Rechenlasten sind hingegen Jobs. Persistente Speicher wie Datenbanken werden mit StatefulSets verwaltet. Die folgende Abbildung gibt einen Überblick über die Begriffe:

Deployment-Controller
Abb. 4: Was ist was in Kubernetes? Im Deployment wird angegeben was gewünscht ist; der Deployment-Controller kümmert sich um das Erstellen, den Erhalt und das Skalieren der Modell-Container, welche denn als einzelne Pods auf den Nodes laufen. Jobs und StatefulSets funktionieren analog mit ihrem eigenen Controller.

3.    Jobs

Mit Kubernetes Jobs können sowohl einmalige als auch wiederkehrende Jobs (sog. CronJobs) in Form eines Container-Deployment auf dem Cluster ausgeführt werden.

Im einfachsten Fall können diese wie ein Skript gesehen werden, welches für Wartungs- oder Aufbereitungsarbeiten von beispielsweise Datenbanken genutzt werden kann. Des Weiteren verwendet man diese auch zum Batch-Processing, wenn zum Beispiel Deep Learning Modelle auf größere Datenmengen angewandt werden sollen und es sich aber nicht lohnt das Modell durchgehend auf dem Cluster zu halten. Der Modell-Container wird hier eigens hochgefahren, erhält Zugriff auf das gewünschte Dataset, führt seine Inferenz darüber aus, speichert die Ergebnisse und fährt sich herunter. Auch für die Herkunft und anschließende Speicherung der Daten ist man hier flexibel, so können eigene oder Cloud Datenbanken, Bucket/Objekt-Speicher oder auch lokale Daten und Logging-Frameworks angebunden werden.

Für wiederkehrende CronJobs kann ein einfaches Zeitschema spezifiziert werden, sodass beispielsweise nachts bestimmte Kundendaten, -transaktionen oder ähnliches verarbeitet werden. Mit Natural Language Processing können so zum Beispiel nachts automatisch Pressespiegel erstellt werden, welche am folgenden Morgen ausgewertet bereitstehen: Nachrichten zu einem Unternehmen, dessen Branche, Wirtschaftsstandorte, Kunden, usw. können aggregiert oder bezogen werden, mit NLP ausgewertet, zusammengefasst, und mit Stimmungsbildern präsentiert oder nach Themen/Inhalten geordnet werden.

Auch arbeitsintensive ETL (Extract Transform Load) Prozesse können so außerhalb der Geschäftszeiten durchgeführt oder vorbereitet werden.

4.    Rolling Updates

Soll ein Deployment auf die neuste Version gebracht werden, oder muss ein Rollback auf eine ältere Version vollzogen werden, können in Kubernetes Rolling Updates angestoßen werden. Diese garantieren durchgehende Erreichbarkeit der Anwendungen und Modelle innerhalb einer Continuous Integration/Continuous Deployment Pipeline.

Ein solches Rollout kann reibungslos in einem oder wenigen Schritten angestoßen und überwacht werden. Durch eine Rollout-History besteht auch die Möglichkeit, nicht nur auf eine vorherige Containerversion zurückzuspringen, sondern auch die vorherigen Deployment-Parameter wiederhergestellt werden, sprich Mindest- und Höchstanzahl der Nodes, welche Ressourcengruppe (GPU Nodes, CPU Nodes mit wenig/viel RAM,…), Health-Checks usw.

Wird ein Rolling Update angestoßen, werden die jeweiligen bestehenden Pods so lange am Laufen und erreichbar gehalten, bis dieselbe Anzahl an neuen Pods hochgefahren und zugänglich sind. Hier gibt es sowohl Methoden, um zu garantieren, dass keine Requests verloren gehen, wie auch Parameter, die für den Wechsel eine Mindesterreichbarkeit oder einen maximalen Überschuss an Pods regeln.

Illustration eines Rolling Updates
Abb. 5: Illustration eines Rolling Updates.

Die Abbildung 5 veranschaulicht das Rolling Update.

1) Die bisher aktuelle Version einer Anwendung liegt mit 2 Replicas auf dem Kubernetes Cluster und ist gewohnt ansprechbar.

2) Ein Rolling Update auf Version V2 wird gestartet, dieselbe Anzahl an Pods wie für V1 werden erstellt.

3) Sobald die neuen Pods den Zustand „Running“ haben und ggf. Health-Checks absolviert wurden, damit also funktional sind, werden die Container der älteren Version heruntergefahren.

4) Die älteren Pods sind entfernt und die Ressourcen wieder freigegeben.

Der DevOps- und Zeitaufwand ist hierbei marginal, intern ändern sich keine Hostnamen oder ähnliches, während der Dienst aus Sicht der Konsumierenden wie bisher in gewohnter Weise ansprechbar ist (gleiche IP, URL, …) und lediglich auf die neuste Version gebracht wurde.

5.    Platform/Infrastructure as a Service

Natürlich lässt sich ein Kubernetes Cluster auch lokal auf eigener Hardware on-premises einrichten sowie auf teilweise vorgefertigten Lösungen wie DGX Workbenches.

Einige unserer Kunden haben strikte Richtlinien oder Auflagen bezüglich (Data-) Compliance oder Informationssicherheit, und möchten nicht, dass möglicherweise sensible Daten das Unternehmen verlassen. Weiterhin kann so vermieden werden, dass der Datenverkehr über nicht-europäische Knotenpunkte fließt oder generell in ausländischen Rechenzentren landet.

Erfahrungsgemäß ist dies aber nur in einem sehr geringen Anteil der Fall. Durch Verschlüsselung, Rechtemanagement und SLAs der Betreiber erachten wir die Verwendung von Cloud-Diensten und -Rechenzentren als allgemein sicher und verwenden diese auch für größere Projekte. Diesbezüglich sind auch Deployment, Wartung, CI/CD Pipelines dank Methoden der Containerization (Docker) und Abstraktion (Kubernetes) größtenteils identisch und einfach zu verwenden.

Alle großen Cloud-Betreiber wie Google (GCP), Amazon (AWS) und Microsoft (Azure), aber auch kleinere Anbieter und bald sogar spannende neue deutsche Projekte, bieten sehr ähnliche Kubernetes Dienste an. Dadurch wird es noch einfacher, ein Projekt oder Modell bereitzustellen und vor allem zu skalieren, da durch auto-scaling das Cluster je nach Ressourcenbedarf erweitert oder verkleinert werden kann. Dies entbindet uns aus technischer Sicht größtenteils davon die Nachfrage eines Dienstes abschätzen zu müssen, während die Rentabilität und Kostenstruktur gleichbleiben. Weiterhin können die Dienste auch in unterschiedlichen (geographischen) Zonen gehostet und betrieben werden, um schnellste Erreichbarkeit und Redundanz zu garantieren.

6.    Node-Vielfalt

Die Cloud-Betreiber bieten eine große Anzahl unterschiedlicher Node-Typen an, um für alle Anwendungsfälle vom einfacheren Webservice bis hin zu High Performance Computing alle Ressourcenanforderungen zu befriedigen. Besonders im Anwendungsfeld Deep Learning lassen sich so die immer größer werdenden Modelle stets auf der benötigten neuesten Hardware trainieren und bereitstellen.

Während wir beispielsweise für kleinere NLP Zwecke Nodes mit einer durchschnittlichen CPU und geringem Arbeitsspeicher verwenden, lassen sich große Transformer-Modelle im gleichen Cluster auf GPU-Nodes deployen, was deren Verwendung effektiv erst ermöglicht und gleichzeitig die Inferenz (Anwendung des Modells) um Faktor 20 beschleunigen kann. Da neuerdings die Bedeutung dedizierter Hardware für Neuronale Netze stetig zunimmt, bietet Google auch Zugriff auf die eigens entwickelten, für Tensorflow optimierten TPUs an.

Die Organisation und Gruppierung all dieser unterschiedlichen Nodes erfolgt in Kubernetes in sog. Node Pools. Diese können im Deployment ausgewählt bzw. angegeben werden, sodass den Pods der Modelle die richtigen Ressourcen zugeteilt werden.

7.    Cluster Autoscaling

Das Ausmaß der Nutzung von Modellen oder Diensten, intern oder durch Kunden, ist oftmals nicht absehbar oder schwankt zeitlich stark. Mit einem Cluster Autoscaler können automatisch neue Nodes erstellt werden, oder nicht benötigte „leerstehende“ Nodes entfernt werden. Auch hier kann ein Minimum an Nodes angegeben werden, welche immer bereitstehen sollen sowie, wenn gewünscht, auch eine maximale Anzahl, die nicht überschritten werden kann, um ggf. die Kosten zu deckeln.

8.    Anbindung anderer Dienste

Prinzipiell können Cloud Dienste verschiedener Anbieter kombiniert werden, komfortabler und einfacher ist jedoch die Nutzung eines Anbieters (Beispiel Google GCP). Somit können Dienste wie Datenbuckets, Container-Registry, Lambda Funktionen Cloud-intern ohne große Authentifizierungsprozesse eingebunden und verwendet werden. Des Weiteren ist gerade in einer Microservice-Architektur die Netzwerkkommunikation unter den einzelnen Hosts (Anwendungen, Modelle) wichtig und innerhalb eines Anbieters erleichtert. Hier kann auch Zugangskontrolle/RBAC implementiert werden, sowie mehrere Cluster oder Projekte mit einem Virtuellen Netzwerk überbrückt werden, um die Zuständigkeits- und Kompetenzbereiche besser zu trennen.

Umfeld und zukünftige Entwicklungen

Die steigende Nutzung und Verbreitung von Kubernetes haben ein ganzes Umfeld an nützlichen Tools, wie auch Weiterentwicklungen und weitere Abstraktionen mit sich gebracht, welche dessen Verwendung weiter erleichtern.

Tools und Pipelines basierend auf Kubernetes

Mit Kubeflow lässt sich beispielsweise das Training von Machine Learning Modellen als TensorFlow Training Job anstoßen und fertige Modelle mit TensorFlow Serving bereitstellen.

Der ganze Prozess kann auch in eine Pipeline verpackt werden, welche dann mit Verweis auf Trainings-, Validation- und Testdaten in Speicherbuckets das Training verschiedener Modelle durchführt, überwacht, deren Metriken loggt und die Modell-Performance vergleicht. Der Workflow beinhaltet auch die Aufbereitung der Inputdaten, sodass nach erstmaligem Aufbau der Pipeline einfach Experimente zur Exploration von Modellarchitekturen und Hyperparameter-Tuning angestellt werden können

Serverless

Durch Serverless Deployment Verfahren wie Cloud Run oder Amazon Fargate wird ein weiterer Abstraktionsschritt weg von den technischen Anforderungen unternommen. Hiermit können Container binnen Sekunden deployed werden, und skalieren wie Pods auf einem Kubernetes Cluster, ohne dass man dieses überhaupt erstellen oder warten muss. Dieselbe Infrastruktur wurde also noch einmal in ihrer Benutzung vereinfacht. Nach dem Prinzip pay-per-use wird nur die Zeit berechnet, in welcher der Code wirklich aufgerufen und ausgeführt wird.

Fazit

Kubernetes ist heute zu einer zentralen Säule im Machine Learning Deployment geworden. Der Weg von der Daten- und Modellexploration zum Prototyp und schließlich in die Produktion ist durch Bibliotheken wie PyTorch, TensorFlow und Keras zum einen enorm verschlankt und vereinfacht worden. Gleichzeitig können diese Methoden bei Bedarf aber auch enorm detailliert verwendet werden, um maßgeschneiderte Komponenten zu entwickeln oder mittels Transfer Learning bestehende Modelle einzubinden und anzupassen. Container Technologien wie Docker erlauben im Anschluss, das Ergebnis mit all dessen Anforderungen und Abhängigkeiten zu bündeln und ohne weiteren Aufwand fast überall blitzschnell auszuführen. Im letzten Schritt ist deren Bereitstellung, Wartung und Skalierung mit Kubernetes ebenfalls ungemein vereinfacht und leistungsfähig geworden.

All dies erlaubt uns eigene Produkte sowie Lösungen für Kunden strukturiert zu entwickeln:

  • Die Komponenten und die Rahmeninfrastruktur haben eine hohe Wiederverwendbarkeit
  • Mit verhältnismäßig geringem Zeit- und Kostenaufwand kann ein erster Meilenstein oder Proof-of-Concept erreicht werden
  • Die weiterführende Entwicklungsarbeit folgt auf natürliche Weise weiter diesem Prozess
  • Fertige Deployments skalieren ohne zusätzlichen Aufwand, mit Kosten proportional zum Bedarf
  • Daraus folgt eine verlässliche Plattform mit planbarer Kostenstruktur

Wenn Sie sich im Anschluss an diesen Artikel weiter über einige zentrale Komponenten informieren möchten, haben wir hier noch einige interessante Beiträge über:

Quellen

 

Jonas Braun Jonas Braun

Management Summary

Machine Learning Projekte zu deployen und zu überwachen ist ein komplexes Vorhaben. Neben dem konsequenten Dokumentieren von Modellparametern und den dazugehörigen Evaluationsmetriken, besteht die Herausforderung vor allem darin, das gewünschte Modell in eine Produktivumgebung zu überführen. Sofern mehrere Personen an der Entwicklung beteiligt sind, ergeben sich zusätzlich Synchronisationsprobleme in Bezug auf die Entwicklungsumgebungen und Versionsstände der Modelle. Aus diesem Grund werden Tools zum effizienten Management von Modellergebnissen bis hin zu umfangreichen Trainings- und Inferenzpipelines benötigt.

In diesem Artikel werden die typischen Herausforderungen entlang des Machine Learning Workflows dargestellt und mit MLflow eine mögliche Lösungsplattform beschrieben. Zusätzlich stellen wir drei verschiedene Szenarien dar, mit deren Hilfe sich Machine Learning Workflows professionalisieren lassen:

  1. Einsteigervariante:
    Modellparameter und Performance-Metriken werden über eine R/Python API geloggt und in einer GUI übersichtlich dargestellt. Zusätzlich werden die trainierten Modelle als Artefakt abgespeichert und können über APIs bereitgestellt werden.
  2. Fortgeschrittenes Modellmanagement:
    Neben dem Tracking von Parametern und Metriken werden bestimmte Modelle geloggt und versioniert. Dies ermöglicht ein kontrolliertes Monitoring und vereinfacht das Deployment von ausgewählten Modellversionen.
  3. Kollaboratives Workflowmanagement:
    Das Abkapseln von Machine Learning Projekten als Pakete oder Git Repositories und der damit einhergehenden lokalen Reproduzierbarkeit von Entwicklungsumgebungen, ermöglichen eine reibungslose Entwicklung von Machine Learning Projekten mit mehreren Beteiligten.

Je nach Reifegrad Ihres Machine Learning Projektes können die drei Szenarien als Inspiration für einen potenziellen Machine Learning Workflow dienen. Zum besseren Verständnis haben wir jedes Szenario detailliert ausgearbeitet und geben Empfehlungen hinsichtlich der zu verwendeten APIs und Deployment-Umgebungen.

Herausforderungen entlang des Machine Learning Workflows

Das Training von Machine Learning Modellen wird immer einfacher. Mittlerweile ermöglichen eine Vielzahl von Open Source Tools eine effiziente Datenaufbereitung sowie ein immer einfacheres Modelltraining und Deployment.

Der Mehrwert für Unternehmen entsteht vor allem durch das systematische Zusammenspiel von Modelltraining, in Form von Modellidentifikation, Hyperparametertuning und Fitting auf den Trainingsdaten, und Deployment, also dem Bereitstellen des Modells zur Berechnung von Vorhersagen. Insbesondere in frühen Phasen der Entwicklung von Machine Learning Initiativen wird dieses Zusammenspiel häufig nicht als kontinuierlicher Prozess etabliert. Ein Modell kann jedoch nur dann langfristig Mehrwerte generieren, wenn ein stabiler Produktionsprozess vom Modelltraining, über dessen Validierung bis hin zum Test und Deployment implementiert wird. Sofern dieser Prozess korrekt implementiert wird können bei der operativen Inbetriebnahme des Modells komplexe Abhängigkeiten und langfristig kostspielige Wartungsarbeiten entstehen [2]. Die folgenden Risiken sind hierbei besonders hervorzuheben

1. Gewährleistung von Synchronität

Häufig werden im explorativen Kontext Datenaufbereitungs- und Modellierungs-Workflows lokal entwickelt. Unterschiedliche Konfigurationen der Entwicklungsumgebungen oder gar der Einsatz von verschiedenen Technologien erschweren eine Reproduktion von Ergebnissen, insbesondere zwischen Entwickler*innen bzw. Teams. Zusätzlich ergeben sich potenzielle Gefahren hinsichtlich der Kompatibilität des Workflows, sofern mehrere Skripte in einer logischen Reihenfolge exekutiert werden müssen. Ohne einer entsprechenden Versionskontroll-Logik kann der Synchronisationsaufwand im Nachhinein nur mit großem Aufwand gewährleistet werden.

2. Aufwand der Dokumentation

Um die Performance des Modells zu bewerten, werden häufig im Anschluss an das Training Modellmetriken berechnet. Diese hängen von verschiedenen Faktoren ab, wie z.B. der Parametrisierung des Modells oder den verwendeten Einflussfaktoren. Diese Metainformationen über das Modell werden häufig nicht zentral gespeichert. Zur systematischen Weiterentwicklung und Verbesserung eines Modells ist es jedoch zwingend erforderlich, eine Übersicht über die Parametrisierung und Performance aller vergangenen Trainingsläufe zu haben.

3. Heterogenität von Modellformaten

Neben der Verwaltung von Modellparametern und Ergebnissen besteht die Herausforderung das Modell anschließend in die Produktionsumgebung zu überführen. Sofern verschiedene Modelle aus mehreren Paketen zum Training verwendet werden kann das Deployment aufgrund unterschiedlicher Pakete und Versionen schnell umständlich und fehleranfällig werden.

4. Wiederherstellung alter Ergebnisse

In einem typischen Machine Learning Projekt ergibt sich häufig die Situation, dass ein Modell über einen langen Zeitraum entwickelt wird. Beispielsweise können neue Features verwendet oder auch gänzlich neue Architekturen evaluiert werden. Nicht zwangsläufig führen diese Experimente zu besseren Ergebnissen. Sofern Experimente nicht sauber versioniert werden, besteht die Gefahr alte Ergebnisse nicht mehr nachbilden zu können.

Um diese und weitere Herausforderungen im Umgang und Management von Machine Learning Workflows zu lösen, wurden in den vergangenen Jahren verschiedene Tools entwickelt, wie beispielsweise TensorFlow TFX, cortex, Marvin oder MLFlow. Insbesondere letzteres ist aktuell eine der am häufigsten verwendeten Lösungen.

MLflow ist ein Open Source Projekt mit dem Ziel, das Beste aus existierenden ML Plattformen zu vereinen, um die Integration zu bestehenden ML Bibliotheken, Algorithmen und Deployment Tools so unkompliziert wie möglich zu gestalten [3]. Im Folgenden werden die wesentlichen MLflow Module vorgestellt und Möglichkeiten erörtert, mit der Machine Learning Workflows über MLflow abgebildet werden können.

MLflow Services

MLflow besteht aus vier Komponenten: MLflow Tracking, MLflow Models, MLflow Projectsund MLflow Registry. Je nach Anforderung an das Experimental- und Deployment-Szenario können alle Services gemeinsam genutzt, oder auch einzelne Komponenten isoliert werden.

Mit MLflowTracking lassen sich alle Hyperparameter, Metriken (Modell-Performance) und Artefakte, wie bspw. Charts, loggen. MLflow Tracking bietet die Möglichkeit, für jeden Trainings- oder Scoring-Lauf eines Modells Voreinstellungen, Parameter und Ergebnisse für ein kollektives Monitoring zu sammeln. Die geloggten Ergebnisse lassen sich in einer GUI visualisieren oder alternativ über eine REST API ansprechen.

Das Modul MLflow Models fungiert als Schnittstelle zwischen Technologien und ermöglicht ein vereinfachtes Deployment. Ein Modell wird je nach Typ als Binary, z.B, als reine Python-Funktion oder als Keras-, oder H2O-Modell gespeichert. Man spricht hierbei von den sogenannten model flavors. Weiterhin stellt MLflow Models eine Unterstützung zur Modellbereitstellung auf verschiedenen Machine Learning Cloud Services bereit, z.B. für AzureML und Amazon Sagemaker.

MLflow Projects dienen dazu, einzelne ML-Projekte in einem Paket oder Git-Repository abzukapseln. Die Basiskonfigurationen des jeweiligen Environments werden über eine YAML-Datei festgelegt. Über diese kann z.B. gesteuert werden, wie genau das conda-Environment parametrisiert ist, das im Falle einer Ausführung von MLflow erstellt wird. Durch MLflow Projects können Experimente, die lokal entwickelt wurden, auf anderen Rechnern in der gleichen Umgebung ausgeführt werden. Dies ist bspw. bei der Entwicklung in kleineren Teams von Vorteil.

Ein zentralisiertes Modellmanagement bietet MLflow Registry. Ausgewählte MLflow Models können darin registriert und versioniert werden. Ein Staging-Workflow ermöglicht ein kontrolliertes Überführen von Modellen in die Produktivumgebung. Der gesamte Prozess lässt sich wiederum über eine GUI oder eine REST API steuern.

Beispiele für Machine Learning Pipelines mit MLflow

Im Folgenden werden mit Hilfe der o.g. MLflow Module drei verschiedene ML Workflow-Szenarien dargestellt. Diese steigern sich von Szenario zu Szenario hinsichtlich der Komplexität. In allen Szenarien wird ein Datensatz mittels eines Python Skripts in eine Entwicklungsumgebung geladen, verarbeitet und ein Machine Learning Modell trainiert. Der letzte Schritt stellt in allen Szenarien ein Deployment des ML Modells in eine beispielhafte Produktivumgebung dar.

1. Szenario – Die Einsteigervariante

Szenario 1 – Simple Metrics TrackingSzenario 1 – Simple Metrics Tracking

Szenario 1 bedient sich der Module MLflow Tracking und MLflow Models. Hierbei können mittels der Python API die Modellparameter und Metriken der einzelnen Runs auf dem MLflow Tracking Server Backend Store gespeichert und das entsprechende MLflow Model File als Artefakt auf dem MLflow Tracking Server Artifact Store abgelegt werden. Jeder Run wird hierbei einem Experiment zugeordnet. Beispielsweise könnte ein Experiment ‚fraud_classification‘ lauten und ein Run wäre ein bestimmtes ML Modell mit einer Hyperparameterkonfiguration und den entsprechenden Metriken. Jeder Run wird zur eindeutigen Zuordnung mit einer einzigartigen RunID abgespeichert.

Artikel MLFlow Tool Bild 01

Im Screenshot wird die MLflow Tracking UI beispielhaft nach der Ausführung eines Modelltrainings dargestellt. Der Server wird im Beispiel lokal gehostet. Selbstverständlich besteht auch die Möglichkeit den Server Remote, beispielsweise in einem Docker Container, innerhalb einer VM zu hosten. Neben den Parametern und Modellmetriken werden zudem der Zeitpunkt des Modelltrainings sowie der User und der Name des zugrundeliegenden Skripts geloggt. Klickt man auf einen bestimmten Run werden zudem weitere Informationen dargestellt, wie beispielsweise die RunID und die Modelltrainingsdauer.

Artikel MLFlow Tool Bild 02

Sofern man neben den Metriken zusätzlich noch weitere Artefakte, wie bspw. das Modell, geloggt hat, wird das MLflow Model Artifact ebenfalls in der Run-Ansicht dargestellt. In dem Beispiel wurde ein Modell aus dem sklearn.svm Package verwendet. Das File MLmodel enthält Metadaten mit Informationen über die Art und Weise, wie das Modell geladen werden soll. Zusätzlich dazu wird ein conda.yaml erstellt, das alle Paketabhängigkeiten des Environments zum Trainingszeitpunkt enthält. Das Modell selbst befindet sich als serialisierte Version unter model.pklund enthält die auf den Trainingsdaten optimierten Modellparameter.

Artikel MLFlow Tool Bild 03

Das Deployment des trainierten Modells kann nun auf mehrere Weisen erfolgen. Möchte man beispielsweise das Modell mit der besten Accuracy Metrik deployen, kann der MLflow Tracking Server über die Python API mlflow.list_run_infos angesteuert werden, um so die RunID des gesuchten Modells zu identifizieren. Nun kann der Pfad zu dem gewünschten Artefakt zusammengesetzt werden und das Modell bspw. über das Python Paket pickle geladen werden. Dieser Workflow kann nun über ein Dockerfile getriggert werden, was ein flexibles Deployment in die Infrastruktur Ihrer Wahl ermöglicht. MLFlow bietet für das Deployment auf Microsoft Azure und AWS zusätzliche gesonderte APIs an. Sofern das Modell bspw. auf AzureML deployed werden soll, kann ein Azure ML Container Image mit der Python API mlflow.azureml.build_image erstellt werden, welches als Webservice nach Azure Container Instances oder Azure Kubernetes Service deployed werden kann. Neben dem MLflow Tracking Server besteht auch die Möglichkeit andere Ablagesysteme für das Artefakt zu verwenden, wie zum Beispiel Amazon S3, Azure Blob Storage, Google Cloud Storage, SFTP Server, NFS und HDFS.

2. Szenario – Fortgeschrittenes Modellmanagement

Szenario 2 – Advanced Model ManagementSzenario 2 – Advanced Model Management

Szenario 2 beinhaltet, neben den in Szenario 1 verwendeten Modulen, zusätzlich MLflow Model Registry als Modelmanagementkomponente. Hierbei besteht die Möglichkeit, aus bestimmten Runs die dort geloggten Modelle zu registrieren und zu verarbeiten. Diese Schritte können über die API oder GUI gesteuert werden. Eine Grundvoraussetzung, um die Model Registry zu nutzen, ist eine Bereitstellung des MLflow Tracking Server Backend Store als Database Backend Store. Um ein Modell über die GUI zu registrieren, wählt man einen bestimmten Run aus und scrollt in die Artefakt Übersicht.

Artikel MLFlow Tool Bild 04

Mit einem Klick auf Register Model öffnet sich ein neues Fenster, in dem ein Modell registriert werden kann. Sofern man eine neue Version eines bereits existierenden Modells registrieren möchte, wählt man das gesuchte Modell aus dem Dropdown Feld aus. Ansonsten kann jederzeit ein neues Modell angelegt werden. Nach dem Klick auf den Button Register erscheint in dem Reiter Models das zuvor registrierte Modell mit einer entsprechenden Versionierung.

Artikel MLFlow Tool Bild 05

Jedes Modell beinhaltet eine Übersichtsseite, bei der alle vergangenen Versionen dargestellt werden. Dies ist bspw. nützlich, um nachzuvollziehen, welche Modelle wann in Produktion waren.

Artikel MLFlow Tool Bild 06

Wählt man nun eine Modellversion aus, gelangt man auf eine Übersicht, bei der beispielsweise eine Modellbeschreibung angefügt werden kann. Ebenso gelangt man über den Link Source Run zu dem Run, aus dem das Modell registriert worden ist. Hier befindet sich auch das dazugehörige Artefakt, das später zum Deployment verwendet werden kann.

Artikel MLFlow Tool Bild 07

Zusätzlich können einzelne Modellversionen in dem Bereich Stage in festgelegte Phasen kategorisiert werden. Dieses Feature kann beispielsweise dazu genutzt werden, um festzulegen, welches Modell gerade in der Produktion verwendet wird oder dahin überführt werden soll. Für das Deployment kann, im Gegensatz zu Szenario 1, die Versionierung und der Staging-Status dazu verwendet werden, um das geeignete Modell identifizieren und zu deployen. Hierzu kann z.B. die Python API MlflowClient().search_model_versions verwendet werden, um das gewünschte Modell und die dazugehörige RunID zu filtern. Ähnlich wie in Szenario 1 kann dann das Deployment beispielsweise nach AWS Sagemaker oder AzureML über die jeweiligen Python APIs vollzogen werden.

3. Szenario – Kollaboratives Workflowmanagement

Szenario 3 – Full Workflow ManagementSzenario 3 – Full Workflow Management

Das Szenario 3 beinhaltet, neben denen in Szenario 2 verwendeten Modulen, zusätzlich noch das Modul MLflow Projects. Wie bereits erläutert, eignen sich MLflow Projects besonders gut für kollaborative Arbeiten. Jedes Git Repository oder jede lokale Umgebung kann hierbei als Projekt fungieren und mittels eines MLproject File gesteuert werden. Hierbei können Paketabhängigkeiten in einem conda.yaml festgehalten und beim Starten des Projekts auf das MLproject File zugegriffen werden. Anschließend wird die entsprechende conda Umgebung mit allen Abhängigkeiten vor dem Training und Logging des Modells erstellt. Dies verhindert den Bedarf eines manuellen Angleichens der Entwicklungsumgebungen aller beteiligten Entwickler*innen und garantiert zudem standardisierte und vergleichbare Ergebnisse aller Runs. Insbesondere letzteres ist erforderlich im Deployment Kontext, da allgemein nicht garantiert werden kann, dass unterschiedliche Package-Versionen dieselben Modellartefakte produzieren. Anstelle einer conda Umgebung kann auch eine Docker Umgebung mittels eines Dockerfiles definiert werden. Dies bietet den Vorteil, dass auch von Python unabhängige Paketabhängigkeiten festgelegt werden können. Ebenso ermöglichen MLflow Projects durch die Anwendung unterschiedlicher commit hashes oder branch names das Verwenden verschiedener Projektstände, sofern ein Git Repository verwendet wird.

Ein interessanter Use Case hierbei ist die modularisierte Entwicklung von Machine Learning Trainingspipelines [4]. Hierbei kann bspw. die Datenaufbereitung vom Modelltraining entkoppelt und parallel weiterentwickelt werden, während parallel ein anderes Team einen unterschiedlichen branch name verwendet, um das Modell zu trainieren. Hierbei muss lediglich beim Starten des Projektes im MLflow Projects File ein unterschiedlicher branch name als Parameter verwendet werden. Die finale Datenaufbereitung kann im Anschluss auf denselben branch name gepusht werden, der zum Modelltraining verwendet wird und wäre somit bereits vollständig in der Trainingspipeline implementiert. Das Deployment kann ebenfalls als Teilmodul innerhalb der Projektpipeline mittels eines Python Skripts über das ML Project File gesteuert werden und analog zu Szenario 1 oder 2 auf eine Plattform Ihrer Wahl erfolgen.

Fazit und Ausblick

MLflow bietet eine flexible Möglichkeit den Machine Learning Workflow robust gegen die typischen Herausforderungen im Alltag eines Data Scientists zu gestalten, wie beispielsweise Synchronisationsprobleme aufgrund unterschiedlicher Entwicklungsumgebungen oder fehlendes Modellmanagement. Je nach Reifegrad des bestehenden Machine Learning Workflows können verschiedene Services aus dem MLflow Portfolio verwendet werden, um eine höhere Professionalisierungsstufe zu erreichen.

Im Artikel wurden drei, in der Komplexität aufsteigende, Machine Learning Workflows exemplarisch dargestellt. Vom einfachen Logging der Ergebnisse in einer interaktiven UI, bis hin zu komplexeren, modularen Modellierungspipelines können MLflow Services unterstützen. Logischerweise ergeben sich auch außerhalb des MLflow Ökosystems Synergien mit anderen Tools, wie zum Beispiel Docker/Kubernetes zur Modellskalierung oder auch Jenkins zur Steuerung der CI/CD Pipeline. Sofern noch weiteres Interesse an MLOps Herausforderungen und Best Practices besteht verweise ich auf das von uns kostenfrei zur Verfügung gestellte Webinar zu MLOps von unserem CEO Sebastian Heinz.

Quellen

John Vicente John Vicente

In den letzten drei Beiträgen dieser Serie haben wir erklärt, wie man ein Deep-Learning-Modell trainiert, um ein Auto anhand seiner Marke und seines Modells zu klassifizieren, basierend auf einem Bild des Autos (Teil 1), wie man dieses Modell aus einem Docker-Container mit TensorFlow Serving einsetzt (Teil 2) und wie man die Vorhersagen des Modells erklärt (Teil 3). In diesem Beitrag lernt ihr, wie ihr mit Dash eine ansprechende Oberfläche um unseren Auto-Modell-Classifier herum bauen könnt.

Wir werden unsere Machine Learning-Vorhersagen und -Erklärungen in ein lustiges und spannendes Spiel verwandeln. Wir präsentieren den Anwender*innen zunächst ein Bild von einem Auto. Die Anwender*innen müssen erraten, um welches Automodell und welche Marke es sich handelt – das Machine-Learning-Modell wird das Gleiche tun. Nach 5 Runden wird ausgewertet, wer die Automarke besser vorhersagen kann: die Anwender*innen oder das Modell.

Das Tech Stack: Was ist Dash?

Dash ist, wie der Name schon sagt, eine Software zum Erstellen von Dashboards in Python. In Python, fragen ihr euch? Ja – ihr müsst nichts direkt in HTML oder Javascript programmieren (obwohl ein grundlegendes Verständnis von HTML sicherlich hilfreich ist). Eine hervorragende Einführung findet ihr in dem ausgezeichneten Blogpost meines Kollegen Alexander Blaufuss.

Um das Layout und Styling unserer Web-App zu vereinfachen, verwenden wir auch Dash Bootstrap Components. Sie folgen weitgehend der gleichen Syntax wie die standardmäßigen Dash-Komponenten und fügen sich nahtlos in das Dash-Erlebnis ein.

Denkt daran, dass Dash für Dashboards gemacht ist – das heißt, es ist für Interaktivität gemacht, aber nicht unbedingt für Apps mit mehreren Seiten. Mit dieser Info im Hinterkopf werden wir in diesem Artikel Dash an seine Grenzen bringen.

Organisation ist alles – Die Projektstruktur

Um alles nachbauen zu können, solltet ihr euch unser GitHub-Repository ansehen, auf dem alle Dateien verfügbar sind. Außerdem könnt ihr alle Docker-Container mit einem Klick starten und loslegen.

Die Dateien für das Frontend selbst sind logischerweise in mehrere Teile aufgeteilt. Es ist zwar möglich, alles in eine Datei zu schreiben, aber man verliert leicht den Überblick und daher später schwer zu pflegen. Die Dateien folgen der Struktur des Artikels:

  1. In einer Datei wird das gesamte Layout definiert. Jeder Button, jede Überschrift, jeder Text wird dort gesetzt.
  2. In einer anderen Datei wird die gesamte Dashboard-Logik (sogenannte Callbacks) definiert. Dort wird z. B. definiert, was passieren soll, nachdem die Benutzer*innen auf eine Schaltfläche geklickt hat.
  3. Wir brauchen ein Modul, das 5 zufällige Bilder auswählt und die Kommunikation mit der Prediction and Explainable API übernimmt.
  4. Abschließend gibt es noch zwei Dateien, die die Haupteinstiegspunkte (Entry Points) zum Starten der App sind.

Erstellen der Einstiegspunkte – Das große Ganze

Beginnen wir mit dem letzten Teil, dem Haupteinstiegspunkt für unser Dashboard. Wenn ihr wisst, wie man eine Web-App schreibt, wie z. B. eine Dash-Anwendung oder auch eine Flask-App, ist euch das Konzept einer App-Instanz vertraut. Vereinfacht ausgedrückt, ist die App-Instanz alles. Sie enthält die Konfiguration für die App und schließlich das gesamte Layout. In unserem Fall initialisieren wir die App-Instanz direkt mit den Bootstrap-CSS-Dateien, um das Styling überschaubarer zu machen. Im gleichen Schritt exponieren wir die zugrundeliegende Flask-App. Die Flask-App wird verwendet, um das Frontend in einer produktiven Umgebung zu bedienen.

# app.py
import dash
import dash_bootstrap_components as dbc

# ...

# Initialize Dash App with Bootstrap CSS
app = dash.Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP],
)

# Underlying Flask App for productive deployment
server = app.server

Diese Einstellung wird für jede Dash-Anwendung verwendet. Im Gegensatz zu einem Dashboard benötigen wir eine Möglichkeit, mit mehreren URL-Pfaden umzugehen. Genauer gesagt, wenn die Benutzer*innen /attempt eingibt, wollen wir ihm erlauben, ein Auto zu erraten; wenn er /result eingibt, wollen wir das Ergebnis seiner Vorhersage anzeigen.

Zunächst definieren wir das Layout. Bemerkenswert ist, dass es zunächst grundsätzlich leer ist. Ihr findet dort eine spezielle Dash Core Component. Diese Komponente dient dazu, die aktuelle URL dort zu speichern und funktioniert in beide Richtungen. Mit einem Callback können wir den Inhalt auslesen, herausfinden, welche Seite die Benutzer*innen aufrufen möchte, und das Layout entsprechend rendern. Wir können auch den Inhalt dieser Komponente manipulieren, was praktisch eine Weiterleitung auf eine andere Seite ist. Das leere div wird als Platzhalter für das eigentliche Layout verwendet.

# launch_dashboard.py
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from app import app

# ...

# Set Layout
app.layout = dbc.Container(
    [dcc.Location(id='url', refresh=False),
     html.Div(id='main-page')])

Die Magie geschieht in der folgenden Funktion. Die Funktion selbst hat ein Argument, den aktuellen Pfad als String. Basierend auf dieser Eingabe gibt sie das richtige Layout zurück. Wenn die Benutzer*innen zum Beispiel zum ersten Mal auf die Seite zugreift, ist der Pfad / und das Layout daher start_page. Auf das Layout werden wir gleich noch im Detail eingehen; beachtet zunächst, dass wir an jedes Layout immer eine Instanz der App selbst und den aktuellen Spielzustand übergeben.

Damit diese Funktion tatsächlich funktioniert, müssen wir sie mit dem Callback Decorator schmücken. Jeder Callback benötigt mindestens eine Eingabe und mindestens eine Ausgabe. Eine Änderung des Inputs löst die Funktion aus. Der Eingang ist einfach die oben definierte Ortskomponente mit der Eigenschaft Pathname. Einfach ausgedrückt, aus welchem Grund auch immer sich der Pfad ändert, wird diese Funktion ausgelöst. Die Ausgabe ist das neue Layout, gerendert in dem zuvor zunächst leeren div.

# launch_dashboard.py
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate

# ...

@app.callback(Output('main-page', 'children'), [Input('url', 'pathname')])
def display_page(pathname: str) -> html:
    """Function to define the routing. Mapping routes to layout.

    Arguments:
        pathname {str} -- pathname from url/browser

    Raises:
        PreventUpdate: Unknown/Invalid route, do nothing

    Returns:
        html -- layout
    """
    if pathname == '/attempt':
        return main_layout(app, game_data, attempt(app, game_data))

    elif pathname == '/result':
        return main_layout(app, game_data, result(app, game_data))

    elif pathname == '/finish':
        return main_layout(app, game_data, finish_page(app, game_data))

    elif pathname == '/':
        return main_layout(app, game_data, start_page(app, game_data))

    else:
        raise PreventUpdate

Layout – Schön & Shiny

Beginnen wir mit dem Layout unserer App – wie soll sie aussehen? Wir haben uns für ein relativ einfaches Aussehen entschieden. Wie ihr in der Animation oben sehen könnt, besteht die App aus drei Teilen: dem Header, dem Hauptcontent und dem Footer. Der Header und der Footer sind auf jeder Seite gleich, nur der Hauptinhalt ändert sich. Einige Layouts aus dem Hauptcontent sind in der Regel eher schwierig zu erstellen. Zum Beispiel besteht die Ergebnisseite aus vier Boxen. Die Boxen sollten immer die gleiche Breite von genau der Hälfte der verwendeten Bildschirmgröße haben, können aber je nach Bildgröße in der Höhe variieren. Sie dürfen sich aber nicht überlappen, usw. Von den Cross-Browser-Inkompatibilitäten ganz zu schweigen.

Ihr könnt euch sicher vorstellen, dass wir leicht mehrere Arbeitstage damit hätten verbringen können, das optimale Layout zu finden. Glücklicherweise können wir uns wieder einmal auf Bootstrap und das Bootstrap Grid System verlassen. Die Hauptidee ist, dass ihr so viele Zeilen wie ihr wollt (zwei, im Fall der Ergebnisseite) und bis zu 12 Spalten pro Zeile (ebenfalls zwei für die Ergebnisseite) erstellen könnt. Die Begrenzung auf 12 Spalten basiert auf der Tatsache, dass Bootstrap die Seite intern in 12 gleich große Spalten aufteilt. Ihr müsst nur mit einer einfachen CSS-Klasse definieren, wie groß die Spalte sein soll. Und was noch viel cooler ist: Ihr könnt mehrere Layouts einstellen, je nach Bildschirmgröße. Es wäre also nicht schwierig, unsere App vollständig responsive zu machen.

Um auf den Dash-Teil zurückzukommen, bauen wir eine Funktion für jedes unabhängige Layout-Teil. Den Header, den Footer und eine für jede URL, die die Benutzer*innen aufrufen könnte. Für den Header sieht das so aus:

# layout.py
import dash_bootstrap_components as dbc
import dash_html_components as html

# ...

def get_header(app: dash.Dash, data: GameData) -> html:
    """Layout for the header

    Arguments:
        app {dash.Dash} -- dash app instance
        data {GameData} -- game data

    Returns:
        html -- html layout
    """
    logo = app.get_asset_url("logo.png")

    score_user, score_ai = count_score(data)

    header = dbc.Container(
        dbc.Navbar(
            [
                html.A(
                    # Use row and col to control vertical alignment of logo / brand
                    dbc.Row(
                        [
                            dbc.Col(html.Img(src=logo, height="40px")),
                            dbc.Col(
                                dbc.NavbarBrand("Beat the AI - Car Edition",
                                                className="ml-2")),
                        ],
                        align="center",
                        no_gutters=True,
                    ),
                    href="/",
                ),
                # You find the score counter here; Left out for clarity
            ],
            color=COLOR_STATWORX,
            dark=True,
        ),
        className='mb-4 mt-4 navbar-custom')

    return header

Auch hier seht ihr, dass wir die App-Instanz und den globalen Spieldatenstatus an die Layout-Funktion übergeben. In einer perfekten Welt müssten wir mit keiner dieser Variablen im Layout herumspielen. Leider ist das eine der Einschränkungen von Dash. Eine perfekte Trennung von Layout und Logik ist nicht möglich. Die App-Instanz wird benötigt, um dem Webserver mitzuteilen, dass er das STATWORX-Logo als statische Datei ausliefern soll.

Natürlich könnte man das Logo von einem externen Server ausliefern, das machen wir ja auch für die Fahrzeugbilder, aber nur für ein Logo wäre das ein bisschen zu viel des Guten. Für die Spieldaten müssen wir den aktuellen Punktestand des Benutzers und der KI berechnen. Alles andere ist entweder normales HTML oder Bootstrap-Komponenten. Wer sich damit nicht auskennt, den kann ich noch einmal auf den Blogpost von meinem Kollegen Alexander verweisen oder auf eines der zahlreichen HTML-Tutorials im Internet.

Callbacks – Reaktivität einführen

Wie bereits erwähnt, sind Callbacks das Mittel der Wahl, um das Layout interaktiv zu gestalten. In unserem Fall bestehen sie hauptsächlich aus der Handhabung des Dropdowns sowie der Button Klicks. Während die Dropdowns relativ einfach zu programmieren waren, bereiteten uns die Buttons einige Kopfschmerzen.

Einem guten Programmierstandard folgend, sollte jede Funktion genau eine Verantwortung haben. Deshalb haben wir für jeden Button einen Callback eingerichtet. Nach einer Art Eingabevalidierung und Datenmanipulation ist das Ziel, die Benutzer*innen auf die folgende Seite umzuleiten. Während die Eingabe für den Callback das Button-Klick-Ereignis und möglicherweise einige andere Eingabeformulare ist, ist die Ausgabe immer die Location-Komponente, um die Benutzer*innen weiterzuleiten. Leider erlaubt Dash nicht, mehr als einen Callback zum gleichen Ausgang zu haben. Daher waren wir gezwungen, die Logik für jede Schaltfläche in eine Funktion zu quetschen.

Da wir die Benutzereingaben auf der Versuchsseite validieren mussten, haben wir die aktuellen Werte aus dem Dropdown an den Callback übergeben. Während das für die Versuchsseite einwandfrei funktionierte, funktionierte die Schaltfläche auf der Ergebnisseite nicht mehr, da keine Dropdowns zur Übergabe an die Funktion verfügbar waren. Wir mussten ein verstecktes, nicht funktionierendes Dummy-Dropdown in die Ergebnisseite einfügen, damit die Schaltfläche wieder funktionierte. Das ist zwar eine Lösung und funktioniert in unserem Fall einwandfrei, aber für eine umfangreichere Anwendung könnte es zu kompliziert sein.

Data Download – Wir brauchen Autos

Jetzt haben wir eine schöne App mit funktionierenden Buttons und so weiter, aber die Daten fehlen noch. Wir müssen Bilder, Vorhersagen und Erklärungen in die App einbinden.

Die High-Level-Idee ist, dass jede Komponente für sich alleine läuft – zum Beispiel in einem eigenen Docker-Container mit eigenem Webserver. Alles ist nur lose über APIs miteinander gekoppelt. Der Ablauf ist der folgende:

  • Schritt 1: Abfrage einer Liste aller verfügbaren Auto-Images. Wähle zufällig 5 aus und fordere diese Bilder vom Webserver an.
  • Schritt 2: Sende für alle 5 Bilder eine Anfrage an die Vorhersage-API und parse das Ergebnis aus der API.
  • Schritt 3: Sende wiederum für alle 5 Bilder eine Anfrage an die Explainable-API und speichere das zurückgegebene Bild.

Kombiniert nun jede Ausgabe in der GameData-Klasse.

Aktuell speichern wir die GameData-Instanz als globale Variable. Das erlaubt uns, von überall darauf zuzugreifen. Das ist zwar theoretisch eine schlaue Idee, funktioniert aber nicht, wenn mehr als eine Benutzerin versucht, auf die App zuzugreifen. Derdie zweite Benutzerin wird den Spielstatus vom ersten sehen. Da wir planen, das Spiel auf Messen auf einer großen Leinwand zu zeigen, ist das für den Moment in Ordnung. In Zukunft könnten wir das Dashboard mit Shiny Proxy starten, so dass jeder Benutzer seinen eigenen Docker-Container mit einem isolierten globalen Status erhält.

Data Storage – Die Autos parken

Die native Dash-Methode besteht darin, benutzerspezifische Zustände in einer Store-Komponente zu speichern. Das ist im Grunde dasselbe wie die oben erläuterte Location-Komponente. Die Daten werden im Webbrowser gespeichert, ein Callback wird ausgelöst, und die Daten werden an den Server gesendet. Der erste Nachteil ist, dass wir bei jedem Seitenwechsel die gesamte Spieldateninstanz vom Browser zum Server übertragen müssen. Das kann ziemlich viel Traffic verursachen und verlangsamt das gesamte App-Erlebnis.

Außerdem müssen wir, wenn wir den Spielzustand ändern wollen, dies über einen Callback tun. Die Beschränkung auf einen Callback pro Ausgabe gilt auch hier. Unserer Meinung nach macht es nicht allzu viel aus, wenn Sie ein klassisches Dashboard haben; dafür ist Dash gedacht. Die Verantwortlichkeiten sind getrennt. In unserem Fall wird der Spielstatus von mehreren Komponenten aus aufgerufen und verändert. Wir haben Dash definitiv an seine Grenzen gebracht.

Eine weitere Sache, die ihr im Auge behalten solltet, wenn ihr euch entscheidet, eure eigene Microservice-App zu bauen, ist die Performance der API-Aufrufe. Anfänglich haben wir die berühmte requests Bibliothek verwendet. Während wir große Fans dieser Bibliothek sind, sind alle Anfragen blockierend. Daher wird die zweite Anfrage ausgeführt, sobald die erste abgeschlossen ist. Da unsere Anfragen relativ langsam sind (bedenkt, dass im Hintergrund vollwertige neuronale Netze laufen), verbringt die App viel Zeit mit Warten. Wir haben asynchrone Aufrufe mit Hilfe der Bibliothek aiohttp implementiert. Alle Anfragen werden nun parallel verschickt. Die App verbringt weniger Zeit mit Warten, und der Benutzer ist früher bereit zum Spielen.

Fazit und Hinweise

Auch wenn die Web-App einwandfrei funktioniert, gibt es ein paar Dinge, die zu beachten sind. Wir haben Dash verwendet, wohl wissend, dass es als Dashboarding-Tool gedacht ist. Wir haben es bis an die Grenzen und darüber hinaus getrieben, was zu einigen suboptimalen interessanten Design-Entscheidungen führte.

Zum Beispiel könnt ihr nur einen Callback pro Ausgabeparameter setzen. Mehrere Callbacks für dieselbe Ausgabe sind derzeit nicht möglich. Da das Routing von einer Seite zur anderen im Wesentlichen eine Änderung des Ausgabeparameters (‚url‘, ‚pathname‘) ist, muss jeder Seitenwechsel durch einen Callback geleitet werden. Das erhöht die Komplexität des Codes exponentiell.

Ein weiteres Problem ist die Schwierigkeit, Zustände über mehrere Seiten hinweg zu speichern. Dash bietet mit der Store Component die Möglichkeit, Benutzerdaten im Frontend zu speichern. Das ist eine hervorragende Lösung für kleine Apps; bei größeren steht man schnell vor dem gleichen Problem wie oben – ein Callback, eine Funktion zum Schreiben in den Store, reicht einfach nicht aus. Entweder ihr nutzt den globalen Zustand von Python, was schwierig wird, wenn mehrere Benutzer gleichzeitig auf die Seite zugreifen, oder ihr bindet einen cache ein.

In unserer Blogserie haben wir Ihnen gezeigt, wie ihr den gesamten Lebenszyklus eines Data-Science-Projekts durchlauft, von der Datenexploration über das Modelltraining bis hin zur Bereitstellung und Visualisierung. Dies ist der letzte Artikel dieser Serie, und wir hoffen, ihr habt beim Erstellen der Anwendung genauso viel gelernt wie wir.

Um das Durchblättern der vier Artikel zu erleichtern, sind hier die direkten Links:

  1. Transfer Learning mit ResNet
  2. Deployment von TensorFlow-Modellen in Docker mit TensorFlow Serving
  3. Erklärbarkeit von Deep Learning Modellen mit Grad-CAM
Dominique Lade Dominique Lade

In den letzten drei Beiträgen dieser Serie haben wir erklärt, wie man ein Deep-Learning-Modell trainiert, um ein Auto anhand seiner Marke und seines Modells zu klassifizieren, basierend auf einem Bild des Autos (Teil 1), wie man dieses Modell aus einem Docker-Container mit TensorFlow Serving einsetzt (Teil 2) und wie man die Vorhersagen des Modells erklärt (Teil 3). In diesem Beitrag lernt ihr, wie ihr mit Dash eine ansprechende Oberfläche um unseren Auto-Modell-Classifier herum bauen könnt.

Wir werden unsere Machine Learning-Vorhersagen und -Erklärungen in ein lustiges und spannendes Spiel verwandeln. Wir präsentieren den Anwender*innen zunächst ein Bild von einem Auto. Die Anwender*innen müssen erraten, um welches Automodell und welche Marke es sich handelt – das Machine-Learning-Modell wird das Gleiche tun. Nach 5 Runden wird ausgewertet, wer die Automarke besser vorhersagen kann: die Anwender*innen oder das Modell.

Das Tech Stack: Was ist Dash?

Dash ist, wie der Name schon sagt, eine Software zum Erstellen von Dashboards in Python. In Python, fragen ihr euch? Ja – ihr müsst nichts direkt in HTML oder Javascript programmieren (obwohl ein grundlegendes Verständnis von HTML sicherlich hilfreich ist). Eine hervorragende Einführung findet ihr in dem ausgezeichneten Blogpost meines Kollegen Alexander Blaufuss.

Um das Layout und Styling unserer Web-App zu vereinfachen, verwenden wir auch Dash Bootstrap Components. Sie folgen weitgehend der gleichen Syntax wie die standardmäßigen Dash-Komponenten und fügen sich nahtlos in das Dash-Erlebnis ein.

Denkt daran, dass Dash für Dashboards gemacht ist – das heißt, es ist für Interaktivität gemacht, aber nicht unbedingt für Apps mit mehreren Seiten. Mit dieser Info im Hinterkopf werden wir in diesem Artikel Dash an seine Grenzen bringen.

Organisation ist alles – Die Projektstruktur

Um alles nachbauen zu können, solltet ihr euch unser GitHub-Repository ansehen, auf dem alle Dateien verfügbar sind. Außerdem könnt ihr alle Docker-Container mit einem Klick starten und loslegen.

Die Dateien für das Frontend selbst sind logischerweise in mehrere Teile aufgeteilt. Es ist zwar möglich, alles in eine Datei zu schreiben, aber man verliert leicht den Überblick und daher später schwer zu pflegen. Die Dateien folgen der Struktur des Artikels:

  1. In einer Datei wird das gesamte Layout definiert. Jeder Button, jede Überschrift, jeder Text wird dort gesetzt.
  2. In einer anderen Datei wird die gesamte Dashboard-Logik (sogenannte Callbacks) definiert. Dort wird z. B. definiert, was passieren soll, nachdem die Benutzer*innen auf eine Schaltfläche geklickt hat.
  3. Wir brauchen ein Modul, das 5 zufällige Bilder auswählt und die Kommunikation mit der Prediction and Explainable API übernimmt.
  4. Abschließend gibt es noch zwei Dateien, die die Haupteinstiegspunkte (Entry Points) zum Starten der App sind.

Erstellen der Einstiegspunkte – Das große Ganze

Beginnen wir mit dem letzten Teil, dem Haupteinstiegspunkt für unser Dashboard. Wenn ihr wisst, wie man eine Web-App schreibt, wie z. B. eine Dash-Anwendung oder auch eine Flask-App, ist euch das Konzept einer App-Instanz vertraut. Vereinfacht ausgedrückt, ist die App-Instanz alles. Sie enthält die Konfiguration für die App und schließlich das gesamte Layout. In unserem Fall initialisieren wir die App-Instanz direkt mit den Bootstrap-CSS-Dateien, um das Styling überschaubarer zu machen. Im gleichen Schritt exponieren wir die zugrundeliegende Flask-App. Die Flask-App wird verwendet, um das Frontend in einer produktiven Umgebung zu bedienen.

# app.py
import dash
import dash_bootstrap_components as dbc

# ...

# Initialize Dash App with Bootstrap CSS
app = dash.Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP],
)

# Underlying Flask App for productive deployment
server = app.server

Diese Einstellung wird für jede Dash-Anwendung verwendet. Im Gegensatz zu einem Dashboard benötigen wir eine Möglichkeit, mit mehreren URL-Pfaden umzugehen. Genauer gesagt, wenn die Benutzer*innen /attempt eingibt, wollen wir ihm erlauben, ein Auto zu erraten; wenn er /result eingibt, wollen wir das Ergebnis seiner Vorhersage anzeigen.

Zunächst definieren wir das Layout. Bemerkenswert ist, dass es zunächst grundsätzlich leer ist. Ihr findet dort eine spezielle Dash Core Component. Diese Komponente dient dazu, die aktuelle URL dort zu speichern und funktioniert in beide Richtungen. Mit einem Callback können wir den Inhalt auslesen, herausfinden, welche Seite die Benutzer*innen aufrufen möchte, und das Layout entsprechend rendern. Wir können auch den Inhalt dieser Komponente manipulieren, was praktisch eine Weiterleitung auf eine andere Seite ist. Das leere div wird als Platzhalter für das eigentliche Layout verwendet.

# launch_dashboard.py
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from app import app

# ...

# Set Layout
app.layout = dbc.Container(
    [dcc.Location(id='url', refresh=False),
     html.Div(id='main-page')])

Die Magie geschieht in der folgenden Funktion. Die Funktion selbst hat ein Argument, den aktuellen Pfad als String. Basierend auf dieser Eingabe gibt sie das richtige Layout zurück. Wenn die Benutzer*innen zum Beispiel zum ersten Mal auf die Seite zugreift, ist der Pfad / und das Layout daher start_page. Auf das Layout werden wir gleich noch im Detail eingehen; beachtet zunächst, dass wir an jedes Layout immer eine Instanz der App selbst und den aktuellen Spielzustand übergeben.

Damit diese Funktion tatsächlich funktioniert, müssen wir sie mit dem Callback Decorator schmücken. Jeder Callback benötigt mindestens eine Eingabe und mindestens eine Ausgabe. Eine Änderung des Inputs löst die Funktion aus. Der Eingang ist einfach die oben definierte Ortskomponente mit der Eigenschaft Pathname. Einfach ausgedrückt, aus welchem Grund auch immer sich der Pfad ändert, wird diese Funktion ausgelöst. Die Ausgabe ist das neue Layout, gerendert in dem zuvor zunächst leeren div.

# launch_dashboard.py
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate

# ...

@app.callback(Output('main-page', 'children'), [Input('url', 'pathname')])
def display_page(pathname: str) -> html:
    """Function to define the routing. Mapping routes to layout.

    Arguments:
        pathname {str} -- pathname from url/browser

    Raises:
        PreventUpdate: Unknown/Invalid route, do nothing

    Returns:
        html -- layout
    """
    if pathname == '/attempt':
        return main_layout(app, game_data, attempt(app, game_data))

    elif pathname == '/result':
        return main_layout(app, game_data, result(app, game_data))

    elif pathname == '/finish':
        return main_layout(app, game_data, finish_page(app, game_data))

    elif pathname == '/':
        return main_layout(app, game_data, start_page(app, game_data))

    else:
        raise PreventUpdate

Layout – Schön & Shiny

Beginnen wir mit dem Layout unserer App – wie soll sie aussehen? Wir haben uns für ein relativ einfaches Aussehen entschieden. Wie ihr in der Animation oben sehen könnt, besteht die App aus drei Teilen: dem Header, dem Hauptcontent und dem Footer. Der Header und der Footer sind auf jeder Seite gleich, nur der Hauptinhalt ändert sich. Einige Layouts aus dem Hauptcontent sind in der Regel eher schwierig zu erstellen. Zum Beispiel besteht die Ergebnisseite aus vier Boxen. Die Boxen sollten immer die gleiche Breite von genau der Hälfte der verwendeten Bildschirmgröße haben, können aber je nach Bildgröße in der Höhe variieren. Sie dürfen sich aber nicht überlappen, usw. Von den Cross-Browser-Inkompatibilitäten ganz zu schweigen.

Ihr könnt euch sicher vorstellen, dass wir leicht mehrere Arbeitstage damit hätten verbringen können, das optimale Layout zu finden. Glücklicherweise können wir uns wieder einmal auf Bootstrap und das Bootstrap Grid System verlassen. Die Hauptidee ist, dass ihr so viele Zeilen wie ihr wollt (zwei, im Fall der Ergebnisseite) und bis zu 12 Spalten pro Zeile (ebenfalls zwei für die Ergebnisseite) erstellen könnt. Die Begrenzung auf 12 Spalten basiert auf der Tatsache, dass Bootstrap die Seite intern in 12 gleich große Spalten aufteilt. Ihr müsst nur mit einer einfachen CSS-Klasse definieren, wie groß die Spalte sein soll. Und was noch viel cooler ist: Ihr könnt mehrere Layouts einstellen, je nach Bildschirmgröße. Es wäre also nicht schwierig, unsere App vollständig responsive zu machen.

Um auf den Dash-Teil zurückzukommen, bauen wir eine Funktion für jedes unabhängige Layout-Teil. Den Header, den Footer und eine für jede URL, die die Benutzer*innen aufrufen könnte. Für den Header sieht das so aus:

# layout.py
import dash_bootstrap_components as dbc
import dash_html_components as html

# ...

def get_header(app: dash.Dash, data: GameData) -> html:
    """Layout for the header

    Arguments:
        app {dash.Dash} -- dash app instance
        data {GameData} -- game data

    Returns:
        html -- html layout
    """
    logo = app.get_asset_url("logo.png")

    score_user, score_ai = count_score(data)

    header = dbc.Container(
        dbc.Navbar(
            [
                html.A(
                    # Use row and col to control vertical alignment of logo / brand
                    dbc.Row(
                        [
                            dbc.Col(html.Img(src=logo, height="40px")),
                            dbc.Col(
                                dbc.NavbarBrand("Beat the AI - Car Edition",
                                                className="ml-2")),
                        ],
                        align="center",
                        no_gutters=True,
                    ),
                    href="/",
                ),
                # You find the score counter here; Left out for clarity
            ],
            color=COLOR_STATWORX,
            dark=True,
        ),
        className='mb-4 mt-4 navbar-custom')

    return header

Auch hier seht ihr, dass wir die App-Instanz und den globalen Spieldatenstatus an die Layout-Funktion übergeben. In einer perfekten Welt müssten wir mit keiner dieser Variablen im Layout herumspielen. Leider ist das eine der Einschränkungen von Dash. Eine perfekte Trennung von Layout und Logik ist nicht möglich. Die App-Instanz wird benötigt, um dem Webserver mitzuteilen, dass er das STATWORX-Logo als statische Datei ausliefern soll.

Natürlich könnte man das Logo von einem externen Server ausliefern, das machen wir ja auch für die Fahrzeugbilder, aber nur für ein Logo wäre das ein bisschen zu viel des Guten. Für die Spieldaten müssen wir den aktuellen Punktestand des Benutzers und der KI berechnen. Alles andere ist entweder normales HTML oder Bootstrap-Komponenten. Wer sich damit nicht auskennt, den kann ich noch einmal auf den Blogpost von meinem Kollegen Alexander verweisen oder auf eines der zahlreichen HTML-Tutorials im Internet.

Callbacks – Reaktivität einführen

Wie bereits erwähnt, sind Callbacks das Mittel der Wahl, um das Layout interaktiv zu gestalten. In unserem Fall bestehen sie hauptsächlich aus der Handhabung des Dropdowns sowie der Button Klicks. Während die Dropdowns relativ einfach zu programmieren waren, bereiteten uns die Buttons einige Kopfschmerzen.

Einem guten Programmierstandard folgend, sollte jede Funktion genau eine Verantwortung haben. Deshalb haben wir für jeden Button einen Callback eingerichtet. Nach einer Art Eingabevalidierung und Datenmanipulation ist das Ziel, die Benutzer*innen auf die folgende Seite umzuleiten. Während die Eingabe für den Callback das Button-Klick-Ereignis und möglicherweise einige andere Eingabeformulare ist, ist die Ausgabe immer die Location-Komponente, um die Benutzer*innen weiterzuleiten. Leider erlaubt Dash nicht, mehr als einen Callback zum gleichen Ausgang zu haben. Daher waren wir gezwungen, die Logik für jede Schaltfläche in eine Funktion zu quetschen.

Da wir die Benutzereingaben auf der Versuchsseite validieren mussten, haben wir die aktuellen Werte aus dem Dropdown an den Callback übergeben. Während das für die Versuchsseite einwandfrei funktionierte, funktionierte die Schaltfläche auf der Ergebnisseite nicht mehr, da keine Dropdowns zur Übergabe an die Funktion verfügbar waren. Wir mussten ein verstecktes, nicht funktionierendes Dummy-Dropdown in die Ergebnisseite einfügen, damit die Schaltfläche wieder funktionierte. Das ist zwar eine Lösung und funktioniert in unserem Fall einwandfrei, aber für eine umfangreichere Anwendung könnte es zu kompliziert sein.

Data Download – Wir brauchen Autos

Jetzt haben wir eine schöne App mit funktionierenden Buttons und so weiter, aber die Daten fehlen noch. Wir müssen Bilder, Vorhersagen und Erklärungen in die App einbinden.

Die High-Level-Idee ist, dass jede Komponente für sich alleine läuft – zum Beispiel in einem eigenen Docker-Container mit eigenem Webserver. Alles ist nur lose über APIs miteinander gekoppelt. Der Ablauf ist der folgende:

Kombiniert nun jede Ausgabe in der GameData-Klasse.

Aktuell speichern wir die GameData-Instanz als globale Variable. Das erlaubt uns, von überall darauf zuzugreifen. Das ist zwar theoretisch eine schlaue Idee, funktioniert aber nicht, wenn mehr als eine Benutzerin versucht, auf die App zuzugreifen. Derdie zweite Benutzerin wird den Spielstatus vom ersten sehen. Da wir planen, das Spiel auf Messen auf einer großen Leinwand zu zeigen, ist das für den Moment in Ordnung. In Zukunft könnten wir das Dashboard mit Shiny Proxy starten, so dass jeder Benutzer seinen eigenen Docker-Container mit einem isolierten globalen Status erhält.

Data Storage – Die Autos parken

Die native Dash-Methode besteht darin, benutzerspezifische Zustände in einer Store-Komponente zu speichern. Das ist im Grunde dasselbe wie die oben erläuterte Location-Komponente. Die Daten werden im Webbrowser gespeichert, ein Callback wird ausgelöst, und die Daten werden an den Server gesendet. Der erste Nachteil ist, dass wir bei jedem Seitenwechsel die gesamte Spieldateninstanz vom Browser zum Server übertragen müssen. Das kann ziemlich viel Traffic verursachen und verlangsamt das gesamte App-Erlebnis.

Außerdem müssen wir, wenn wir den Spielzustand ändern wollen, dies über einen Callback tun. Die Beschränkung auf einen Callback pro Ausgabe gilt auch hier. Unserer Meinung nach macht es nicht allzu viel aus, wenn Sie ein klassisches Dashboard haben; dafür ist Dash gedacht. Die Verantwortlichkeiten sind getrennt. In unserem Fall wird der Spielstatus von mehreren Komponenten aus aufgerufen und verändert. Wir haben Dash definitiv an seine Grenzen gebracht.

Eine weitere Sache, die ihr im Auge behalten solltet, wenn ihr euch entscheidet, eure eigene Microservice-App zu bauen, ist die Performance der API-Aufrufe. Anfänglich haben wir die berühmte requests Bibliothek verwendet. Während wir große Fans dieser Bibliothek sind, sind alle Anfragen blockierend. Daher wird die zweite Anfrage ausgeführt, sobald die erste abgeschlossen ist. Da unsere Anfragen relativ langsam sind (bedenkt, dass im Hintergrund vollwertige neuronale Netze laufen), verbringt die App viel Zeit mit Warten. Wir haben asynchrone Aufrufe mit Hilfe der Bibliothek aiohttp implementiert. Alle Anfragen werden nun parallel verschickt. Die App verbringt weniger Zeit mit Warten, und der Benutzer ist früher bereit zum Spielen.

Fazit und Hinweise

Auch wenn die Web-App einwandfrei funktioniert, gibt es ein paar Dinge, die zu beachten sind. Wir haben Dash verwendet, wohl wissend, dass es als Dashboarding-Tool gedacht ist. Wir haben es bis an die Grenzen und darüber hinaus getrieben, was zu einigen suboptimalen interessanten Design-Entscheidungen führte.

Zum Beispiel könnt ihr nur einen Callback pro Ausgabeparameter setzen. Mehrere Callbacks für dieselbe Ausgabe sind derzeit nicht möglich. Da das Routing von einer Seite zur anderen im Wesentlichen eine Änderung des Ausgabeparameters (‚url‘, ‚pathname‘) ist, muss jeder Seitenwechsel durch einen Callback geleitet werden. Das erhöht die Komplexität des Codes exponentiell.

Ein weiteres Problem ist die Schwierigkeit, Zustände über mehrere Seiten hinweg zu speichern. Dash bietet mit der Store Component die Möglichkeit, Benutzerdaten im Frontend zu speichern. Das ist eine hervorragende Lösung für kleine Apps; bei größeren steht man schnell vor dem gleichen Problem wie oben – ein Callback, eine Funktion zum Schreiben in den Store, reicht einfach nicht aus. Entweder ihr nutzt den globalen Zustand von Python, was schwierig wird, wenn mehrere Benutzer gleichzeitig auf die Seite zugreifen, oder ihr bindet einen cache ein.

In unserer Blogserie haben wir Ihnen gezeigt, wie ihr den gesamten Lebenszyklus eines Data-Science-Projekts durchlauft, von der Datenexploration über das Modelltraining bis hin zur Bereitstellung und Visualisierung. Dies ist der letzte Artikel dieser Serie, und wir hoffen, ihr habt beim Erstellen der Anwendung genauso viel gelernt wie wir.

Um das Durchblättern der vier Artikel zu erleichtern, sind hier die direkten Links:

  1. Transfer Learning mit ResNet
  2. Deployment von TensorFlow-Modellen in Docker mit TensorFlow Serving
  3. Erklärbarkeit von Deep Learning Modellen mit Grad-CAM
Dominique Lade Dominique Lade