Zu diesem Buch – sowie zu vielen weiteren O’Reilly-Büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei oreilly.plus+:

www.oreilly.plus

GANs mit PyTorch selbst
programmieren

Ein verständlicher Einstieg in
Generative Adversarial Networks

Tariq Rashid

Deutsche Übersetzung von
Frank Langenau

Tariq Rashid

Lektorat: Alexandra Follenius

Bibliografische Information der Deutschen Nationalbibliothek

ISBN:

1. Auflage 2020

Copyright © 2020 by Tariq Rashid

Translation Copyright © 2020 by dpunkt.verlag. All rights reserved.

Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint

Hinweis:

Schreiben Sie uns:

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

5 4 3 2 1 0

Inhalt

Einführung

Teil IPyTorch und neuronale Netze

1Grundlagen von PyTorch

Google Colab

PyTorch-Tensoren

Automatische Gradienten mit PyTorch

Berechnungsgraphen

Lernziele

2Erstes neuronales Netz mit PyTorch

Das MNIST-Bilddatensatz

Die MNIST-Daten abrufen

Ein Blick auf die Daten

Ein einfaches neuronales Netz

Das Training visualisieren

Die Klasse für den MNIST-Datensatz

Unsere Klassifizierer trainieren

Das neuronale Netz abfragen

Die Performance des Klassifizierers einfach ermitteln

3Verfeinerungen

Verlustfunktion

Aktivierungsfunktion

Optimierungsmethode

Normalisierung

Kombinierte Verfeinerungen

Lernziele

4Grundlagen von CUDA

NumPy vs. Python

NVIDIA CUDA

CUDA in Python verwenden

Lernziele

Teil IIGenerative Adversarial Networks erstellen

5Das GAN-Konzept

Bilder generieren

Gegnerisches Training

Ein GAN trainieren

GANs sind schwer zu trainieren

Lernziele

6Einfache 1010-Muster

Echte Datenquelle

Den Diskriminator erstellen

Den Diskriminator testen

Den Generator erstellen

Die Generatorausgabe überprüfen

Das GAN trainieren

Lernziele

7Handgeschriebene Ziffern

Die Datensatzklasse

Der MNIST-Diskriminator

Den Diskriminator testen

MNIST-Generator

Die Generatorausgabe testen

Das GAN trainieren

Mode Collapse

Das GAN-Training verbessern

Mit Startwerten experimentieren

Lernziele

8Menschliche Gesichter

Farbbilder

Der CelebA-Datensatz

Hierarchisches Datenformat

Die Daten abrufen

Die Daten inspizieren

Die Datensatzklasse

Der Diskriminator

Den Diskriminator testen

GPU-Beschleunigung

Der Generator

Die Generatorausgabe überprüfen

Das GAN trainieren

Lernziele

Teil IIIKomplexere GANs

9Convolutional GANs

Speicherbedarf

Lokalisierte Bildmerkmale

Faltungsfilter

Kerngewichte lernen

Merkmalshierarchie

MNIST-CNN

CelebA-CNN

Eigene Experimente

Lernziele

10Konditionierte GANs

cGAN-Architektur

Diskriminator

Generator

Trainingsschleife

Bilder grafisch darstellen

Ergebnisse für das konditionierte GAN

Lernziele

Fazit

Anhänge

AIdeale Verlustwerte

MSE-Verlust

BCE-Verlust

BGANs lernen Wahrscheinlichkeit

GANs merken sich die Trainingsdaten nicht

Vereinfachtes Beispiel

Bilder aus einer Wahrscheinlichkeitsverteilung generieren

Gruppen von Pixeln für Bildmerkmale lernen

Viele Modi und Mode Collapse

CBeispiele für Faltungen

Beispiel 1: Faltung mit Schrittweite 1, keine Auffüllung

Beispiel 2: Faltung mit Schrittweite 2, keine Auffüllung

Beispiel 3: Faltung mit Schrittweite 2, mit Auffüllung

Beispiel 4: Faltung mit Bedeckungslücken

Beispiel 5: Transponierte Faltung mit Schrittweite 2, keine Auffüllung

Beispiel 6: Transponierte Faltung mit Schrittweite 1, keine Auffüllung

Beispiel 7: Transponierte Faltung mit Schrittweite 2, mit Auffüllung

Ausgabegrößen berechnen

DInstabiles Lernen

Gradientenabstieg – für das Training von GANs geeignet?

Ein einfaches Konfliktbeispiel

Gradientenabstieg – nicht ideal für Konfliktspiele

Warum eine Kreisbahn?

EQuellen

Der MNIST-Datensatz

Der CelebA-Datensatz

NVIDIA und Google

Open Source

Index

Einführung

Künstliche Intelligenz explodiert!

Maschinelles Lernen und künstliche Intelligenz (KI) sind in den letzten Jahren regelrecht explodiert, und alle paar Monate vermelden die Nachrichten außergewöhnliche Leistungen.

Nicht nur, dass Ihr Smartphone Sie versteht, wenn Sie mit ihm sprechen, es kann auch recht gut zwischen verschiedenen menschlichen Sprachen übersetzen. Selbstfahrende Autos können inzwischen so sicher fahren wie Menschen. Und Maschinen sind heute in der Lage, manche Krankheiten genauer und früher zu diagnostizieren als erfahrene Ärzte.

Das alte chinesische Spiel Go wird seit 3.000 Jahren gespielt, und obwohl die Regeln einfacher sind als beim Schach, ist das Spiel selbst viel komplexer und verlangt längerfristige Strategien. Erst vor Kurzem waren Entwickler in der Lage, mit einem System für maschinelles Lernen erstmals gegen einen Weltmeister zu spielen und zu gewinnen. Dieses System für maschinelles Lernen hat zudem neue Spielstrategien entdeckt, von denen wir glauben, dass Menschen sie in diesen 3.000 Jahren nicht hätten finden können!

Jenseits dessen, dass KI-Systeme lernen können, Aufgabe ausführen, ist die Entdeckung neuer Strategien ein immenser Erfolg auf dem Gebiet des maschinellen Lernens.

Kreative KI

Im Oktober 2018 hat das renommierte Aktionshaus Christies ein Porträt für 432.500 Dollar verkauft. Dieses Gemälde wurde nicht von einer Person gemalt, sondern von einem neuronalen Netz generiert. Ein mit KI gemaltes Porträt, das für fast eine halbe Million Dollar verkauft wurde, ist ein Meilenstein in der Geschichte der Kunst.

Dieses neuronale Netz wurde mit einer neuen und spannenden Technik trainiert, dem sogenannten Adversarial Training (von engl. adversarial – gegnerisch). Die Architektur wird als Generative Adversarial Networks, kurz GANs, bezeichnet (etwa »erzeugende gegnerische Netzwerke«).

GANs stoßen auf großes Interesse, speziell im Bereich der kreativen Technik, weil sie Bilder erzeugen können, die sehr plausibel aussehen. Diese Bilder entstehen weder durch einfaches Kopieren und Einfügen von Teilen der Trainingsbeispiele noch durch unscharf gemittelte Trainingsdaten. Das ist es, was GANs von den meisten anderen Formen des maschinellen Lernens unterscheidet. GANs lernen, Bilder auf einer Ebene zu erzeugen, die weit über dem bloßen Replizieren oder Mitteln von Trainingsdaten liegt.

Yann LeCun, einer der weltweit führenden Forscher auf dem Gebiet der neuronalen Netze, hat GANs als »die coolste Idee des Deep Learning in den letzten 20 Jahren« bezeichnet.

GANs sind neu

Im Vergleich zu den jahrzehntelangen Forschungen und Verfeinerungen auf dem Gebiet der neuronalen Netze haben GANs erst 2014 mit dem inzwischen bahnbrechenden Paper von Ian Goodfellow die Aufmerksamkeit auf sich gezogen.

Das heißt, GANs sind ziemlich neu, und man beginnt gerade erst, die kreativen Möglichkeiten zu erforschen. Das bedeutet aber auch, dass wir noch nicht ganz verstehen, wie sie sich so effektiv trainieren lassen, wie wir es bei herkömmlichen Netzen bereits können. Wenn sie funktionieren, dann spektakulär gut. Aber viel zu oft scheitern sie. Die Arbeitsweise von GANs und die Gründe, die dazu führen können, dass sie scheitern, werden derzeit sehr intensiv erforscht.

Für wen dieses Buch gedacht ist

Dieses Buch richtet sich an alle, die erste Schritte unternehmen wollen, um das Wesen von GANs und deren Arbeitsweise zu verstehen. Es eignet sich auch für jeden, der lernen möchte, wie man sie mit Industriestandardtools tatsächlich erstellt.

In dieser Einführung wird versucht, eine verständliche, einfache Sprache zu verwenden und anhand zahlreicher Bilder Ideen visuell zu erklären. Ich werde unnötige Fachausdrücke vermeiden und mathematische Gleichungen nur wenn unbedingt nötig verwenden.

Mein Ziel ist es, möglichst vielen Lesern mit ganz unterschiedlichem Hintergrund GANs nahezubringen und sie dafür zu begeistern, eigene GANs zu erstellen.

Dieses Buch versucht nicht, jedes Thema erschöpfend zu behandeln oder eine Enzyklopädie für GANs zu sein. Es deckt absichtlich nur das Minimum ab, damit Sie eine solide Grundlage bekommen, auf der Sie zu weiterführenden Erkundungstouren aufbrechen können.

Teilnehmer an Kursen für maschinelles Lernen werden in diesem Buch eine gute Basis für das weitere Studium von GANs finden.

Neuronale Netze

GANs bestehen aus neuronalen Netzen. Auch wenn dieser Leitfaden hierzu eine kleine Auffrischung bringt, ist mein vorheriges Buch Neuronale Netze selbst programmieren (O’Reilly 2017) als behutsamste Einführung in neuronale Netze und ihre Arbeitsweise zu empfehlen. Es bietet auch eine Einführung in die Analysis und den Gradientenabstieg, was für die bevorstehende Reise in GANs nützlich ist.

Darüber hinaus enthält es eine Einführung in die Programmierung mit Python, die gerade genug abdeckt, um einfache neuronale Netze in eigener Regie aufzubauen.

Wie Sie dieses Buch verwenden

Ein Konzept lernt und versteht man am besten, wenn man es praktisch anwendet – Learning by Doing. Deshalb entwickelt dieses Buch Ideen und Theorien rund um eine praktische Schritt-für-Schritt-Reise.

Dieser Leitfaden wird Sie begleiten auf dieser Reise, auf der wir manchmal scheitern, bevor wir eine Lösung finden. Zu scheitern und sich durch die Abhilfemaßnahmen durchzuarbeiten, ist eine echte Erfahrung, und das ist viel wertvoller als die bloße Lektüre theoretischer Anleitungen zu GANs.

Freie und Open-Source-Software

Alle hier vorgestellten Tools und Dienste, mit denen Sie Ihre eigenen GANs aufbauen können, sind entweder kostenlos oder Open Source und kostenlos. Dies ist wichtig, um möglichst wenige Menschen davon auszuschließen, etwas über neuronale Netze und GANs zu lernen und diese selbst zu erstellen.

Python ist eine der beliebtesten und am leichtesten zu erlernenden Programmiersprachen und hat sich als Standard im maschinellen Lernen und der KI etabliert. Zudem gibt es eine lebhafte globale Community und ein gesundes Ökosystem von Bibliotheken.

Google bietet derzeit eine kostenlose webbasierte Python-Umgebung namens Google Colab an, was bedeutet, dass Sie weder Python noch irgendeine andere Software installieren müssen. Sie können leistungsstarke neuronale Netz vollständig in der Infrastruktur von Google entwickeln und ausführen, wofür Sie lediglich einen modernen Webbrowser benötigen, der auf einem recht bescheidenen Computer oder Laptop läuft.

PyTorch ist eine Erweiterung von Python, mit der sich Modelle für maschinelles Lernen einfach entwerfen, erstellen und ausführen lassen. Neben TensorFlow gehört es zu den beliebtesten Frameworks für maschinelles Lernen.

Alle diese Tools zählen auch zum Industriestandard, sodass Sie wertvolle wiederverwendbare Fähigkeiten erwerben.

Anmerkung des Autors

Ich sehe meine Mission als gescheitert an, wenn irgendein Leser Schwierigkeiten hat, zu verstehen, was GANs sind und wie sie trainiert werden. Ich hätte auch versagt, wenn Sie nicht in der Lage sind, Ihr eigenes einfaches GAN zu erstellen.

Der Inhalt dieses Buchs ist mit einer Reihe von Studenten und Entwicklern getestet worden. Wenn also irgendetwas nicht schlüssig erscheint, kontaktieren Sie mich bitte über twitter@myoneuralnet, per E-Mail unter makeyourownneuralnetwork@gmail.com oder auf GitHub:

Zusätzliche Erörterungen und Antworten auf interessante Leserfragen finden Sie im Blog, der dieses und das vorherige Buch begleitet:

Abschließend möchte ich Ihnen wärmstens empfehlen, sich Ihrer lokalen Community für maschinelles Lernen oder algorithmische Kunst anzuschließen. Lernen in einer Gruppe ist viel effektiver, denn es macht Spaß, seine Arbeit mit anderen zu teilen und sich von dem inspirieren zu lassen, was andere sich ausdenken.

Viel Spaß dabei!

TEIL I

PyTorch und neuronale Netze

Zuerst lernen Sie PyTorch kennen und setzen es dann in der Praxis ein, indem Sie einen einfachen Klassifizierer für Bilder erstellen und Ihr Wissen zu neuronalen Netzen auffrischen.

KAPITEL 1

Grundlagen von PyTorch

In meinem letzten Buch Neuronale Netze selbst programmieren haben wir einfache, aber effektive neuronale Netze erstellt, und zwar ausschließlich mit Python und der Bibliothek NumPy für das Verarbeiten von Datenarrays.

Auf beliebte Frameworks wie PyTorch und TensorFlow für das Erstellen von neuronalen Netzen haben wir verzichtet, weil es wichtig war, die Netze von Grund auf neu aufzubauen, um ihre Funktionsweise wirklich zu verstehen.

Diese ganze Arbeit, die wir zu Fuß erledigen mussten, macht deutlich, dass der Aufbau größerer Netzwerke eine mühsame Aufgabe werden könnte. Einer der aufwendigsten Bereiche ist die Berechnung der Beziehung zwischen dem Fehler, der durch Backpropagation zurückgegeben wurde, und den Gewichten in unserem Netz. Wenn wir das Netz verändern, müssen wir möglicherweise die gesamte Arbeit noch einmal absolvieren.

Hier werden wir PyTorch einsetzen, weil uns diese Bibliothek eine Menge Routinearbeiten abnimmt, sodass wir uns auf den Entwurf unserer Netze konzentrieren können.

Zu den leistungsfähigsten und komfortabelsten Features von PyTorch gehört, dass die Bibliothek sämtliche Berechnungen für uns erledigt, egal welche Gestalt oder Größe das Netz hat, das wir uns ausdenken. Und wenn wir das Design unseres Netzes verändern, passt PyTorch die Berechnungen automatisch an, ohne dass wir Bleistift und Papier auspacken müssen, um die Gradienten erneut zu berechnen.

Außerdem hat man sich bei PyTorch wirklich sehr darum bemüht, dem Look-and-feel von normalem Python zu entsprechen. Das bedeutet, es ist leicht zu erlernen, wenn Sie Python bereits kennen, und es gibt weniger Überraschungen, wenn Sie damit arbeiten.

Google Colab

Wir haben im Buch Neuronale Netze selbst programmieren Code mithilfe der webbasierten Python-Notebooks geschrieben, die auf unserem eigenen Computer gelaufen sind. Jetzt verwenden wir Python-Notebooks, die der kostenlose Dienst Colab von Google bereitstellt und die unseren Code auf den Google-eigenen Computern ausführen.

Der Zugriff auf Colab-Dienste von Google erfolgt gänzlich über einen Webbrowser. Es ist nicht erforderlich, irgendwelche Software auf dem eigenen Computer oder Laptop zu installieren.

Bevor wir loslegen, sollten Sie sich mit einem Google-Konto anmelden. Wenn Sie über ein Gmail- oder YouTube-Konto verfügen, ist dies Ihr Google-Konto. Haben Sie noch kein Google-Konto eingerichtet, können Sie eines über den folgenden Link erstellen:

Sobald Sie angemeldet sind, aktivieren Sie den Colab-Dienst von Google, indem Sie den diesen Link besuchen:

Von dieser Seite aus gelangen Sie zu einem Beispiel-Python-Notebook. Wählen Sie im Menü File den Eintrag New Python 3 notebook, um ein neues Notebook anzulegen (siehe Abbildung 1-1).

Abbildung 1-1: Die Startseite von Google Colab

Es erscheint ein leeres Python-Notebook (siehe Abbildung 1-2), das wir sofort verwenden können.

Abbildung 1-2: Ein neues leeres Python-Notebook

Wenn Sie sich auf einem separaten Browser-Tab den Google-Dateispeicher Drive ansehen, finden Sie einen neuen Ordner namens Colab Notebooks. Dies ist der Ordner, in dem neue Python-Notebooks standardmäßig gespeichert werden.

Abbildung 1-3 zeigt ein neues Notebook mit dem Namen Untitled0.ipynb.

Abbildung 1-3: Ein neues Notebook mit dem Namen »Untitled0.ipynb«

Wir überprüfen nun, ob wir Python-Code ausführen können. Tippen Sie in die erste Zelle den folgenden einfachen Code ein:

2 + 3

Klicken Sie auf die Schaltfläche mit dem Abspielen-Symbol links neben der Zelle, um den Code auszuführen. Wenn Sie den Colab-Dienst bisher noch nicht genutzt haben, kann es eine Weile dauern, bis die erste Python-Anweisung ausgeführt wird, da Google einen Moment braucht, um eine virtuelle Maschine zu starten und Ihr Notebook mit ihr zu verbinden.

Schließlich sollte die Antwort 5 erscheinen, wie Abbildung 1-4 zeigt.

Abbildung 1-4: Das Ergebnis des ausgeführten Codes

Großartig! Alles funktioniert, und wir sind bereit, mehr über PyTorch zu erfahren.

PyTorch-Tensoren

Bevor wir PyTorch verwenden können, müssen wir das Python-Modul torch importieren. Erfreulicherweise hält der Colab-Service von Google viele dieser beliebten Bibliotheken für maschinelles Lernen für uns bereit, PyTorch eingeschlossen. Wir müssen die Bibliotheken nur noch importieren, um sie unmittelbar einsetzen zu können. Es ist nicht erforderlich, einen komplizierten Installationsprozess zu durchlaufen.

Geben Sie den folgenden Code in die erste Zelle ein und führen Sie ihn aus:

import torch

Um PyTorch zu verstehen, bietet es sich an, seine grundlegenden Informationseinheiten mit reinem Python zu vergleichen. In reinem Python speichern wir Zahlen in Variablen. Diese Variablen können wir wie mathematische Symbole verwenden, um neue Werte zu berechnen und diese in neuen Variablen zu speichern, wenn wir das wünschen.

Sehen Sie sich dazu den folgenden einfachen Python-Code an:

# Normale Python-Variablen

x = 3.5

y = x*x + 2

print(x, y)

Wir erzeugen eine Variable x und geben ihr den Wert 3.5. Dann erzeugen wir eine neue Variable y und geben ihr einen Wert, der aus dem Ausdruck x*x + 2 berechnet wird, was (3.5*3.5) + 2 oder 14.25 ist. Schließlich geben wir die Werte von x und y aus.

Tippen Sie den Code in eine neue Zelle ein und führen Sie ihn aus. Abbildung 1-5 zeigt, wie das Ergebnis aussehen sollte.

Abbildung 1-5: Die Verwendung einer Variablen

PyTorch hat eine eigene Form von Variablen, um Zahlen zu speichern – die sogenannten PyTorch-Tensoren. Mit den folgenden Anweisungen erstellen Sie einen sehr einfachen Tensor:

# Einfacher PyTorch-Tensor

x = torch.tensor(3.5)

print(x)

Wir erzeugen hier etwas, das x genannt wird. Dieses x ist ein PyTorch-Tensor, der mit dem Wert 3.5 initialisiert wird.

Geben Sie den Code ein und führen Sie ihn aus, um zu sehen, was die Ausgabe von x bewirkt.

Abbildung 1-6: Einen PyTorch-Tensor erzeugen und ausgeben

Die Ausgabe zeigt, dass der numerische Wert 3.5000 beträgt, aber auch, dass er in einem PyTorch-tensor enthalten ist. Es ist nützlich zu wissen, in welcher Art von Container diese Zahl gespeichert ist.

Führen wir nun einige einfache arithmetische Berechnungen mit diesem Tensor aus. Geben Sie in die nächste Zelle den folgenden Code ein:

# Einfache Arithmetik mit Tensoren

y = x + 3

print(y)

Hier erzeugen wir aus dem Ausdruck x + 3 eine neue Variable y. Eben haben wir x als PyTorch-Tensor mit dem Wert 3.5 erzeugt. Welchen Wert wird also y haben?

Probieren Sie es aus.

Abbildung 1-7: Arithmetik mit einem Tensor

Wie Abbildung 1-7 zeigt, hat y den Wert 6.5, was Sinn ergibt, denn 3.5 + 3 = 6.5. Außerdem sehen wir, dass y ebenfalls ein PyTorch-Tensor ist.

Sicherlich erinnern Sie sich daran, dass auch NumPy-Arrays in der gleichen Weise funktionieren. Diese Vertrautheit kommt uns entgegen, und durch die Übereinstimmung mit NumPy ist es zudem einfacher, PyTorch zu erlernen.

Automatische Gradienten mit PyTorch

Sehen wir uns nun an, wie sich PyTorch von reinem Python und NumPy abhebt und es so besonders macht. Der folgende Code erzeugt genau wie zuvor einen Tensor x, dieses Mal aber geben wir PyTorch eine zusätzliche Option requires_grad= True mit. Wir werden bald sehen, was diese Option bewirkt.

# PyTorch-Tensor

x = torch.tensor(3.5, requires_grad=True)

print(x)

Führen Sie den Code aus und sehen Sie sich an, was für x ausgegeben wird (siehe Abbildung 1-8).

Abbildung 1-8: Eine Tensoroperation mit einer zusätzlichen Option

Wie Abbildung 1-8 zeigt, hat x den Wert 3.5000 und ist vom Typ tensor. Aus der Ausgabe geht auch hervor, dass für den Tensor x die Option requires_grad auf True gesetzt ist.

Wir erzeugen nun wie zuvor eine neue Variable y aus x, dieses Mal aber mit einem anderen Ausdruck:

# y wird als Funktion von x definiert

y = (x-1) * (x-2) * (x-3)

print(y)

Der Code berechnet y aus dem Ausdruck (x-1) * (x-2) * (x-3). Führen Sie den Code aus.

Abbildung 1-9: Eine Variable als Funktion definieren

Wie Abbildung 1-9 zeigt, beträgt der Wert von y wie erwartet 1.8750. Das ergibt sich daraus, dass x gleich 3.5 ist und somit (3.5-1) * (3.5-2) * (3.5-3) das Ergebnis 1.8750 liefert.

Abbildung 1-10 mit dem Graphen der Funktion y = (x-1) * (x-2) * (x-3) veranschaulicht, was wir eben berechnet haben.

Abbildung 1-10: Der Graph der Funktion y = (x-1) * (x-2) * (x-3)

Bislang erscheint alles normal und vertraut.

Tatsächlich hat PyTorch aber zusätzliche Arbeit geleistet, die wir nicht gesehen haben. Denn PyTorch hat nicht einfach den Wert 1.8750 berechnet und in einen Tensor namens y gestellt. Vielmehr hat sich PyTorch tatsächlich daran erinnert, dass y mathematisch in Form von x definiert ist.

Wären x und y normale Python-Variablen oder sogar NumPy-Arrays, käme Python nicht auf die Idee, dass y von x kommt. Das ist auch nicht notwendig. Nachdem der Wert von y berechnet ist, und zwar aus x, ist nur noch dieser Wert an sich wichtig und dass er in y steht. Fertig.

PyTorch-Tensoren funktionieren anders. Sie merken sich, aus welchen anderen Tensoren sie berechnet werden und wie. Im Beispiel erinnert sich PyTorch daran, dass y von x gekommen ist.

Weshalb ist das nützlich? Schauen wir mal.

Sie werden sich erinnern, dass es bei den Berechnungen zum Trainieren eines neuronalen Netzes erforderlich ist, den Fehlergradienten per Analysis zu bestimmen, das heißt die Rate, mit der sich der Ausgabefehler infolge veränderter Gewichte für die Netzverknüpfungen ändert.

Die Ausgabe eines neuronalen Netzes wird von den Verknüpfungsgewichten bestimmt. Diese Ausgabe hängt von den Gewichten genau so ab, wie y von x abhängt. Sehen wir uns also an, wie PyTorch die Änderungsrate von y ermitteln kann, wenn sich x verändert.

Wir berechnen den Gradienten von y bei x = 3.5, das heißt, dy/dx bei x = 3.5.

Hierfür muss PyTorch für y feststellen, von welchen Tensoren es abhängt und wie die mathematische Form dieser Abhängigkeit aussieht. Dann kann es dy/dx berechnen.

# Gradienten berechnen

y.backward()

Diese einzelne Anweisung erledigt das alles. PyTorch betrachtet y, sieht, dass es von (x-1) * (x-2) * (x-3) kommt, und ermittelt automatisch den Gradienten dy/dx, der – wenn Sie es auflösen – den Ausdruck 3x2 - 12x + 11 ergibt.

Diese Anweisung berechnet auch den numerischen Wert dieses Gradienten und setzt ihn in den Tensor x neben den eigentlichen Wert von x. Da x gleich 3.5 ist, wird der Gradient zu 3*(3.5*3.5) - 12*(3.5) + 11 = 5.75.

Der Graph in Abbildung 1-11 veranschaulicht, wo wir diesen Gradienten berechnet haben.

Abbildung 1-11: Berechnung des Gradienten an der Stelle x = 3.5

Das ist ein beeindruckendes Arbeitsergebnis, das wir von y.backward() mit nur einer einzigen Anweisung bekommen haben!

Wir können den numerischen Wert des Gradienten, der in den Tensor x gestellt wurde, inspizieren:

# Wert des Gradienten bei x = 3.5

x.grad

Führen Sie den Code aus, um zu kontrollieren, ob er korrekt funktioniert.

Abbildung 1-12: Den Wert eines Gradienten ermitteln

Wie Abbildung 1-12 zeigt, hat er funktioniert!

An der Option requires_grad=True, die wir für den Tensor x gesetzt haben, erkennt PyTorch, dass wir an der Berechnung eines Gradienten in Bezug auf x interessiert sind.

Es ist also zu sehen, dass PyTorch-Tensoren reicher sind als normale Python-Variablen und NumPy-Arrays. Ein PyTorch-Tensor kann enthalten:

  • zusätzliche Informationen über den primären Zahlenwert hinaus, beispielsweise einen Gradientenwert,
  • Informationen darüber, von welchen anderen Tensoren er abhängt, und die mathematische Form dieser Abhängigkeit.

Wir haben hier ein Beispiel für eine sehr wertvolle Fähigkeit gesehen. Diese Fähigkeit, Tensoren zu verknüpfen und ein automatisches Differenzieren durchzuführen, ist eines der wichtigsten Features von PyTorch.

Ein Notebook des Codes, mit dem wir gerade gearbeitet haben, finden Sie online unter:

  • https://github.com/makeyourownneuralnetwork/gan/blob/master/00_pytorch_basics.ipynb

Berechnungsgraphen

Diese eben vorgestellte automatische Gradientenberechnung scheint magisch zu sein, aber das ist sie natürlich nicht.

Es lohnt sich trotzdem, ein wenig davon zu verstehen, weil dieses Wissen uns später helfen wird, wenn es um den Aufbau größerer Netze geht.

Sehen Sie sich das sehr einfache Netz in Abbildung 1-13 an. Es ist kein neuronales Netz, sondern lediglich eine Folge von Berechnungen.

Abbildung 1-13: Ein sehr einfaches Netz

Abbildung 1-13 zeigt einen Eingang x, der verwendet wird, um y zu berechnen, das dann verwendet wird, um z, den Ausgang, zu berechnen.

Stellen Sie sich vor, dass y und z wie in Abbildung 1-14 gezeigt berechnet werden.

Abbildung 1-14: Berechnung von y und z

Wenn wir wissen wollen, wie sich die Ausgabe z verändert, wenn x variiert, müssen wir einige Berechnungen anstellen, um den Gradienten dy/dx zu ermitteln. Wir führen das schrittweise durch.

Abbildung 1-15: Schritte beim Berechnen des Gradienten

Die erste Zeile ist die Kettenregel der Differenzialrechnung. Als Ausgangspunkt ist sie uns hier sehr nützlich. Falls Sie eine Auffrischung brauchen: Einer der Anhänge meines Buchs Neuronale Netze selbst programmieren ist eine Einführung in die Analysis und die Kettenregel.

Wir haben also gerade herausgefunden, dass die Ausgabe z mit x als 4x variiert. Wenn x = 3.5 ist, wird dz/dx zu 4*3.5 = 14.

Wenn y in Form von x und z in Form von y definiert ist, erstellt PyTorch ein Bild, wie diese Tensoren verknüpft sind. Dieses Bild ist ein sogenannter Berechnungsgraph.

Abbildung 1-16 zeigt, wie er für unser Beispiel aussehen könnte.

Abbildung 1-16: Der Berechnungsgraph für unser Beispiel

In Abbildung 1-16 sehen Sie, wie y aus x und z aus y berechnet wird. Zusätzlich fügt PyTorch Rückwärtspfeile hinzu, die zeigen, wie sich y ändert, wenn sich xzy