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

Warum wir KI-Prinzipien brauchen

Künstliche Intelligenz verändert unsere Welt grundlegend. Algorithmen beeinflussen zunehmend, wie wir uns verhalten, denken und fühlen. Unternehmen rund um den Globus werden KI-Technologien zunehmend nutzen und ihre derzeitigen Prozesse und Geschäftsmodelle neu erfinden. Unsere sozialen Strukturen, die Art und Weise, wie wir arbeiten und wie wir miteinander interagieren, werden sich mit den Fortschritten der Digitalisierung, insbesondere der KI, verändern.

Neben ihrem sozialen und wirtschaftlichen Einfluss spielt KI auch eine wichtige Rolle bei einer der größten Herausforderungen unserer Zeit: dem Klimawandel. Einerseits kann KI Instrumente bereitstellen, um einen Teil dieser dringenden Herausforderung zu bewältigen. Andererseits wird die Entwicklung und Implementierung von KI-Anwendungen viel Energie verbrauchen und große Mengen an Treibhausgasen ausstoßen.

Risiken der KI

Mit dem Fortschritt einer Technologie, die einen so großen Einfluss auf alle Bereiche unseres Lebens hat, gehen große Chancen, aber auch große Risiken einher. Um Euch einen Eindruck von den Risiken zu vermitteln, haben wir sechs Beispiele herausgegriffen:

  • KI kann zur Überwachung von Menschen eingesetzt werden, zum Beispiel durch Gesichtserkennungssysteme. Einige Länder setzen diese Technologie bereits seit einigen Jahren intensiv ein.
  • KI wird in sehr sensiblen Bereichen eingesetzt. In diesen können schon kleine Fehlfunktionen dramatische Auswirkungen haben. Beispiele dafür sind autonomes Fahren, robotergestützte Chirurgie, Kreditwürdigkeitsprüfung, Auswahl von Bewerber:innen oder Strafverfolgung.
  • Der Skandal um Facebook und Cambridge Analytica hat gezeigt, dass Daten und KI-Technologien zur Erstellung psychografischer Profile genutzt werden können. Diese Profile ermöglichen die gezielte Ansprache von Personen mit maßgeschneiderten Inhalten. Beispielsweise zur Beeinflussung von politischen Wahlen. Dieses Beispiel zeigt die enorme Macht der KI-Technologien und die Möglichkeit für Missbrauch und Manipulation.
  • Mit den jüngsten Fortschritten in der Computer Vision Technologie können Deep Learning Algorithmen nun zur Erstellung von Deepfakes verwendet werden. Deepfakes sind realistische Videos oder Bilder von Menschen, in denen diese etwas tun oder sagen, was sie nie in der Realität getan oder gesagt haben. Die Möglichkeiten für Missbrauch dieser Technologie sind vielfältig.
  • KI-Lösungen werden häufig entwickelt, um manuelle Prozesse zu verbessern oder zu optimieren. Es wird Anwendungsfälle geben, bei denen menschliche Arbeit ersetzt wird. Dabei entstehen unterschiedlichste Herausforderungen, die nicht ignoriert, sondern frühzeitig angegangen werden müssen.
  • In der Vergangenheit haben KI-Modelle diskriminierende Muster der Daten, auf denen sie trainiert wurden, reproduziert. So hat Amazon beispielsweise ein KI-System in seinem Rekrutierungsprozess eingesetzt, das Frauen eindeutig benachteiligte.

Diese Beispiele machen deutlich, dass jedes Unternehmen und jede Person, die KI-Systeme entwickelt, sehr sorgfältig darüber nachdenken sollte, welche Auswirkungen das System auf die Gesellschaft, bestimmte Gruppen oder sogar Einzelpersonen haben wird oder haben könnte.

Daher besteht die große Herausforderung für uns darin, sicherzustellen, dass die von uns entwickelten KI-Technologien den Menschen helfen und sie befähigen, während wir gleichzeitig potenzielle Risiken minimieren.

Warum gibt es im Jahr 2022 keine offizielle Regelung?

Vielleicht fragt Ihr euch, warum es keine Gesetze gibt, die sich mit diesem Thema befassen. Das Problem bei neuen Technologien, insbesondere bei künstlicher Intelligenz, ist, dass sie sich schnell weiterentwickeln, manchmal sogar zu schnell.

Die jüngsten Veröffentlichungen neuer Sprachmodelle wie GPT-3 oder Computer Vision Modelle, z. B. DALLE-2, haben selbst die Erwartungen vieler KI-Expert:innen übertroffen. Die Fähigkeiten und Anwendungen der KI-Technologien werden sich schneller weiterentwickeln, als die Regulierung es kann. Und wir sprechen hier nicht von Monaten, sondern von Jahren.

Dabei ist zu erwähnen, dass die EU einen ersten Versuch in diese Richtung unternommen hat, indem sie eine Regulierung von künstlicher Intelligenz vorgeschlagen hat. In diesem Vorschlag wird jedoch darauf hingewiesen, dass die Verordnung frühestens in der zweiten Hälfte des Jahres 2024 für die anwendenden Unternehmen gelten könnte. Das sind Jahre, nachdem die oben beschriebenen Beispiele Realität geworden sind.

Unser Ansatz: statworx AI Principles

Die logische Konsequenz daraus ist, dass wir uns als Unternehmen selbst dieser Herausforderung stellen müssen. Und genau deshalb arbeiten wir derzeit an den statworx AI Principles, einer Reihe von Prinzipien, die uns bei der Entwicklung von KI-Lösungen leiten und Orientierung geben sollen.

Was wir bisher getan haben und wie wir dazu gekommen sind

In unserer Arbeitsgruppe „AI & Society“ haben wir begonnen, uns mit diesem Thema zu beschäftigen. Zunächst haben wir den Markt gescannt und viele interessante Paper gefunden. Allerdings sind wir zu dem Schluss gekommen, dass sich keins davon 1:1 auf unser Geschäftsmodell übertragen lässt. Oft waren diese Prinzipien oder Richtlinien sehr schwammig oder zu detailliert und zusätzlich ungeeignet für ein Beratungsunternehmen, das im B2B-Bereich als Dienstleister tätig ist. Also beschlossen wir, dass wir selbst eine Lösung entwickeln mussten.

In den ersten Diskussionen darüber wurden vier große Herausforderungen deutlich:

  • Einerseits müssen die AI Principles klar und für das breite Publikum verständlich formuliert sein, damit auch Nicht-Expert:innen sie verstehen. Andererseits müssen sie konkret sein, um sie in unseren Entwicklungsprozess integrieren zu können.
  • Als Dienstleister haben wir nur begrenzte Kontrolle und Entscheidungsgewalt über einige Aspekte einer KI-Lösung. Daher müssen wir verstehen, was wir entscheiden können und was außerhalb unserer Kontrolle liegt.
  • Unsere AI Principles werden nur dann einen nachhaltigen Mehrwert schaffen, wenn wir auch nach ihnen handeln können. Deshalb müssen wir sie in unseren Kundenprojekten anwenden und bewerben. Wir sind uns darüber im Klaren, dass Budgetzwänge, finanzielle Ziele und andere Faktoren dem entgegenstehen könnten, da es zusätzlichen Zeit- und Geldaufwand erfordert.
  • Außerdem ist nicht immer klar, was falsch und richtig ist. Unsere Diskussionen haben gezeigt, dass es viele unterschiedliche Auffassungen darüber gibt, was richtig und notwendig ist. Das bedeutet, dass wir eine gemeinsame Basis finden müssen, auf die wir uns als Unternehmen einigen können.

Unsere zwei wichtigsten Erkenntnisse

Eine wichtige Erkenntnis aus diesen Überlegungen war, dass wir zwei Dinge brauchen.

In einem ersten Schritt brauchen wir übergeordnete Grundsätze, die verständlich und klar sind und bei denen alle mit an Bord sind. Diese Grundsätze dienen als Leitidee und geben Orientierung bei der Entscheidungsfindung. In einem zweiten Schritt wird daraus ein Framework abgeleitet, welches diese Grundsätze in allen Phasen unserer Projekte in konkrete Maßnahmen übersetzt.

Die zweite wichtige Erkenntnis ist, dass es durchaus schwierig ist, diesen Prozess zu durchlaufen und sich diese Fragen zu stellen. Aber gleichzeitig auch, dass dies für jedes Unternehmen, das KI-Technologie entwickelt oder einsetzt, unvermeidlich ist.

 

Was kommt als nächstes?

Bis jetzt sind wir fast am Ende des ersten Schritts angelangt. Wir werden die statworx AI Principles bald über unsere Kanäle kommunizieren. Wenn Ihr euch ebenfalls in diesem Prozess befindet, würden wir uns freuen, mit Euch in Kontakt zu treten, um zu verstehen, wie ihr vorgegangen seid und was ihr dabei gelernt habt.

Quellen

https://www.nytimes.com/2019/04/14/technology/china-surveillance-artificial-intelligence-racial-profiling.html

https://www.nytimes.com/2018/04/04/us/politics/cambridge-analytica-scandal-fallout.html

https://www.reuters.com/article/us-amazon-com-jobs-automation-insight-idUSKCN1MK08G

https://digital-strategy.ec.europa.eu/en/policies/european-approach-artificial-intelligence

https://www.bundesregierung.de/breg-de/themen/umgang-mit-desinformation/deep-fakes-1876736

https://www.welt.de/wirtschaft/article173642209/Jobverlust-Diese-Jobs-werden-als-erstes-durch-Roboter-ersetzt.html

Jan Fischer Jan Fischer Jan Fischer Jan Fischer Jan Fischer Jan Fischer

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

Warum sich Sorgen machen? KI und die Klimakrise

Nach dem neuesten Bericht des Weltklimarats (IPCC) im August 2021 „ist es eindeutig, dass menschlicher Einfluss die Atmosphäre, das Meer und das Land erwärmt hat“ [1]. Zudem schreitet der Klimawandel schneller voran als gedacht. Basierend auf den neuesten Berechnungen ist die globale Durchschnittstemperatur zwischen 2010 und 2019 im Vergleich zu dem Zeitraum zwischen 1850 und 1900 aufgrund des menschlichen Einflusses um 1.07°C gestiegen. Außerdem war die CO2 Konzentration in der Atmosphäre in dieser Zeit „höher als zu irgendeiner Zeit in mindestens 2 Millionen Jahren“ [1].

Dessen ungeachtet nehmen die globalen CO2 Emissionen weiter zu, auch wenn es 2020 einen kleinen Rückgang gab [2], der wahrscheinlich auf das Coronavirus und die damit zusammenhängenden ökonomischen Auswirkungen zurückzuführen ist. Im Jahr 2019 wurden weltweit insgesamt 36.7 Gigatonnen (Gt) CO2 ausgestoßen [2]. Eine Gt entspricht dabei einer Milliarden Tonnen. Um das 1.5 °C Ziel noch mit einer geschätzten Wahrscheinlichkeit von 80% zu erreichen, blieben Anfang 2020 nur noch 300 Gt übrig [1]. Da 2020 und 2021 bereits vorüber sind und unter Annahme von circa 35 Gt CO2 Emissionen für jedes Jahr, beträgt das verbleibende CO2 -Budget nur rund 230 Gt. Bleibt der jährliche Ausstoß konstant, wäre dieses in den nächsten sieben Jahren aufgebraucht.

Im Jahr 2019 verursachten China, die USA und Indien die größten CO2-Emissionen. Deutschland ist zwar nur für ungefähr 2% aller globalen CO2 Emissionen verantwortlich, liegt mit 0.7 Gt aber immer noch auf dem siebten Platz (siehe nachfolgende Grafik). Zusammen genommen sind die 10 Länder mit dem größten CO2-Ausstoß für circa zwei Drittel aller CO2-Emissionen weltweit verantwortlich [2]. Die meisten dieser Länder sind hoch industrialisiert, wodurch es sehr wahrscheinlich ist, dass sie künstliche Intelligenz (KI) in den nächsten Jahrzenten verstärkt nutzen werden, um Ihre eigene Wirtschaft zu stärken.

Mit KI den CO2-Ausstoß reduzieren

Was genau hat jetzt KI mit dem Ausstoß von CO2 zu tun? Die Antwort ist: Einiges! Prinzipiell ist die Anwendung von KI wie zwei Seiten derselben Medaille [3]. Auf der einen Seite hat KI großes Potenzial, CO2-Emissionen durch genauere Vorhersagen oder die Verbesserung von Prozessen in vielen Industrien zu reduzieren. Beispielsweise kann KI zur Vorhersage extremer Wetterereignisse, der Optimierung von Lieferketten oder der Überwachung von Mooren eingesetzt werden [4, 5].

Nach einer aktuellen Schätzung von Microsoft und PwC kann die Verwendung von KI im Umweltbereich den Ausstoß der weltweiten Treibhausgase um bis zu 4.4% im Jahr 2030 senken [6]. Absolut gesehen handelt es sich dabei um eine Reduzierung der weltweiten Treibhausgasemissionen von 0.9 bis 2.4 Gt CO2e. Dies entspricht dem, aufgrund aktueller Werte prognostizierten, Ausstoß von Australien, Kanada und Japan im Jahr 2030 zusammen [7]. Der Begriff Treibhausgase beinhaltet hier zusätzlich zu CO2 noch andere Gase wie Methan, die ebenfalls den Treibhauseffekt der Erde verstärken. Um all diese Gase einfach zu messen, werden sie oft als CO2-Äquivalente angeben und als CO2e abgekürzt.

Der CO2-Fußabdruck von KI

Obwohl KI großes Potenzial hat, CO2-Emissionen zu reduzieren, stößt die Anwendung von KI selbst CO2 aus. Dies ist die Kehrseite der Medaille. Im Vergleich zum Jahr 2012 ist die geschätzte Menge an Rechenaufwand für das Training von Deep Learning (DL) Modellen im Jahr 2018 um das 300.000-fache gestiegen (siehe nachfolgende Grafik, [8]). Die Erforschung, das Training und die Anwendung von KI-Modellen benötigen daher eine immer größere Menge an Strom, aber natürlich auch an Hardware. Beides setzt letztlich CO2-Emissionen frei und verstärkt somit den Klimawandel.

Anmerkung: Die Grafik wurde ursprünglich in [8] veröffentlicht.

Leider ist es mir nicht gelungen, eine Studie ausfindig zu machen, die den CO2-Fußabdruck von KI insgesamt schätzt. Allerdings gibt es diverse Studien, die den CO2– oder CO2e-Ausstoß von Natural Language Processing (NLP) Modellen schätzen. Diese sind in den vergangenen Jahren immer akkurater und somit populärer geworden [9]. Basierend auf der nachfolgenden Tabelle hat das abschließende Training von Googles BERT Modell ungefähr so viel CO2e freigesetzt, wie ein Passagier bei einer Flugreise von New York nach San Francisco. Das Training anderer Modelle, wie bspw. des Transformerbig-Modells, haben zwar wesentlich weniger CO2e-Emissionen verursacht, doch ist das abschließende Training von KI-Modellen nur der letzte Baustein beim Finden des besten Modells. Bevor ein Modell zum letzten Mal trainiert wird, sind häufig bereits viele verschiedene Modelle getestet worden, um so die besten Parameterwerte zu bestimmen. Diese neuronale Architektursuche hat beim Transformerbig-Modell entsprechend viele CO2e-Emissionen verursacht, insgesamt circa fünf Mal so viele wie ein durchschnittliches Auto in seiner gesamten Lebenszeit. Wirf jetzt mal einen Blick auf die CO2e-Emissionen des GPT-3 Modells und stell dir vor, wie hoch der CO2e-Ausstoß bei der dazugehörigen neuronalen Architektursuche gewesen sein muss.

Comparison of selected human and AI carbon emissions
Emissionen durch Menschen Emissionen durch KI
Beispiel CO2e Emissionen (Tonnen) Training von NLP Modellen CO2e Emissionen (Tonnen)
Ein Passagier bei Flugreise
New York San Francisco
0.90 Transformerbig 0.09
Durchschnittlicher Mensch
ein Jahr
5.00 BERTbase 0.65
Durchschnittlicher Amerikaner
ein Jahr
16.40 GPT-3 84.74
Durchschnittliches Auto während
Lebenszeit inkl. Benzin
57.15 Neuronale Architektursuche
für Transformerbig
284.02

Anmerkung: Alle Werte sind aus [9] entnommen, außer der Werte für GPT-3 [17].

Was du als Data Scientist tun kannst, um deinen CO2-Fußabdruck zu verringern

Insgesamt gibt es ganz unterschiedliche Möglichkeiten, wie du als Data Scientist den CO2-Fußabdruck beim Training und Anwendung von KI-Modellen reduzieren kannst. Aktuell sind im KI-Bereich Machine Learning (ML) und Deep Learning (DL) am populärsten, deswegen findest du nachfolgend verschiedene Ansätze, um den CO2-Fußabdruck dieser Art KI-Modelle zu messen und zu reduzieren.

1. Sei dir der negativen Auswirkungen bewusst und berichte darüber

Es mag einfach klingen, aber sich der negativen Konsequenzen bewusst zu sein, die sich durch die Suche, das Training sowie die Anwendung von ML und DL Modellen ergeben, ist der erste Schritt, deinen CO2-Fußabdruck zu reduzieren. Zu verstehen, wie sich KI negativ auf die Umwelt auswirkt, ist entscheidend, um bereit zu sein, den zusätzlichen Aufwand bei der Messung und systematische Erfassung von CO2-Emissionen zu betreiben. Dies widerrum ist nötig, um den Klimawandel zu bekämpfen [8, 9, 10]. Solltest du also den ersten Teil über KI und die Klimakrise übersprungen haben, gehh zurück und lies ihn. Es lohnt sich!

2. Miss den CO2-Ausstoß deines Codes

Um die CO2-Emissionen deiner ML und DL Modelle transparent darzulegen, müssen diese zuerst gemessen werden. Zurzeit gibt es leider noch kein standardisiertes Konzept, um alle Nachhaltigkeitsaspekte von KI zu messen. Eines wird allerdings gerade entwickelt [11]. Bis dieses fertiggestellt ist, kannst du bereits beginnen, den Energieverbrauch und die damit verbundenen CO2-Emissionen deiner KI-Modelle offen zu legen [12]. Mit TensorFlow und PyTorch sind die ausgereiftesten Pakete für die Berechnung von ML und DL Modellen wahrscheinlich in der Programmiersprache Python verfügbar. Obwohl Python nicht die effizienteste Programmiersprache ist [13], war es im September 2021 erneut die populärste im PYPL Index [14]. Dementsprechend gibt es sogar drei Python Pakete, die du nutzen kannst, um den CO2-Fußabdruck beim Training deiner Modelle zu messen:

  • CodeCarbon [15, 16]
  • CarbonTracker [17]
  • Experiment Impact Tracker [18]

Meiner Auffassung nach sind die beiden Pakete, CodeCarbon und CarbonTracker, am einfachsten anzuwenden. Außerdem lässt sich CodeCarbon problemlos mit TensorFlow und CarbonTracker mit PyTorch kombinieren. Aus diesen Gründen findest du für jedes der beiden Pakete nachfolgend ein Beispiel.

Um beide Pakete zu testen, habe ich den MNIST Datensatz verwendet und jeweils ein einfaches Multilayer Perceptron (MLP) mit zwei Hidden Layern und jeweils 256 Neuronen trainiert. Um sowohl eine CPU- als auch GPU-basierte Berechnung zu testen, habe ich das Modell mit TensorFlow und CodeCarbon auf meinem lokalen PC (15 Zoll MacBook Pro mit 6 Intel Core i7 CPUs aus dem Jahr 2018) und das mit PyTorch und CarbonTracker in einem Google Colab unter Verwendung einer Tesla K80 GPU trainiert. Beginnen wir mit den Ergebnissen für TensorFlow und CodeCarbon.

# benötigte Pakete importieren
import tensorflow as tf
from codecarbon import EmissionsTracker

# Modeltraining vorbereiten
mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(256, activation=“relu“),
        tf.keras.layers.Dense(256, activation=“relu“),
        tf.keras.layers.Dense(10, activation=“softmax“),
    ]
)

loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

model.compile(optimizer=“adam“, loss=loss_fn, metrics=[„accuracy“])

# Modell trainieren und CO2 Emissionen berechnen
tracker = EmissionsTracker()
tracker.start()
model.fit(x_train, y_train, epochs=10)
emissions: float = tracker.stop()
print(emissions)

Nach der Ausführung des Codes erstellt CodeCarbon automatisch eine CSV-Datei, welche verschiedene Ergebnisparameter beinhaltet, wie Berechnungszeit in Sekunden, totaler Stromverbrauch durch die verwendete Hardware in kWh und die damit verbundenen CO2-Emissionen in kg. Das Training meines Modells dauerte insgesamt 112.15 Sekunden, verbrauchte 0.00068 kWh und verursachte 0.00047 kg CO2-Emissionen.

Als Grundlage für die Berechnungen mit PyTorch und CarbonTracker habe ich dieses Google Colab Notebook verwendet. Um auch hier ein Multilayer Perceptron zu berechnen und die dabei entstehenden CO2-Emissionen zu messen, habe ich einige Details des Notebooks geändert. Als erstes habe ich in Schritt 2 („Define Network“) das Convolutional Neural Network in ein Multilayer Perceptron geändert (Den Namen der Klasse „CNN“ habe ich beibehalten, damit der restliche Code im Notebook noch funktioniert.):

 class CNN(nn.Module):
  """Ein einfaches MLP Modell."""

  @nn.compact
  def __call__(self, x):
    x = x.reshape((x.shape[0], -1))  # flach machen
    x = nn.Dense(features=256)(x)
    x = nn.relu(x)
    x = nn.Dense(features=256)(x)
    x = nn.relu(x)
    x = nn.Dense(features=10)(x)
    x = nn.log_softmax(x)
    return x

Als zweites habe ich die Installation und den Import von CarbonTracker sowie die Messung der CO2-Emissionen in Schritt 14 („Train and evaluate“) eingefügt:

 !pip install carbontracker

from carbontracker.tracker import CarbonTracker

tracker = CarbonTracker(epochs=num_epochs)
for epoch in range(1, num_epochs + 1):
  tracker.epoch_start()

  # Vewendung des separaten PRNG keys, um Bilddaten zu permutieren
  rng, input_rng = jax.random.split(rng)
  # Optimierung für Trainings Batches
  state = train_epoch(state, train_ds, batch_size, epoch, input_rng)
  # Evaluation für Testdatensatz nach jeder Epoche 
  test_loss, test_accuracy = eval_model(state.params, test_ds)
  print(' test epoch: %d, loss: %.2f, accuracy: %.2f' % (
      epoch, test_loss, test_accuracy * 100))
  
  tracker.epoch_end()

tracker.stop()

Nachdem das leicht geänderte Google Colab Notebook bis zum eigentlichen Training des Modells ausgeführt wurde, gab CarbonTracker nach der ersten Trainingsepoche das nachfolgende Ergebnis aus:

 train epoch: 1, loss: 0.2999, accuracy: 91.25
 test epoch: 1, loss: 0.22, accuracy: 93.42
CarbonTracker:
Actual consumption for 1 epoch(s):
       Time:  0:00:15
       Energy: 0.000397 kWh
       CO2eq: 0.116738 g
       This is equivalent to:
       0.000970 km travelled by car
CarbonTracker:
Predicted consumption for 10 epoch(s):
       Time:  0:02:30
       Energy: 0.003968 kWh
       CO2eq: 1.167384 g
       This is equivalent to:
       0.009696 km travelled by car

Wie erwartet hat die GPU mehr Strom verbraucht und somit auch mehr CO2-Emissionen verursacht. Der Stromverbrauch war um das 6-fache und die CO2-Emissionen um das 2,5-fache Mal höher im Vergleich zu der lokalen Berechnung mit CPUs. Logischerweise hängt beides mit der längeren Berechnungszeit zusammen. Diese betrug zweieinhalb Minuten für die GPU und nur etwas weniger als zwei Minuten für die CPUs. Insgesamt geben beide Pakete alle notwendigen Informationen an, um die CO2-Emissionen und damit zusammenhängende Informationen zu beurteilen und zu berichten.

3. Vergleiche die verschiedenen Regionen von Cloud-Anbietern

In den vergangenen Jahren hat das Training und die Anwendung von ML sowie DL Modellen in der Cloud im Vergleich zu lokalen Berechnungen immer mehr an Bedeutung gewonnen. Sicherlich ist einer der Gründe dafür der zunehmende Bedarf an Rechenleistung [8]. Zugriff auf GPUs in der Cloud ist für viele Unternehmen günstiger und schneller als der Bau eines eigenen Rechenzentrums. Natürlich benötigen auch Rechenzentren von Cloud-Anbietern Hardware und Strom für deren Betrieb. Es wird geschätzt, dass bereits circa 1% des weltweiten Strombedarfs auf Rechenzentren zurückgeht [19]. Da die Nutzung von Hardware, unabhängig vom Standort, immer CO2-Emissionen verursachen kann, ist es auch beim Training und der Anwendung von ML und DL Modellen in der Cloud wichtig, die CO2-Emissionen zu messen.

Aktuell ermöglichen zwei verschiedene Plattformen, die CO2e-Emissionen von Berechnungen in der Cloud zu ermitteln [20, 21]. Die guten Neuigkeiten dabei sind, dass die drei großen Cloud-Anbieter – AWS, Azure und GCP – in beiden Plattformen implementiert sind. Um zu beurteilen, welcher der drei Cloud-Anbieter und welche der verfügbaren europäischen Regionen die geringsten CO2e-Emissionen verursachen, habe ich die erste Plattform – ML CO2 Impact [20] – verwendet, um die CO2e-Emissionen für das abschließende Training von GPT-3 zu berechnen. Das finale Training von GPT-3 benötigte 310 GPUs (NVIDIA Tesla V100 PCIe), die ununterbrochen für 90 Tagen liefen [17]. Als Grundlage für die Berechnungen der CO2e-Emissionen der verschiedenen Cloud-Anbieter und deren Regionen, habe ich die verfügbare Option “Tesla V100-PCIE-16GB” als GPU gewählt. Die Ergebnisse der Berechnungen befinden sich in der nachfolgenden Tabelle.

Vergleich verschiedener Cloud-Anbieter und Regionen in Europa
Google Cloud Computing AWS Cloud Computing Microsoft Azure
Region CO2e Emissionen (Tonnen) Region CO2e Emissionen (Tonnen) Region CO2e Emissionen (Tonnen)
europe-west1 54.2 EU – Frankfurt 122.5 France Central 20.1
europe-west2 124.5 EU – Ireland 124.5 France South 20.1
europe-west3 122.5 EU – London 124.5 North Europe 124.5
europe-west4 114.5 EU – Paris 20.1 West Europe 114.5
europe-west6 4.0 EU – Stockholm 10.0 UK West 124.5
europe-north1 42.2 UK South 124.5

Zwei Ergebnisse in der Tabelle sind besonders auffällig. Erstens, die ausgewählte Region hat selbst innerhalb eines Cloud-Anbieters einen extrem großen Einfluss auf die geschätzten CO2e-Emissionen. Den größten Unterschied gab es bei GCP, mit einem Faktor von mehr als 30. Dieser große Unterschied ergibt sich auch durch die Region „europe-west6“, welche mit vier Tonnen die insgesamt geringsten CO2e-Emissionen verursacht. Interessanterweise ist ein Faktor der Größe 30 weit mehr als die Faktoren von 5 bis 10, welche in Studien beschrieben werden [12]. Neben den Unterschieden zwischen Regionen sind zweitens die Werte einiger Regionen exakt identisch. Dies spricht dafür, dass eine gewisse Vereinfachung bei den Berechnungen vorgenommen wurde. Die absoluten Werte sollten daher mit Vorsicht betrachtet werden, wobei die Unterschiede weiterhin bestehen bleiben, da allen Regionen die gleiche (vereinfachte) Art der Berechnung zu Grunde liegt.
Neben den reinen CO2e-Emissionen durch Rechenzentren, ist es für die Wahl eines Cloud-Anbieters ebenfalls wichtig, die Nachhaltigkeitsstrategie der Anbieter zu berücksichtigen. In diesem Bereich scheinen GCP und Azure im Vergleich zu AWS die besseren Strategien zu haben [22, 23]. Auch wenn kein Cloud-Anbieter bisher 100% erneuerbare Energien nutzt (siehe Tabelle 2 in [9]), haben GCP und Azure dies mit dem Ausgleich ihres CO2-Ausstoßes sowie Energiezertifikaten bereits in der Theorie erreicht. Aus ökologischer Sicht bevorzuge ich letztlich GCP, weil mich deren Strategie am meisten überzeugt hat. Zudem hat GCP seit 2021 bei der Auswahl der Regionen einen Hinweis eingefügt, welche den geringsten CO2-Ausstoß verursachen [24]. Für mich zeigen solche kleinen Hilfestellungen, welchen Stellenwert das Thema dort einnimmt.

4. Trainiere und nutze KI-Modelle mit Bedacht

Zu guter Letzt gibt es noch viele weitere Tipps und Tricks in Bezug auf das Training und den Einsatz von ML sowie DL Modellen, die dir helfen, deinen CO2-Fußabdruck als Data Scientist zu minimieren.

  • Sei sparsam! Neue Forschung, die DL Modelle mit aktuellen Ergebnissen aus den Neurowissenschaften kombiniert, kann die Berechnungszeit um das bis zu 100-fache reduzieren und dadurch extrem viel CO2 einsparen [25].
  • Verwende, wenn möglich, einfachere KI-Modelle, die eine vergleichbare Vorhersagegenauigkeit haben, aber weniger rechenintensiv sind. Beispielsweise gibt es das Modell DistilBERT, welches eine kleinere und schnellere Version von BERT ist, aber eine vergleichbare Genauigkeit besitzt [26].
  • Ziehe Transfer Learning und sogenannte Foundation Modelle [10| in Betracht, um die Vorhersagegenauigkeit zu maximieren und Berechnungszeit zu minimieren.
  • Ziehe Federated Learning in Betracht, um CO2-Emissionen zu minimieren [27].
  • Denke nicht nur an die Vorhersagegenauigkeit deiner Modelle. Effizienz ist ebenfalls ein wichtiges Kriterium. Wäge ab, ob eine 1% höhere Genauigkeit die zusätzlichen Umweltauswirkungen wert sind [9, 12].
  • Wenn der beste Bereich für die Hyperparameter deines Modells noch unbekannt sind, nutze eine zufällige oder Bayesianische Suche nach den Hyperparametern anstatt einer Rastersuche [9, 20].
  • Wenn dein Modell während der Anwendung regelmäßig neu trainiert wird, wähle das Trainingsintervall bewusst aus. Je nach Anwendungsfall reicht es womöglich aus, das Modell nur jeden Monat und nicht jede Woche neu zu trainieren.

Fazit

Es besteht kein Zweifel daran, dass Menschen und ihre Treibhausgasemissionen das Klima beeinflussen und unseren Planeten erwärmen. KI kann und sollte beim Problem des Klimawandels zur Lösung beitragen. Gleichzeitig müssen wir den CO2-Fußabdruck von KI im Auge behalten, um sicherzustellen, dass es Teil der Lösung und nicht Teil des Problems ist.

Du kannst als Data Scientist dabei einen großen Beitrag leisten. Informiere dich über die positiven Möglichkeiten und die negativen Auswirkungen von KI und kläre andere darüber auf. Außerdem kannst du die CO2-Emissionen deiner Modelle messen und transparent darstellen. Du solltest zudem deine Anstrengungen zur Minimierung des CO2-Fußabdrucks deiner Modelle beschreiben. Letztlich kannst du deinen Cloud-Anbieter bewusst wählen und beispielsweise prüfen, ob es für deinen Anwendungsfall einfachere Modelle gibt, die eine vergleichbare Vorhersagegenauigkeit bieten, aber mit weniger Emissionen.

Wir bei statworx haben vor kurzem die Initiative AI & Environment ins Leben gerufen, um genau solche Aspekte in unserer täglichen Arbeit als Data Scientists einzubauen. Wenn du mehr darüber erfahren möchtest, sprich uns einfach an!

Referenzen

  1. https://www.ipcc.ch/report/ar6/wg1/downloads/report/IPCC_AR6_WGI_SPM_final.pdf
  2. http://www.globalcarbonatlas.org/en/CO2-emissions
  3. https://doi.org/10.1007/s43681-021-00043-6
  4. https://arxiv.org/pdf/1906.05433.pdf
  5. Harnessing Artificial Intelligence
  6. https://www.pwc.co.uk/sustainability-climate-change/assets/pdf/how-ai-can-enable-a-sustainable-future.pdf
  7. https://climateactiontracker.org/
  8. https://arxiv.org/pdf/1907.10597.pdf
  9. https://arxiv.org/pdf/1906.02243.pdf
  10. https://arxiv.org/pdf/2108.07258.pdf
  11. https://algorithmwatch.org/de/sustain/
  12. https://arxiv.org/ftp/arxiv/papers/2104/2104.10350.pdf
  13. https://stefanos1316.github.io/my_curriculum_vitae/GKS17.pdf
  14. https://pypl.github.io/PYPL.html
  15. https://codecarbon.io/
  16. https://mlco2.github.io/codecarbon/index.html
  17. https://arxiv.org/pdf/2007.03051.pdf
  18. https://github.com/Breakend/experiment-impact-tracker
  19. https://www.iea.org/reports/data-centres-and-data-transmission-networks
  20. https://mlco2.github.io/impact/#co2eq
  21. http://www.green-algorithms.org/
  22. https://blog.container-solutions.com/the-green-cloud-how-climate-friendly-is-your-cloud-provider
  23. https://www.wired.com/story/amazon-google-microsoft-green-clouds-and-hyperscale-data-centers/
  24. https://cloud.google.com/blog/topics/sustainability/pick-the-google-cloud-region-with-the-lowest-co2)
  25. https://arxiv.org/abs/2112.13896
  26. https://arxiv.org/abs/1910.01108
  27. https://flower.dev/blog/2021-07-01-what-is-the-carbon-footprint-of-federated-learning

Alexander Niltop Alexander Niltop

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

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

Im ersten Artikel dieser Serie über die Klassifizierung von Automodellen haben wir ein Modell gebaut, das Transfer Learning verwendet, um das Automodell durch ein Bild eines Autos zu klassifizieren. Im zweiten Beitrag haben wir gezeigt, wie TensorFlow Serving verwendet werden kann, um ein TensorFlow-Modell am Beispiel des Automodell-Classifiers einzusetzen. Diesen dritten Beitrag widmen wir einem weiteren wesentlichen Aspekt von Deep Learning und maschinellem Lernen im Allgemeinen: der Erklärbarkeit von Modellvorhersagen (englisch: Explainable AI).

Wir beginnen mit einer kurzen allgemeinen Einführung in das Thema Erklärbarkeit beim maschinellen Lernen. Als nächstes werden wir kurz auf verbreitete Methoden eingehen, die zur Erklärung und Interpretation von CNN-Vorhersagen verwendet werden können. Anschließend werden wir Grad-CAM, eine gradientenbasierte Methode, ausführlich erklären, indem wir Schritt für Schritt eine Implementierung des Verfahrens durchgehen. Zum Schluss zeigen wir Ergebnisse, die wir mit unserer Grad-CAM-Implementierung für den Auto-Modell-Classifier berechnet haben.

Eine kurze Einführung in die Erklärbarkeit von Machine Learning Modellen

In den letzten Jahren war die Erklärbarkeit ein immer wiederkehrendes Thema – aber dennoch ein Nischenthema – im Machine Learning. In den letzten vier Jahren jedoch hat das Interesse an diesem Thema stark zugenommen. Stark dazu beigetragen hat unter anderem die steigende Anzahl von Machine Learning-Modellen in der Produktion. Einerseits führt dies zu einer wachsenden Zahl von Endnutzern, die verstehen müssen, wie die Modelle Entscheidungen treffen. Andererseits müssen immer mehr Entwickler*innen von Machine Learning verstehen, warum (oder warum nicht) ein Modell auf eine bestimmte Weise funktioniert.

Dieser steigende Bedarf an Erklärbarkeit führte in den letzten Jahren zu einigen sowohl methodisch als auch technisch bemerkenswerten Innovationen:

Methoden zur Erklärung von CNN-Outputs für Bilddaten

Deep Neural Networks (DNNs) und insbesondere komplexe Architekturen wie CNNs galten lange Zeit als reine Blackbox-Modelle. Wie oben beschrieben änderte sich dies in den letzten Jahren, und inzwischen gibt es verschiedene Methoden, um CNN-Outputs zu erklären. Zum Beispiel implementiert die hervorragende Bibliothek tf-explain eine breite Palette nützlicher Methoden für TensorFlow 2.x. Wir werden nun kurz auf die Ideen der verschiedenen Ansätze eingehen, bevor wir uns Grad-CAM zuwenden:

Activations Visualization

Activations Visualization ist die einfachste Visualisierungstechnik. Hierbei wird die Ausgabe einer bestimmten Layer innerhalb des Netzwerks während des Vorwärtsdurchlaufs ausgegeben. Diese kann hilfreich sein, um ein Gefühl für die extrahierten Features zu bekommen, da die meisten Activations während des Trainings gegen Null tendieren (bei Verwendung der ReLu-Activation). Ein Beispiel für die Ausgabe der ersten Faltungsschicht des Auto-Modell-Classifiers ist unten dargestellt:

Vanilla Gradients

Man kann die Vanilla-Gradients der Ausgabe der vorhergesagten Klassen für das Eingangsbild verwenden, um die Bedeutung der Eingangspixel abzuleiten.

Wir sehen hier, dass der hervorgehobene Bereich hauptsächlich auf das Auto fokussiert ist. Im Vergleich zu den unten besprochenen Methoden ist der diskriminierende Bereich viel weniger eingegrenzt.

Occlusion Sensitivity

Bei diesem Ansatz wird die Signifikanz bestimmter Teile des Eingangsbildes berechnet, indem die Vorhersage des Modells für verschiedene ausgeblendete Teile des Eingangsbildes bewertet wird. Teile des Bildes werden iterativ ausgeblendet, indem sie durch graue Pixel ersetzt werden. Je schwächer die Vorhersage wird, wenn ein Teil des Bildes ausgeblendet ist, desto wichtiger ist dieser Teil für die endgültige Vorhersage. Basierend auf der Unterscheidungskraft der Bildregionen kann eine Heatmap erstellt und dargestellt werden. Die Anwendung der Occlusion Sensitivity für unseren Auto-Modell-Classifier hat keine aussagekräftigen Ergebnisse geliefert. Daher zeigen wir das Beispielbild von tf-explain, welches das Ergebnis der Anwendung des Verfahrens der Occlusion Sensitivity für ein Katzenbild zeigt.

CNN Fixations

Ein weiterer interessanter Ansatz namens CNN Fixations wurde in diesem Paper vorgestellt . Die Idee dabei ist, zurück zu verfolgen, welche Neuronen in jeder Schicht signifikant waren, indem man die Activations aus der Vorwärtsrechnung und die Netzwerkgewichte betrachtet. Die Neuronen mit großem Einfluss werden als Fixations bezeichnet. Dieser Ansatz erlaubt es also, die wesentlichen Regionen für das Ergebnis zu finden, ohne wiederholte Modellvorhersagen berechnen zu müssen (wie dies z.B. für die oben erklärte Occlusion Sensitivity der Fall ist).

Das Verfahren kann wie folgt beschrieben werden: Der Knoten, der der Klasse entspricht, wird als Fixation in der Ausgabeschicht gewählt. Dann werden die Fixations für die vorherige Schicht bestimmt, indem berechnet wird, welche der Knoten den größten Einfluss auf die Fixations der nächsthöheren Ebene haben, die im letzten Schritt bestimmt wurden. Die Knotengewichtung wird durch Multiplikation von Activations und Netzwerk-Gewichten errechnet. Wenn ihr an den Details des Verfahrens interessiert seid, schaut euch das Paper oder das entsprechende Github Repo an. Dieses Backtracking wird so lange durchgeführt, bis das Eingabebild erreicht ist, was eine Menge von Pixeln mit beträchtlicher Unterscheidungskraft ergibt. Ein Beispiel aus dem Paper ist unten dargestellt.

CAM

Das in diesem Paper vorgestellte Class Activation Mapping (CAM) ist ein Verfahren, um die diskriminante(n) Region(en) für eine CNN-Vorhersage durch die Berechnung von sogenannten Class Activation Maps zu finden. Ein wesentlicher Nachteil dieses Verfahrens ist, dass das Netzwerk als letzten Schritt vor der Vorhersageschicht ein Global Average Pooling (GAP) verwenden muss. Es ist daher nicht möglich, diesen Ansatz für allgemeine CNN-Architekturen anzuwenden. Ein Beispiel ist in der folgenden Abbildung dargestellt (entnommen aus dem CAM paper):

Die Class Activation Map weist jeder Position (x, y) in der letzten Faltungsschicht eine Bedeutung zu, indem sie die Linearkombination der Activations – gewichtet mit den entsprechenden Ausgangsgewichten für die beobachtete Klasse (im obigen Beispiel „Australian Terrier“) – berechnet. Die resultierende Class Activation Mapping wird dann auf die Größe des Eingabebildes hochgerechnet. Dies wird durch die oben dargestellte Heatmap veranschaulicht. Aufgrund der Architektur von CNNs ist die Aktivierung, z. B. oben links für eine beliebige Schicht, direkt mit der oberen linken Seite des Eingabebildes verbunden. Deshalb können wir nur aus der Betrachtung der letzten CNN-Schicht schließen, welche Eingabebereiche wichtig sind.

Bei dem Grad-CAM-Verfahren, das wir unten im Detail besprechen werden, handelt es sich um eine Verallgemeinerung von CAM. Grad-CAM kann auf Netzwerke mit allgemeinen CNN-Architekturen angewendet werden, die mehrere fully connected Layers am Ausgang enthalten.

Grad-CAM

Grad-CAM erweitert die Anwendbarkeit des CAM-Verfahrens durch das Einbeziehen von Gradienteninformationen. Konkret bestimmt der Gradient der Loss-Funktion in Bezug auf die letzte Faltungsschicht das Gewicht für jede der entsprechenden Feature Maps. Wie beim obigen CAM-Verfahren bestehen die weiteren Schritte in der Berechnung der gewichteten Summe der Aktivierungen und dem anschließenden Upsampling des Ergebnisses auf die Bildgröße, um das Originalbild mit der erhaltenen Heatmap darzustellen. Wir werden nun den Code, der zur Ausführung von Grad-CAM verwendet werden kann, zeigen und diskutieren. Der vollständige Code ist hier auf GitHub verfügbar.

import pickle
import tensorflow as tf
import cv2
from car_classifier.modeling import TransferModel

INPUT_SHAPE = (224, 224, 3)

# Load list of targets
file = open('.../classes.pickle', 'rb')
classes = pickle.load(file)

# Load model
model = TransferModel('ResNet', INPUT_SHAPE, classes=classes)
model.load('...')

# Gradient model, takes the original input and outputs tuple with:
# - output of conv layer (in this case: conv5_block3_3_conv)
# - output of head layer (original output)
grad_model = tf.keras.models.Model([model.model.inputs],
                                   [model.model.get_layer('conv5_block3_3_conv').output,
                                    model.model.output])

# Run model and record outputs, loss, and gradients
with tf.GradientTape() as tape:
    conv_outputs, predictions = grad_model(img)
    loss = predictions[:, label_idx]

# Output of conv layer
output = conv_outputs[0]

# Gradients of loss w.r.t. conv layer
grads = tape.gradient(loss, conv_outputs)[0]

# Guided Backprop (elimination of negative values)
gate_f = tf.cast(output > 0, 'float32')
gate_r = tf.cast(grads > 0, 'float32')
guided_grads = gate_f * gate_r * grads

# Average weight of filters
weights = tf.reduce_mean(guided_grads, axis=(0, 1))

# Class activation map (cam)
# Multiply output values of conv filters (feature maps) with gradient weights
cam = np.zeros(output.shape[0: 2], dtype=np.float32)
for i, w in enumerate(weights):
    cam += w * output[:, :, i]

# Or more elegant: 
# cam = tf.reduce_sum(output * weights, axis=2)

# Rescale to org image size and min-max scale
cam = cv2.resize(cam.numpy(), (224, 224))
cam = np.maximum(cam, 0)
heatmap = (cam - cam.min()) / (cam.max() - cam.min())

Detailbetrachtung des Codes

  • Der erste Schritt besteht darin, eine Instanz des Modells zu laden.
  • Dann erstellen wir eine neue keras.Model-Instanz, die zwei Ausgaben hat: Die Aktivierungen der letzten CNN-Schicht ('conv5_block3_3_conv') und die ursprüngliche Modellausgabe.
  • Als nächstes führen wir eine Vorwärtsrechnung für unser neues grad_model aus, wobei wir als Eingabe ein Bild ( img) der Form (1, 224, 224, 3) verwenden, das mit der Methode resnetv2.preprocess_input vorverarbeitet wurde. Zur Aufzeichnung der Gradienten wird tf.GradientTape angelegt und angewendet (die Gradienten werden hierbei im tapeObjekt gespeichert). Weiterhin werden die Ausgaben der Faltungsschicht (conv_outputs) und des heads (predictions) gespeichert. Schließlich können wir label_idx verwenden, um den Verlust zu erhalten, der dem Label entspricht, für das wir die diskriminierenden Regionen finden wollen.
  • Mit Hilfe der gradient-Methode kann man die gewünschten Gradienten aus tape extrahieren. In diesem Fall benötigen wir den Gradienten des Verlustes in Bezug auf die Ausgabe der Faltungsschicht.
  • In einem weiteren Schritt wird eine guided Backprop angewendet. Dabei werden nur Werte für die Gradienten behalten, bei denen sowohl die Aktivierungen als auch die Gradienten positiv sind. Dies bedeutet im Wesentlichen, dass die Aufmerksamkeit auf die Aktivierungen beschränkt wird, die positiv zu der gewünschten Ausgabevorhersage beitragen.
  • Die weights werden durch Mittelung der erhaltenen geführten Gradienten für jeden Filter berechnet.
  • Die Class Activation Map cam wird dann als gewichteter Durchschnitt der Aktivierungen der Feature Map (output) berechnet. Die Methode mit der obigen for-Schleife hilft zu verstehen, was die Funktion im Detail tut. Eine weniger einfache, aber effizientere Art, die CAM-Berechnung zu implementieren, ist die Verwendung von tf.reduce_mean und wird in der kommentierten Zeile unterhalb der Schleifenimplementierung gezeigt.
  • Schließlich wird das Resampling (Größenänderung) mit der resize-Methode von OpenCV2 durchgeführt, und die Heatmap wird so skaliert, dass sie Werte in [0, 1] enthält, um sie zu plotten.

Eine Version von Grad-CAM ist auch in tf-explain implementiert.

Beispiele für den Auto-Modell-Classifier

Wir verwenden nun die Grad-CAM-Implementierung, um die Vorhersagen des TransferModel für die Klassifizierung von Automodellen zu interpretieren und zu erklären. Wir beginnen mit der Betrachtung von Fahrzeugbildern, die von vorne aufgenommen wurden.


Grad-CAM für Fahrzeugaufnahmen von der Vorderseite

Die roten Regionen markieren die wichtigsten diskriminierenden Regionen, die blauen Regionen die unwichtigsten. Wir können sehen, dass sich das CNN bei Bildern von vorne auf den Kühlergrill des Autos und den Bereich des Logos konzentriert. Ist das Auto leicht gekippt, verschiebt sich der Fokus mehr auf den Rand des Fahrzeugs. Dies ist auch bei leicht gekippten Bildern von der Rückseite des Fahrzeugs der Fall, wie im mittleren Bild unten gezeigt.


Grad-CAM für Fahrzeugaufnahmen von der Rückseite

Bei Bildern von der Rückseite des Autos liegt der wichtigste Unterscheidungsbereich in der Nähe des Nummernschilds. Wie bereits erwähnt, hat bei Autos, die aus einem Winkel betrachtet werden, die nächstgelegene Ecke die höchste Trennschärfe. Ein sehr interessantes Beispiel ist die Mercedes-Benz C-Klasse auf der rechten Seite, bei der sich das Modell nicht nur auf die Rückleuchten konzentriert, sondern auch die höchste Trennschärfe auf den Modellschriftzug legt.


Grad-CAM für Fahrzeugaufnahmen von der Seite

Wenn wir Bilder von der Seite betrachten, stellen wir fest, dass die diskriminierende Region auf die untere Hälfte der Autos beschränkt ist. Auch hier bestimmt der Winkel, aus dem das Fahrzeugbild aufgenommen wurde, die Verschiebung der Region in Richtung der vorderen oder hinteren Ecke.

Im Allgemeinen ist die wichtigste Tatsache, dass die diskriminierenden Bereiche immer auf Teile der Autos beschränkt sind. Es gibt keine Bilder, bei denen der Hintergrund eine hohe Unterscheidungskraft hat. Die Betrachtung der Heatmaps und der zugehörigen diskriminierenden Regionen kann als Sanity-Check für CNN-Modelle verwendet werden.

Fazit

Wir haben mehrere Ansätze zur Erklärung von CNN-Klassifikatorausgaben diskutiert. Wir haben Grad-CAM im Detail vorgestellt, indem wir den Code untersucht und uns Beispiele für den Auto-Modell-Classifier angeschaut haben. Am auffälligsten ist, dass die durch das Grad-CAM-Verfahren hervorgehobenen diskriminierenden Regionen immer auf das Auto fokussiert sind und nie auf die Hintergründe der Bilder. Das Ergebnis zeigt, dass das Modell so funktioniert, wie wir es erwarten und spezifische Teile des Autos zur Unterscheidung zwischen verschiedenen Modellen verwendet werden.

Im vierten und letzten Teil dieser Blog-Serie werden wir zeigen, wie der Car Classifier mit Dash in eine Web-Anwendung eingebaut werden kann. Bis bald!

Stephan Müller Stephan Müller

Im ersten Beitrag dieser Serie haben wir Transfer Learning im Detail besprochen und ein Modell zur Klassifizierung von Automodellen erstellt. In diesem Beitrag werden wir das Problem der Modellbereitstellung am Beispiel des im ersten Beitrags vorgestellten TransferModel diskutieren.

Ein Modell ist in der Praxis nutzlos, wenn es keine einfache Möglichkeit gibt, damit zu interagieren. Mit anderen Worten: Wir brauchen eine API für unsere Modelle. TensorFlow Serving wurde entwickelt, um diese Funktionalitäten für TensorFlow-Modelle bereitzustellen. In diesem Beitrag zeigen wir, wie ein TensorFlow Serving Server in einem Docker-Container gestartet werden kann und wie wir mit dem Server über HTTP-Anfragen interagieren können.

Wenn ihr noch nie mit Docker gearbeitet habt, empfehlen wir, dieses Tutorial von Docker durchzuarbeiten, bevor ihr diesen Artikel lest. Wenn ihr euch ein Beispiel für das Deployment in Docker ansehen möchtet, empfehlen wir euch, diesen Blogbeitrag von unserem Kollegen Oliver Guggenbühl zu lesen, in dem beschrieben wird, wie ein R-Skript in Docker ausgeführt werden kann.

Einführung in TensorFlow Serving

Zum Einstieg geben wir euch zunächst einen Überblick über TensorFlow Serving.

TensorFlow Serving ist das Serving-System von TensorFlow, das entwickelt wurde, um das Deployment von verschiedenen Modellen mit einer einheitlichen API zu ermöglichen. Unter Verwendung der Abstraktion von Servables, die im Grunde Objekte sind, mit denen Inferenz durchgeführt werden kann, ist es möglich, mehrere Versionen von deployten Modellen zu serven. Das ermöglicht zum Beispiel, dass eine neue Version eines Modells hochgeladen werden kann, während die vorherige Version noch für Kunden verfügbar ist. Im Großen und Ganzen sind sogenannte Manager für die Verwaltung des Lebenszyklus von Servables verantwortlich, d. h. für das Laden, Bereitstellen und Löschen.

In diesem Beitrag werden wir zeigen, wie eine einzelne Modellversion deployed werden kann. Die unten aufgeführten Code-Beispiele zeigen, wie ein Server in einem Docker-Container gestartet werden kann und wie die Predict API verwendet werden kann, um mit dem Modell zu interagieren. Um mehr über TensorFlow Serving zu erfahren, verweisen wir auf die TensorFlow-Website.

Implementierung

Wir werden nun die folgenden drei Schritte besprechen, die erforderlich sind, um das Modell einzusetzen und Requests zu senden.

  • Speichern eines Modells im richtigen Format und in der richtigen Ordnerstruktur mit TensorFlow SavedModel
  • Ausführen eines Serving-Servers innerhalb eines Docker-Containers
  • Interaktion mit dem Modell über REST Requests

Speichern von TensorFlow-Modellen

Für diejenigen, die den ersten Beitrag dieser Serie nicht gelesen haben, folgt nun eine kurze Zusammenfassung der wichtigsten Punkte, die zum Verständnis des nachfolgenden Codes notwendig sind:

Das TransferModel.model (unten im Code auch self.model) ist eine tf.keras.Model Instanz, also kann es mit der eingebauten save Methode gespeichert werden. Da das Modell auf im Internet gescrapten Daten trainiert wurde, können sich die Klassenbezeichnungen beim erneuten Scraping der Daten ändern. Wir speichern daher die Index-Klassen-Zuordnung beim Speichern des Modells in classes.pickle ab. TensorFlow Serving erfordert, dass das Modell im SavedModel Format gespeichert wird. Wenn Sie tf.keras.Model.save verwenden, muss der Pfad ein Ordnername sein, sonst wird das Modell in einem anderen, inkompatiblen Format (z.B. HDF5) gespeichert. Im Code unten enthält folderpath den Pfad des Ordners, in dem wir alle modellrelevanten Informationen speichern wollen. Das SavedModel wird unter folderpath/model gespeichert und das Class Mapping wird als folderpath/classes.pickle gespeichert.

def save(self, folderpath: str):
    """
    Save the model using tf.keras.model.save

    Args:
        folderpath: (Full) Path to folder where model should be stored
    """

    # Make sure folderpath ends on slash, else fix
    if not folderpath.endswith("/"):
        folderpath += "/"

    if self.model is not None:
        os.mkdir(folderpath)
        model_path = folderpath + "model"
        # Save model to model dir
        self.model.save(filepath=model_path)
        # Save associated class mapping
        class_df = pd.DataFrame({'classes': self.classes})
        class_df.to_pickle(folderpath + "classes.pickle")
    else:
        raise AttributeError('Model does not exist')

TensorFlow Serving im Docker Container starten

Nachdem wir das Modell auf der Festplatte gespeichert haben, müssen wir nun den TensorFlow Serving Server starten. Am schnellsten deployen kann man TensorFlow Serving mithilfe eines Docker-Containers. Der erste Schritt ist daher das Ziehen des TensorFlow Serving Images von DockerHub. Das kann im Terminal mit dem Befehl docker pull tensorflow/serving gemacht werden.

Dann können wir den unten stehenden Code verwenden, um einen TensorFlow Serving Container zu starten. Er führt den Shell-Befehl zum Starten eines Containers aus. Die in docker_run_cmd gesetzten Optionen sind die folgenden:

  • Das Serving-Image exponiert Port 8501 für die REST-API, die wir später zum Senden von Anfragen verwenden werden. Wir mappen mithilfe der -p– Flag also den Host-Port 8501 auf den Port 8501 des Containers.
  • Als nächstes binden wir unser Modell mit -v in den Container ein. Es ist wichtig, dass das Modell in einem versionierten Ordner gespeichert ist (hier MODEL_VERSION=1); andernfalls wird das Serving-Image das Modell nicht finden. Der model_path_guest muss also die Form <path>/<model name>/MODEL_VERSION haben, wobei MODEL_VERSION eine ganze Zahl ist.
  • Mit -e können wir die Umgebungsvariable MODEL_NAME setzen, die den Namen unseres Modells enthält.
  • Die Option --name tf_serving wird nur benötigt, um unserem neuen Docker-Container einen bestimmten Namen zuzuweisen.

Wenn wir versuchen, diese Datei zweimal hintereinander auszuführen, wird der Docker-Befehl beim zweiten Mal nicht ausgeführt, da bereits ein Container mit dem Namen tf_serving existiert. Um dieses Problem zu vermeiden, verwenden wir docker_run_cmd_cond. Hier prüfen wir zunächst, ob ein Container mit diesem spezifischen Namen bereits existiert und läuft. Wenn ja, lassen wir ihn gleich; wenn nicht, prüfen wir, ob eine beendete Version des Containers existiert. Wenn ja, wird diese gelöscht und ein neuer Container gestartet; wenn nicht, wird direkt ein neuer Container erstellt.

import os

MODEL_FOLDER = 'models'
MODEL_SAVED_NAME = 'resnet_unfreeze_all_filtered.tf'
MODEL_NAME = 'resnet_unfreeze_all_filtered'
MODEL_VERSION = '1'

# Define paths on host and guest system
model_path_host = os.path.join(os.getcwd(), MODEL_FOLDER, MODEL_SAVED_NAME, 'model')
model_path_guest = os.path.join('/models', MODEL_NAME, MODEL_VERSION)

# Container start command
docker_run_cmd = f'docker run ' 
                 f'-p 8501:8501 ' 
                 f'-v {model_path_host}:{model_path_guest} ' 
                 f'-e MODEL_NAME={MODEL_NAME} ' 
                 f'-d ' 
                 f'--name tf_serving ' 
                 f'tensorflow/serving'

# If container is not running, create a new instance and run it
docker_run_cmd_cond = f'if [ ! "(docker ps -q -f name=tf_serving)" ]; then n'                        f'   if [ "(docker ps -aq -f status=exited -f name=tf_serving)" ]; then 														n' 
                      f'   		docker rm tf_serving n' 
                      f'   fi n' 
                      f'   {docker_run_cmd} n' 
                      f'fi'

# Start container
os.system(docker_run_cmd_cond)

Anstatt das Modell von unserer lokalen Festplatte zu mounten, indem wir das -v-Flag im Docker-Befehl verwenden, könnten wir das Modell auch in das Docker-Image kopieren, so dass das Modell einfach durch das Ausführen eines Containers und die Angabe der Port-Zuweisungen bedient werden könnte. Es ist wichtig zu beachten, dass in diesem Fall das Modell mit der Ordnerstruktur Ordnerpfad/<Modellname>/1 gespeichert werden muss, wie oben erklärt. Wenn dies nicht der Fall ist, wird der TensorFlow Serving Container das Modell nicht finden. Wir werden hier nicht weiter auf diesen Fall eingehen. Wenn ihr daran interessiert seid, eure Modelle auf diese Weise zu deployen, verweisen wir auf diese Anleitung auf der TensorFlow Webseite.

REST Request

Da das Modell nun geserved ist und bereit zur Verwendung ist, brauchen wir einen Weg, um damit zu interagieren. TensorFlow Serving bietet zwei Optionen, um Anfragen an den Server zu senden: gRCP und REST API, welche beide an unterschiedlichen Ports verfügbar sind. Im folgenden Codebeispiel werden wir REST verwenden, um das Modell abzufragen.

Zuerst laden wir ein Bild von der Festplatte, für das wir eine Vorhersage machen wollen. Dies kann mit dem image Modul von TensorFlow gemacht werden. Als nächstes konvertieren wir das Bild in ein Numpy-Array mittels der img_to_array-Methode. Der nächste und letzte Schritt ist entscheidend für unseren Car Classifier Use Case: da wir das Trainingsbild vorverarbeitet haben, bevor wir unser Modell trainiert haben (z.B. Normalisierung), müssen wir die gleiche Transformation auf das Bild anwenden, das wir vorhersagen wollen. Die praktische Funktion „preprocess_input“ sorgt dafür, dass alle notwendigen Transformationen auf unser Bild angewendet werden.

from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet_v2 import preprocess_input

# Load image
img = image.load_img(path, target_size=(224, 224))
img = image.img_to_array(img)

# Preprocess and reshape data
img = preprocess_input(img)
img = img.reshape(-1, *img.shape)

Die RESTful API von TensorFlow Serving bietet mehrere Endpunkte. Im Allgemeinen akzeptiert die API Post-Requests der folgenden Struktur:

POST http://host:port/<URI>:<VERB>

URI: /v1/models/{MODEL_NAME}[/versions/{MODEL_VERSION}]
VERB: classify|regress|predict

Für unser Modell können wir die folgende URL für Vorhersagen verwenden: http://localhost:8501/v1/models/resnet_unfreeze_all_filtered:predict

Die Portnummer (hier 8501) ist der Port des Hosts, den wir oben angegeben haben, um ihn auf den Port 8501 des Serving-Images abzubilden. Wie oben erwähnt, ist 8501 der Port des Serving-Containers, der für die REST-API verwendet wird. Die Modellversion ist optional und wird standardmäßig auf die neueste Version gesetzt, wenn sie weggelassen wird.

In Python kann die Bibliothek requests verwendet werden, um HTTP-Anfragen zu senden. Wie in der Dokumentation angegeben, muss der Request-Body für die predict API ein JSON-Objekt mit den unten aufgeführten Schlüssel-Wert-Paaren sein:

  • signature_name – zu verwendende Signatur (weitere Informationen finden Sie in der Dokumentation)
  • instances – Modelleingabe im Zeilenformat
import json
import requests

# Send image as list to TF serving via json dump
request_url = 'http://localhost:8501/v1/models/resnet_unfreeze_all_filtered:predict'
request_body = json.dumps({"signature_name": "serving_default", "instances": img.tolist()})
request_headers = {"content-type": "application/json"}
json_response = requests.post(request_url, data=request_body, headers=request_headers)
response_body = json.loads(json_response.text)
predictions = response_body['predictions']

# Get label from prediction
y_hat_idx = np.argmax(predictions)
y_hat = classes[y_hat_idx]

Der Response-Body ist ebenfalls ein JSON-Objekt mit einem einzigen Schlüssel namens predictions. Da wir für jede Zeile in den Instanzen die Wahrscheinlichkeit für alle 300 Klassen erhalten, verwenden wir np.argmax, um die wahrscheinlichste Klasse zurückzugeben. Alternativ hätten wir auch die übergeordnete classify-API verwenden können.

Fazit

In diesem zweiten Blog-Artikel der Serie „Car Model Classification“ haben wir gelernt, wie ein TensorFlow-Modell zur Bilderkennung mittels TensorFlow Serving als RestAPI bereitgestellt werden kann, und wie damit Modellabfragen ausgeführt werden können.

Dazu haben wir zuerst das Modell im SavedModel Format abgespeichert. Als nächstes haben wir den TensorFlow Serving-Server in einem Docker-Container gestartet. Schließlich haben wir gezeigt, wie man Vorhersagen aus dem Modell mit Hilfe der API-Endpunkte und einem korrekt spezifizierten Request Body anfordert.

Ein Hauptkritikpunkt an Deep Learning Modellen jeglicher Art ist die fehlende Erklärbarkeit der Vorhersagen. Im dritten Beitrag werden wir zeigen, wie man Modellvorhersagen mit einer Methode namens Grad-CAM erklären kann.

Stephan Müller Stephan Müller

Im ersten Beitrag dieser Serie haben wir Transfer Learning im Detail besprochen und ein Modell zur Klassifizierung von Automodellen erstellt. In diesem Beitrag werden wir das Problem der Modellbereitstellung am Beispiel des im ersten Beitrags vorgestellten TransferModel diskutieren.

Ein Modell ist in der Praxis nutzlos, wenn es keine einfache Möglichkeit gibt, damit zu interagieren. Mit anderen Worten: Wir brauchen eine API für unsere Modelle. TensorFlow Serving wurde entwickelt, um diese Funktionalitäten für TensorFlow-Modelle bereitzustellen. In diesem Beitrag zeigen wir, wie ein TensorFlow Serving Server in einem Docker-Container gestartet werden kann und wie wir mit dem Server über HTTP-Anfragen interagieren können.

Wenn ihr noch nie mit Docker gearbeitet habt, empfehlen wir, dieses Tutorial von Docker durchzuarbeiten, bevor ihr diesen Artikel lest. Wenn ihr euch ein Beispiel für das Deployment in Docker ansehen möchtet, empfehlen wir euch, diesen Blogbeitrag von unserem Kollegen Oliver Guggenbühl zu lesen, in dem beschrieben wird, wie ein R-Skript in Docker ausgeführt werden kann.

Einführung in TensorFlow Serving

Zum Einstieg geben wir euch zunächst einen Überblick über TensorFlow Serving.

TensorFlow Serving ist das Serving-System von TensorFlow, das entwickelt wurde, um das Deployment von verschiedenen Modellen mit einer einheitlichen API zu ermöglichen. Unter Verwendung der Abstraktion von Servables, die im Grunde Objekte sind, mit denen Inferenz durchgeführt werden kann, ist es möglich, mehrere Versionen von deployten Modellen zu serven. Das ermöglicht zum Beispiel, dass eine neue Version eines Modells hochgeladen werden kann, während die vorherige Version noch für Kunden verfügbar ist. Im Großen und Ganzen sind sogenannte Manager für die Verwaltung des Lebenszyklus von Servables verantwortlich, d. h. für das Laden, Bereitstellen und Löschen.

In diesem Beitrag werden wir zeigen, wie eine einzelne Modellversion deployed werden kann. Die unten aufgeführten Code-Beispiele zeigen, wie ein Server in einem Docker-Container gestartet werden kann und wie die Predict API verwendet werden kann, um mit dem Modell zu interagieren. Um mehr über TensorFlow Serving zu erfahren, verweisen wir auf die TensorFlow-Website.

Implementierung

Wir werden nun die folgenden drei Schritte besprechen, die erforderlich sind, um das Modell einzusetzen und Requests zu senden.

Speichern von TensorFlow-Modellen

Für diejenigen, die den ersten Beitrag dieser Serie nicht gelesen haben, folgt nun eine kurze Zusammenfassung der wichtigsten Punkte, die zum Verständnis des nachfolgenden Codes notwendig sind:

Das TransferModel.model (unten im Code auch self.model) ist eine tf.keras.Model Instanz, also kann es mit der eingebauten save Methode gespeichert werden. Da das Modell auf im Internet gescrapten Daten trainiert wurde, können sich die Klassenbezeichnungen beim erneuten Scraping der Daten ändern. Wir speichern daher die Index-Klassen-Zuordnung beim Speichern des Modells in classes.pickle ab. TensorFlow Serving erfordert, dass das Modell im SavedModel Format gespeichert wird. Wenn Sie tf.keras.Model.save verwenden, muss der Pfad ein Ordnername sein, sonst wird das Modell in einem anderen, inkompatiblen Format (z.B. HDF5) gespeichert. Im Code unten enthält folderpath den Pfad des Ordners, in dem wir alle modellrelevanten Informationen speichern wollen. Das SavedModel wird unter folderpath/model gespeichert und das Class Mapping wird als folderpath/classes.pickle gespeichert.

def save(self, folderpath: str):
    """
    Save the model using tf.keras.model.save

    Args:
        folderpath: (Full) Path to folder where model should be stored
    """

    # Make sure folderpath ends on slash, else fix
    if not folderpath.endswith("/"):
        folderpath += "/"

    if self.model is not None:
        os.mkdir(folderpath)
        model_path = folderpath + "model"
        # Save model to model dir
        self.model.save(filepath=model_path)
        # Save associated class mapping
        class_df = pd.DataFrame({'classes': self.classes})
        class_df.to_pickle(folderpath + "classes.pickle")
    else:
        raise AttributeError('Model does not exist')

TensorFlow Serving im Docker Container starten

Nachdem wir das Modell auf der Festplatte gespeichert haben, müssen wir nun den TensorFlow Serving Server starten. Am schnellsten deployen kann man TensorFlow Serving mithilfe eines Docker-Containers. Der erste Schritt ist daher das Ziehen des TensorFlow Serving Images von DockerHub. Das kann im Terminal mit dem Befehl docker pull tensorflow/serving gemacht werden.

Dann können wir den unten stehenden Code verwenden, um einen TensorFlow Serving Container zu starten. Er führt den Shell-Befehl zum Starten eines Containers aus. Die in docker_run_cmd gesetzten Optionen sind die folgenden:

Wenn wir versuchen, diese Datei zweimal hintereinander auszuführen, wird der Docker-Befehl beim zweiten Mal nicht ausgeführt, da bereits ein Container mit dem Namen tf_serving existiert. Um dieses Problem zu vermeiden, verwenden wir docker_run_cmd_cond. Hier prüfen wir zunächst, ob ein Container mit diesem spezifischen Namen bereits existiert und läuft. Wenn ja, lassen wir ihn gleich; wenn nicht, prüfen wir, ob eine beendete Version des Containers existiert. Wenn ja, wird diese gelöscht und ein neuer Container gestartet; wenn nicht, wird direkt ein neuer Container erstellt.

import os

MODEL_FOLDER = 'models'
MODEL_SAVED_NAME = 'resnet_unfreeze_all_filtered.tf'
MODEL_NAME = 'resnet_unfreeze_all_filtered'
MODEL_VERSION = '1'

# Define paths on host and guest system
model_path_host = os.path.join(os.getcwd(), MODEL_FOLDER, MODEL_SAVED_NAME, 'model')
model_path_guest = os.path.join('/models', MODEL_NAME, MODEL_VERSION)

# Container start command
docker_run_cmd = f'docker run ' 
                 f'-p 8501:8501 ' 
                 f'-v {model_path_host}:{model_path_guest} ' 
                 f'-e MODEL_NAME={MODEL_NAME} ' 
                 f'-d ' 
                 f'--name tf_serving ' 
                 f'tensorflow/serving'

# If container is not running, create a new instance and run it
docker_run_cmd_cond = f'if [ ! "(docker ps -q -f name=tf_serving)" ]; then n'                        f'   if [ "(docker ps -aq -f status=exited -f name=tf_serving)" ]; then 														n' 
                      f'   		docker rm tf_serving n' 
                      f'   fi n' 
                      f'   {docker_run_cmd} n' 
                      f'fi'

# Start container
os.system(docker_run_cmd_cond)

Anstatt das Modell von unserer lokalen Festplatte zu mounten, indem wir das -v-Flag im Docker-Befehl verwenden, könnten wir das Modell auch in das Docker-Image kopieren, so dass das Modell einfach durch das Ausführen eines Containers und die Angabe der Port-Zuweisungen bedient werden könnte. Es ist wichtig zu beachten, dass in diesem Fall das Modell mit der Ordnerstruktur Ordnerpfad/<Modellname>/1 gespeichert werden muss, wie oben erklärt. Wenn dies nicht der Fall ist, wird der TensorFlow Serving Container das Modell nicht finden. Wir werden hier nicht weiter auf diesen Fall eingehen. Wenn ihr daran interessiert seid, eure Modelle auf diese Weise zu deployen, verweisen wir auf diese Anleitung auf der TensorFlow Webseite.

REST Request

Da das Modell nun geserved ist und bereit zur Verwendung ist, brauchen wir einen Weg, um damit zu interagieren. TensorFlow Serving bietet zwei Optionen, um Anfragen an den Server zu senden: gRCP und REST API, welche beide an unterschiedlichen Ports verfügbar sind. Im folgenden Codebeispiel werden wir REST verwenden, um das Modell abzufragen.

Zuerst laden wir ein Bild von der Festplatte, für das wir eine Vorhersage machen wollen. Dies kann mit dem image Modul von TensorFlow gemacht werden. Als nächstes konvertieren wir das Bild in ein Numpy-Array mittels der img_to_array-Methode. Der nächste und letzte Schritt ist entscheidend für unseren Car Classifier Use Case: da wir das Trainingsbild vorverarbeitet haben, bevor wir unser Modell trainiert haben (z.B. Normalisierung), müssen wir die gleiche Transformation auf das Bild anwenden, das wir vorhersagen wollen. Die praktische Funktion „preprocess_input“ sorgt dafür, dass alle notwendigen Transformationen auf unser Bild angewendet werden.

from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet_v2 import preprocess_input

# Load image
img = image.load_img(path, target_size=(224, 224))
img = image.img_to_array(img)

# Preprocess and reshape data
img = preprocess_input(img)
img = img.reshape(-1, *img.shape)

Die RESTful API von TensorFlow Serving bietet mehrere Endpunkte. Im Allgemeinen akzeptiert die API Post-Requests der folgenden Struktur:

POST http://host:port/<URI>:<VERB>

URI: /v1/models/{MODEL_NAME}[/versions/{MODEL_VERSION}]
VERB: classify|regress|predict

Für unser Modell können wir die folgende URL für Vorhersagen verwenden: http://localhost:8501/v1/models/resnet_unfreeze_all_filtered:predict

Die Portnummer (hier 8501) ist der Port des Hosts, den wir oben angegeben haben, um ihn auf den Port 8501 des Serving-Images abzubilden. Wie oben erwähnt, ist 8501 der Port des Serving-Containers, der für die REST-API verwendet wird. Die Modellversion ist optional und wird standardmäßig auf die neueste Version gesetzt, wenn sie weggelassen wird.

In Python kann die Bibliothek requests verwendet werden, um HTTP-Anfragen zu senden. Wie in der Dokumentation angegeben, muss der Request-Body für die predict API ein JSON-Objekt mit den unten aufgeführten Schlüssel-Wert-Paaren sein:

import json
import requests

# Send image as list to TF serving via json dump
request_url = 'http://localhost:8501/v1/models/resnet_unfreeze_all_filtered:predict'
request_body = json.dumps({"signature_name": "serving_default", "instances": img.tolist()})
request_headers = {"content-type": "application/json"}
json_response = requests.post(request_url, data=request_body, headers=request_headers)
response_body = json.loads(json_response.text)
predictions = response_body['predictions']

# Get label from prediction
y_hat_idx = np.argmax(predictions)
y_hat = classes[y_hat_idx]

Der Response-Body ist ebenfalls ein JSON-Objekt mit einem einzigen Schlüssel namens predictions. Da wir für jede Zeile in den Instanzen die Wahrscheinlichkeit für alle 300 Klassen erhalten, verwenden wir np.argmax, um die wahrscheinlichste Klasse zurückzugeben. Alternativ hätten wir auch die übergeordnete classify-API verwenden können.

Fazit

In diesem zweiten Blog-Artikel der Serie „Car Model Classification“ haben wir gelernt, wie ein TensorFlow-Modell zur Bilderkennung mittels TensorFlow Serving als RestAPI bereitgestellt werden kann, und wie damit Modellabfragen ausgeführt werden können.

Dazu haben wir zuerst das Modell im SavedModel Format abgespeichert. Als nächstes haben wir den TensorFlow Serving-Server in einem Docker-Container gestartet. Schließlich haben wir gezeigt, wie man Vorhersagen aus dem Modell mit Hilfe der API-Endpunkte und einem korrekt spezifizierten Request Body anfordert.

Ein Hauptkritikpunkt an Deep Learning Modellen jeglicher Art ist die fehlende Erklärbarkeit der Vorhersagen. Im dritten Beitrag werden wir zeigen, wie man Modellvorhersagen mit einer Methode namens Grad-CAM erklären kann.

Stephan Müller Stephan Müller