Convolutional Neural Networks, mit Keras und TPUs

1. Übersicht

In diesem Lab lernen Sie, wie Sie eine Convolutional Layer in ein neuronales Netzwerkmodell einbinden, das Blumen erkennen kann. Dieses Mal erstellen Sie das Modell von Grund auf neu und nutzen die Leistungsfähigkeit von TPU, um es in Sekundenschnelle zu trainieren und das Design zu iterieren.

Dieses Lab enthält die erforderlichen theoretischen Erklärungen zu Convolutional Neural Networks und ist ein guter Ausgangspunkt für Entwickler, die sich mit Deep Learning vertraut machen möchten.

Dieses Lab ist Teil 3 der Serie „Keras on TPU“. Sie können sie in der folgenden Reihenfolge oder unabhängig voneinander ausführen.

ca8cc21f6838eccc.png

Lerninhalte

  • Erstellen eines Convolutional-Bildklassifikators mithilfe eines Keras Sequential-Modells.
  • Keras-Modell auf TPU trainieren
  • Zur Feinabstimmung Ihres Modells mit einer guten Auswahl an Faltungsebenen.

Feedback

Bitte teilen Sie uns mit, wenn Sie in diesem Code-Lab etwas nicht erkennen. Sie können Feedback über GitHub-Probleme [ feedback link] geben.

2. Kurzanleitung für Google Colaboratory

Für dieses Lab wird Google Collaboratory verwendet. Sie müssen nichts einrichten. Colaboratory ist eine Online-Notebook-Plattform für Bildungszwecke. Es bietet kostenloses CPU-, GPU- und TPU-Training.

688858c21e3beff2.png

Sie können dieses Beispiel-Notebook öffnen und einige Zellen durchgehen, um sich mit Colaboratory vertraut zu machen.

c3df49e90e5a654f.png Welcome to Colab.ipynb

TPU-Back-End auswählen

8832c6208c99687d.png

Wählen Sie im Colab-Menü Laufzeit > Laufzeittyp ändern und dann TPU aus. In diesem Codelab verwenden Sie eine leistungsstarke TPU (Tensor Processing Unit), die für hardwaregestütztes Training unterstützt wird. Die Verbindung zur Laufzeit erfolgt bei der ersten Ausführung automatisch. Alternativ können Sie auf die Schaltfläche „Verbinden“ in der oberen rechten Ecke klicken.

Notebook-Ausführung

76d05caa8b4db6da.png

Führen Sie die Zellen einzeln aus, indem Sie auf eine Zelle klicken und die Umschalttaste und die Eingabetaste drücken. Sie können das gesamte Notebook auch mit Laufzeit > Alle ausführen ausführen.

Inhaltsverzeichnis

429f106990037ec4.png

Alle Notebooks haben ein Inhaltsverzeichnis. Sie können ihn mit dem schwarzen Pfeil auf der linken Seite öffnen.

Ausgeblendete Zellen

edc3dba45d26f12a.png

In einigen Zellen wird nur der Titel angezeigt. Dies ist eine Colab-spezifische Notebook-Funktion. Sie können darauf doppelklicken, um den Code zu sehen, der aber in der Regel nicht sehr interessant ist. Sie unterstützen in der Regel Funktionen für die Visualisierung. Sie müssen diese Zellen trotzdem ausführen, damit die darin enthaltenen Funktionen definiert werden.

Authentifizierung

cdd4b41413100543.png

Colab kann auf Ihre privaten Google Cloud Storage-Buckets zugreifen, sofern Sie sich mit einem autorisierten Konto authentifizieren. Das Code-Snippet oben löst einen Authentifizierungsprozess aus.

3. [INFO] Was sind Tensor Processing Units (TPUs)?

Kurz und bündig

f88cf6facfc70166.png

Code zum Trainieren eines Modells auf einer TPU in Keras (mit automatischem Wechsel zu GPU oder CPU, falls keine TPU verfügbar ist):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Wir verwenden TPUs heute, um einen Blumenklassifikator mit interaktiven Geschwindigkeiten (Minuten pro Trainingslauf) zu entwickeln und zu optimieren.

688858c21e3beff2.png

Warum TPUs?

Moderne GPUs sind um programmierbare „Kerne“ organisiert, eine sehr flexible Architektur, mit der eine Vielzahl von Aufgaben wie 3D-Rendering, Deep Learning, physische Simulationen usw. ausgeführt werden können. TPUs hingegen kombinieren einen klassischen Vektorprozessor mit einer dedizierten Matrixmultiplikationseinheit. Sie eignen sich für alle Aufgaben, bei denen große Matrixmultiplikationen dominieren, z. B. neuronale Netzwerke.

8eb3e718b8e2ed08.png

Illustration: Eine dichte neuronale Netzwerkschicht als Matrixmultiplikation mit einem Batch von acht Bildern, die gleichzeitig durch das neuronale Netzwerk verarbeitet werden. Bitte führen Sie eine Zeile × Spalte-Multiplikation durch, um zu prüfen, ob tatsächlich eine gewichtete Summe aller Pixelwerte eines Bildes berechnet wird. Faltungsschichten können auch als Matrixmultiplikationen dargestellt werden, obwohl dies etwas komplizierter ist ( Erläuterung in Abschnitt 1).

Die Hardware

MXU und VPU

Ein TPU v2-Kern besteht aus einer Matrix Multiply Unit (MXU), die Matrixmultiplikationen durchführt, und einer Vector Processing Unit (VPU) für alle anderen Aufgaben wie Aktivierungsfunktionen und Softmax. Die VPU verarbeitet float32- und int32-Berechnungen. Die MXU hingegen arbeitet mit einem Gleitkommaformat mit gemischter Genauigkeit von 16 bis 32 Bit.

7d68944718f76b18.png

Gleitkomma mit gemischter Genauigkeit und bfloat16

Die MXU berechnet Matrixmultiplikationen mit bfloat16-Eingängen und float32-Ausgaben. Zwischenakkumulierungen werden mit der Genauigkeit float32 ausgeführt.

19c5fc432840c714.png

Das Training von neuronalen Netzwerken ist in der Regel unempfindlich gegenüber dem Rauschen, das durch eine reduzierte Gleitkommagenauigkeit verursacht wird. Es gibt Fälle, in denen das Rauschen dem Optimierungstool sogar beim Konvergieren hilft. Üblicherweise wurde 16-Bit-Gleitkommagenauigkeit zur Beschleunigung von Berechnungen verwendet, aber die Formate float16 und float32 haben sehr unterschiedliche Bereiche. Die Reduzierung der Precision von float32 auf float16 führt in der Regel zu Über- und Unterflüssen. Lösungen gibt es, aber es ist in der Regel zusätzliche Arbeit erforderlich, damit float16 funktioniert.

Aus diesem Grund hat Google das bfloat16-Format in TPUs eingeführt. bfloat16 ist eine gekürzte Float32-Zahl mit genau denselben Exponentenbits und demselben Bereich wie Float32. Zusammen mit der Tatsache, dass TPUs Matrixmultiplikationen mit gemischter Genauigkeit mit bfloat16-Eingängen, aber float32-Ausgaben berechnen, sind in der Regel keine Codeänderungen erforderlich, um von den Leistungsvorteilen einer reduzierten Genauigkeit zu profitieren.

Systolic Array

Die MXU implementiert Matrixmultiplikationen in der Hardware mithilfe einer sogenannten „systolischen Array“-Architektur, in der Datenelemente durch eine Reihe von Hardware-Recheneinheiten fließen. (In der Medizin bezieht sich „systolisch“ auf Herzkontraktionen und Blutfluss, hier auf den Datenfluss.)

Das Grundelement einer Matrixmultiplikation ist ein Punktprodukt zwischen einer Linie aus einer Matrix und einer Spalte aus der anderen Matrix (siehe Abbildung oben in diesem Abschnitt). Bei einer Matrixmultiplikation Y=X*W würde ein Element des Ergebnisses so aussehen:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

Auf einer GPU würde man dieses Punktprodukt in einen GPU-„Kern“ programmieren und dann auf so vielen „Kernen“ ausführen, wie parallel verfügbar sind, um zu versuchen, jeden Wert der resultierenden Matrix auf einmal zu berechnen. Wenn die resultierende Matrix 128 x 128 groß ist, wären 128 x 128=16.000 "Kerne" verfügbar, was normalerweise nicht möglich ist. Die größten GPUs haben etwa 4.000 Kerne. Eine TPU hingegen verwendet nur das Nötigste an Hardware für die Recheneinheiten in der MXU: nur bfloat16 x bfloat16 => float32 Multiplikator-Akkumulatoren, sonst nichts. Diese sind so klein, dass eine TPU 16.000 davon in einer 128 x 128 MXU implementieren und diese Matrixmultiplikation auf einmal verarbeiten kann.

f1b283fc45966717.gif

Illustration: Das systolische Array von MXU. Die Rechenelemente sind Multiplikator-Akkumulatoren. Die Werte einer Matrix werden in das Array geladen (rote Punkte). Die Werte der anderen Matrix fließen durch das Array (graue Punkte). Vertikale Linien leiten die Werte nach oben weiter. Horizontale Linien geben Teilsummen weiter. Es bleibt dem Nutzer überlassen, zu überprüfen, ob das Ergebnis der Matrixmultiplikation auf der rechten Seite ausgegeben wird, wenn die Daten durch das Array fließen.

Während die Punktprodukte in einer MXU berechnet werden, fließen Zwischensummen einfach zwischen benachbarten Recheneinheiten. Sie müssen nicht gespeichert und aus dem Speicher oder aus einer Registrierungsdatei abgerufen werden. Das Endergebnis ist, dass die systolische TPU-Array-Architektur bei der Berechnung von Matrixmultiplikationen einen erheblichen Dichte- und Leistungsvorteil sowie einen nicht vernachlässigbaren Geschwindigkeitsvorteil gegenüber einer GPU hat.

Cloud TPU

Wenn Sie eine Cloud TPU v2 auf der Google Cloud Platform anfordern, erhalten Sie eine virtuelle Maschine (VM) mit einem PCI-angebundenen TPU-Board. Die TPU-Platine hat vier Dual-Core-TPU-Chips. Jeder TPU-Kern verfügt über eine VPU (Vector Processing Unit) und eine 128 × 128 MXU (MatriX Multiply Unit). Diese „Cloud TPU“ ist dann normalerweise über das Netzwerk mit der VM verbunden, die sie angefordert hat. Das vollständige Bild sieht so aus:

dfce5522ed644ece.png

Abbildung: Ihre VM mit einem netzwerkgebundenen „Cloud TPU“-Beschleuniger. „Die Cloud TPU“ selbst besteht aus einer VM mit einem PCI-angebundenen TPU-Board mit vier Dual-Core-TPU-Chips.

TPU-Pods

In den Rechenzentren von Google sind TPUs mit einer Hochleistungs-Computing-Verbindung (High Performance Computing, HPC) verbunden, wodurch sie wie ein sehr großer Beschleuniger erscheinen können. Google nennt sie Pods. Sie können bis zu 512 TPU v2- oder 2.048 TPU v3-Kerne umfassen.

2ec1e0d341e7fc34.jpeg

Abbildung: TPU v3-Pod TPU-Boards und -Racks, die über HPC Interconnect verbunden sind.

Während des Trainings werden Gradienten mithilfe des Allreduce-Algorithmus zwischen TPU-Kernen ausgetauscht (gute Erklärung von Allreduce hier). Das trainierte Modell kann die Hardware nutzen, indem es mit großen Batchgrößen trainiert wird.

d97b9cc5d40fdb1d.gif

Illustration: Synchronisierung von Gradienten während des Trainings mit dem Algorithmus „All-Reduce“ im 2-D-Toroidal-Mesh-HPC-Netzwerk von Google TPU.

Die Software

Training mit großen Batchgrößen

Die ideale Batchgröße für TPUs beträgt 128 Datenelemente pro TPU-Kern. Die Hardware kann jedoch bereits bei 8 Datenelementen pro TPU-Kern eine gute Auslastung erzielen. Eine Cloud TPU hat 8 Kerne.

In diesem Code-Lab verwenden wir die Keras API. In Keras ist der von Ihnen angegebene Batch die globale Batchgröße für die gesamte TPU. Ihre Batches werden automatisch in acht aufgeteilt und auf den 8 Kernen der TPU ausgeführt.

da534407825f01e3.png

Weitere Tipps zur Leistung finden Sie im TPU-Leistungsleitfaden. Bei sehr großen Batchgrößen sind bei einigen Modellen besondere Sorgfalt erforderlich. Weitere Informationen finden Sie unter LARSOptimizer.

Details: XLA

TensorFlow-Programme definieren Berechnungsgrafiken. Auf der TPU wird Python-Code nicht direkt ausgeführt, sondern der von Ihrem Tensorflow-Programm definierte Berechnungsgraph. Intern wandelt ein Compiler namens XLA (beschleunigte lineare Algebra-Compiler-) den Tensorflow-Graphen von Rechenknoten in TPU-Maschinencode um. Dieser Compiler führt auch viele erweiterte Optimierungen an Ihrem Code und Ihrem Speicherlayout durch. Die Kompilierung erfolgt automatisch, während die Arbeit an die TPU gesendet wird. Sie müssen XLA nicht explizit in Ihre Build-Kette aufnehmen.

edce61112cd57972.png

Illustration: Zur Ausführung auf TPU wird der von Ihrem Tensorflow-Programm definierte Berechnungsgraph zuerst in eine XLA-Darstellung (beschleunigte lineare Algebra-Compiler-Darstellung) übersetzt und dann von XLA in TPU-Maschinencode kompiliert.

TPUs in Keras verwenden

TPUs werden ab TensorFlow 2.1 über die Keras API unterstützt. Die Keras-Unterstützung funktioniert auf TPUs und TPU-Pods. Hier ein Beispiel, das auf TPU, GPU(s) und CPU funktioniert:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

In diesem Code-Snippet gilt Folgendes:

  • TPUClusterResolver().connect() findet die TPU im Netzwerk. Die Funktion funktioniert ohne Parameter in den meisten Google Cloud-Systemen (AI Platform-Jobs, Colaboratory, Kubeflow sowie Deep Learning-VMs, die mit dem Dienstprogramm „ctpu up“ erstellt wurden). Diese Systeme wissen dank einer TPU_NAME-Umgebungsvariable, wo sich ihre TPU befindet. Wenn Sie eine TPU manuell erstellen, legen Sie entweder die TPU_NAME-Umgebungsvariable auf der VM fest, von der aus Sie sie verwenden, oder rufen Sie TPUClusterResolver mit expliziten Parametern auf: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy ist der Teil, der die Verteilung und den Gradientensynchronisierungsalgorithmus „all-reduce“ implementiert.
  • Die Strategie wird über einen Umfang angewendet. Das Modell muss im Strategiebereich definiert sein.
  • Die Funktion tpu_model.fit erwartet ein tf.data.Dataset-Objekt als Eingabe für das TPU-Training.

Häufige Aufgaben bei der TPU-Portierung

  • Es gibt zwar viele Möglichkeiten, Daten in ein TensorFlow-Modell zu laden, für TPUs ist jedoch die Verwendung der tf.data.Dataset API erforderlich.
  • TPUs sind sehr schnell und die Datenaufnahme wird oft zum Engpass, wenn sie darauf ausgeführt werden. Im TPU-Leistungsleitfaden finden Sie Tools, mit denen Sie Datenengpässe erkennen können, sowie weitere Leistungstipps.
  • int8- oder int16-Zahlen werden als int32 behandelt. Die TPU hat keine Ganzzahlhardware, die mit weniger als 32 Bit arbeitet.
  • Einige Tensorflow-Vorgänge werden nicht unterstützt. Die Liste finden Sie hier. Die gute Nachricht ist, dass diese Einschränkung nur für den Trainingscode gilt, also für den Vorwärts- und Rückwärtsdurchlauf durch Ihr Modell. Sie können weiterhin alle Tensorflow-Vorgänge in Ihrer Dateneingabepipeline verwenden, da sie auf der CPU ausgeführt wird.
  • tf.py_func wird auf TPUs nicht unterstützt.

4. [INFO] Klassifikator für neuronale Netzwerke – erste Schritte

Kurz und bündig

Wenn Ihnen alle Begriffe im nächsten Abschnitt, die fett hervorgehoben sind, bereits bekannt sind, können Sie mit der nächsten Übung fortfahren. Wenn Sie gerade erst mit Deep Learning beginnen, lesen Sie weiter.

Für Modelle, die als Folge von Ebenen erstellt wurden, bietet Keras die Sequential API an. Ein Bildklassifikator mit drei dichten Schichten kann beispielsweise in Keras so geschrieben werden:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

Dichtes neuronales Netzwerk

Dies ist das einfachste neuronale Netzwerk zur Klassifizierung von Bildern. Es besteht aus „Neuronen“, die in Schichten angeordnet sind. Die erste Schicht verarbeitet Eingabedaten und gibt die Ergebnisse an andere Schichten weiter. Sie wird als „dicht“ bezeichnet, weil jedes Neuron mit allen Neuronen aus der vorherigen Schicht verbunden ist.

c21bae6dade487bc.png

Sie können ein Bild in ein solches Netzwerk einspeisen, indem Sie die RGB-Werte aller seiner Pixel zu einem langen Vektor zusammenfassen und als Eingabe verwenden. Es ist nicht die beste Technik für die Bilderkennung, aber wir werden sie später verbessern.

Neuronen, Aktivierungen, RELU

Ein „Neuron“ berechnet eine gewichtete Summe aller Eingaben, fügt einen Wert hinzu, der als „Bias“ bezeichnet wird, und speist das Ergebnis in eine sogenannte „Aktivierungsfunktion“ ein. Die Gewichte und die Voreingenommenheit sind anfangs unbekannt. Sie werden zufällig initialisiert und „erlernt“, indem das neuronale Netzwerk mit vielen bekannten Daten trainiert wird.

644f4213a4ee70e5.png

Die gängigste Aktivierungsfunktion heißt RELU (Rectified Linear Unit). Wie Sie in der Abbildung oben sehen, ist es eine sehr einfache Funktion.

Softmax-Aktivierung

Das obige Netzwerk endet mit einer Schicht mit 5 Neuronen, da wir Blumen in fünf Kategorien unterteilen: Rose, Tulpe, Löwenzahn, Gänseblümchen, Sonnenblume. Neuronen in Zwischenschichten werden mit der klassischen RELU-Aktivierungsfunktion aktiviert. In der letzten Ebene möchten wir jedoch Zahlen zwischen 0 und 1 berechnen, die die Wahrscheinlichkeit darstellen, dass diese Blume eine Rose, eine Tulpe usw. ist. Dazu verwenden wir eine Aktivierungsfunktion namens „Softmax“.

Um die Softmax-Funktion auf einen Vektor anzuwenden, wird die Exponentialfunktion auf jedes Element angewendet und der Vektor dann normalisiert. Normalerweise wird dabei die L1-Norm (Summe der Absolutwerte) verwendet, damit sich die Werte auf 1 summieren und als Wahrscheinlichkeiten interpretiert werden können.

ef0d98c0952c262d.png d51252f75894479e.gif

Kreuzentropie-Verlust

Nachdem nun unser neuronales Netzwerk Vorhersagen aus Eingabebildern produziert, müssen wir messen, wie gut sie sind, d.h. den Abstand zwischen dem, was uns das Netzwerk mitteilt, und den richtigen Antworten, die oft als „Labels“ bezeichnet werden. Denken Sie daran, dass wir für alle Bilder im Datensatz korrekte Labels haben.

Jede Distanz würde funktionieren, aber für Klassifizierungsprobleme ist die sogenannte „Kreuzentropie-Distanz“ am effektivsten. Wir nennen dies unsere Fehler- oder „Verlust“-Funktion:

7bdf8753d20617fb.png

Gradientenabstieg

Das „Training“ des neuronalen Netzes bedeutet, mithilfe von Trainingsbildern und Labels Gewichte und Voreingenommenheiten so anzupassen, dass die Kreuzentropie-Verlustfunktion minimiert wird. Und so funktioniert es:

Die Kreuzentropie ist eine Funktion von Gewichtungen, Verzerrungen, Pixeln des Trainingsbilds und seiner bekannten Klasse.

Wenn wir die partiellen Ableitungen der Kreuzentropie relativ zu allen Gewichten und Voreingenommenheiten berechnen, erhalten wir einen „Gradienten“, der für ein bestimmtes Bild, Label und den aktuellen Wert der Gewichte und Voreingenommenheiten berechnet wird. Denken Sie daran, dass wir Millionen von Gewichten und Voreingenommenheiten haben können, sodass die Berechnung des Gradienten viel Arbeit bedeutet. Glücklicherweise erledigt Tensorflow das für uns. Die mathematische Eigenschaft eines Farbverlaufs ist, dass er „nach oben“ zeigt. Da wir dorthin gehen möchten, wo die Kreuzentropie niedrig ist, gehen wir in die entgegengesetzte Richtung. Wir aktualisieren die Gewichte und Voreingenommenheiten um einen Bruchteil des Gradienten. Dann wiederholen wir den Vorgang in einem Trainings-Loop immer wieder mit den nächsten Batches von Trainingsbildern und Labels. Hoffentlich konvergiert dies zu einem Punkt, an dem die Kreuzentropie minimal ist, obwohl es keine Garantie dafür gibt, dass dieses Minimum eindeutig ist.

Gradientenabstieg2.png

Mini-Batching und Momentum

Sie können Ihren Gradienten nur für ein Beispielbild berechnen und die Gewichtungen und Gewichtungen sofort aktualisieren. Bei einem Batch von beispielsweise 128 Bildern ergibt sich jedoch ein Farbverlauf, der die Einschränkungen durch verschiedene Beispielbilder besser darstellt und daher wahrscheinlich schneller der Lösung näherkommt. Die Größe des Mini-Batches ist ein anpassbarer Parameter.

Diese Methode, die manchmal als „stochastischer Gradientenabstieg“ bezeichnet wird, hat einen weiteren, pragmatischeren Vorteil: Die Arbeit mit Batches bedeutet auch, mit größeren Matrizen zu arbeiten, und diese lassen sich in der Regel für GPUs und TPUs einfacher optimieren.

Die Konvergenz kann jedoch immer noch etwas chaotisch sein und sogar aufhören, wenn der Gradientenvektor nur Nullen enthält. Heißt das, dass wir einen Mindestwert gefunden haben? Nimmt immer. Eine Farbverlaufskomponente kann bei einem Minimum oder Maximum null sein. Bei einem Gradientenvektor mit Millionen von Elementen ist die Wahrscheinlichkeit, dass jede Null einem Minimum und keines von ihnen einem Höchstpunkt entspricht, ziemlich gering, wenn alle Nullen sind. In einem Raum mit vielen Dimensionen kommen Sattelpunkte häufig vor, sodass wir nicht bei ihnen anhalten möchten.

52e824fe4716c4a0.png

Illustration: ein Sattelpunkt. Der Farbverlauf ist 0, aber kein Mindestwert in alle Richtungen. (Bildzuordnung Wikimedia: By Nicoguaro – Own work, CC BY 3.0)

Die Lösung besteht darin, dem Optimierungsalgorithmus etwas Schwung zu verleihen, damit er die Sattelpunkte überwinden kann, ohne anzuhalten.

Glossar

Batch oder Mini-Batch: Das Training wird immer mit Batches von Trainingsdaten und Labels durchgeführt. Dies trägt dazu bei, dass der Algorithmus konvergiert. Die Dimension „Batch“ ist in der Regel die erste Dimension von Datentensoren. Ein Tensor mit der Form [100, 192, 192, 3] enthält beispielsweise 100 Bilder mit 192 x 192 Pixeln mit drei Werten pro Pixel (RGB).

Kreuzentropie-Verlust: Eine spezielle Verlustfunktion, die häufig in Klassifikatoren verwendet wird.

dichte Schicht: Eine Schicht aus Neuronen, bei der jedes Neuron mit allen Neuronen aus der vorherigen Schicht verbunden ist.

Features: Die Eingaben eines neuronalen Netzes werden manchmal als „Features“ bezeichnet. Die Kunst, herauszufinden, welche Teile eines Datensatzes (oder Kombinationen von Teilen) in ein neuronales Netzwerk eingespeist werden müssen, um gute Vorhersagen zu erhalten, wird als „Feature Engineering“ bezeichnet.

labels: ein anderer Name für "Kurse" oder korrekte Antworten bei einem Klassifizierungsproblem mit Elternaufsicht

Lernrate: Anteil des Gradienten, um den Gewichtungen und Verzerrungen bei jeder Iteration der Trainingsschleife aktualisiert werden.

Logits: Die Ausgaben einer Neuronenschicht vor Anwendung der Aktivierungsfunktion werden als „Logits“ bezeichnet. Der Begriff stammt von der „logistischen Funktion“, auch bekannt als „Sigmoidfunktion“, die früher die am häufigsten verwendete Aktivierungsfunktion war. „Neuronausgaben vor logistischer Funktion“ wurde in „logits“ abgekürzt.

loss: Die Fehlerfunktion, die die Ausgaben des neuronalen Netzes mit den richtigen Antworten vergleicht

Neuron: Er berechnet die gewichtete Summe seiner Eingaben, fügt einen Bias hinzu und leitet das Ergebnis durch eine Aktivierungsfunktion.

One-Hot-Codierung: Die Klasse 3 von 5 wird als Vektor mit 5 Elementen codiert, wobei alle Elemente null sind, mit Ausnahme des 3. Elements, das 1 ist.

relu: Rectified Linear Unit. Eine beliebte Aktivierungsfunktion für Neuronen.

Sigmoid: Eine weitere Aktivierungsfunktion, die früher beliebt war und in bestimmten Fällen immer noch nützlich ist.

Softmax-Parameter: eine spezielle Aktivierungsfunktion, die auf einen Vektor wirkt, die Differenz zwischen der größten und allen anderen Komponenten erhöht und außerdem den Vektor auf die Summe 1 normalisiert, sodass er als Vektor von Wahrscheinlichkeiten interpretiert werden kann. Wird als letzter Schritt in Klassifikatoren verwendet.

tensor: Ein "Tensor" ist wie eine Matrix, aber mit einer beliebigen Anzahl von Dimensionen. Ein eindimensionaler Tensor ist ein Vektor. Ein zweidimensionaler Tensor ist eine Matrix. Dann können Sie Tensoren mit 3, 4, 5 oder mehr Dimensionen haben.

5. [NEU] Convolutional Neural Networks

Kurz und bündig

Wenn Ihnen alle im nächsten Absatz fett formatierten Begriffe bereits bekannt sind, können Sie mit der nächsten Übung fortfahren. Wenn Sie gerade erst mit Convolutional Neural Networks (CNNs) beginnen, lesen Sie weiter.

convolutional.gif

Abbildung: Ein Bild wird mit zwei aufeinanderfolgenden Filtern mit jeweils 4 × 4 × 3 = 48 lernbaren Gewichten gefiltert.

So sieht ein einfaches Convolutional Neural Network in Keras aus:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

Convolutional Neural Networks (CNN) – Einführung

In einer Schicht eines Convolutional Network macht ein „Neuron“ eine gewichtete Summe der Pixel direkt darüber, nur über einen kleinen Bereich des Bildes hinweg. Es fügt einen Bias hinzu und leitet die Summe durch eine Aktivierungsfunktion, genau wie ein Neuron in einer regulären dichten Schicht. Dieser Vorgang wird dann mit denselben Gewichten für das gesamte Bild wiederholt. Denken Sie daran, dass in dichten Schichten jedes Neuron eine eigene Gewichtung hatte. Hier gleitet ein einzelner „Patch“ von Gewichten in beide Richtungen über das Bild (eine „Konvolution“). Die Ausgabe enthält so viele Werte wie Pixel im Bild vorhanden sind. An den Rändern ist jedoch etwas Abstand erforderlich. Es ist ein Filtervorgang mit einem Filter mit 4 × 4 × 3 = 48 Gewichten.

48 Gewichte reichen jedoch nicht aus. Um mehr Freiheitsgrade zu erhalten, wiederholen wir denselben Vorgang mit einer neuen Gewichtsmenge. Dies erzeugt einen neuen Satz von Filterausgaben. Nennen wir ihn in Analogie zu den R,G,B-Kanälen im Eingabebild einen „Kanal“ der Ausgabe.

Screen Shot 2016-07-29 at 16.02.37.png

Die zwei (oder mehr) Gewichtungssätze können durch Hinzufügen einer neuen Dimension zu einem Tensor addiert werden. Dies ergibt die generische Form des Gewichtstensors für eine Convolutional-Schicht. Da die Anzahl der Eingabe- und Ausgabekanäle Parameter sind, können wir mit dem Stapeln und Verketten von Faltungsschichten beginnen.

d1b557707bcd1cb9.png

Illustration: Ein Convolutional Neural Network wandelt „Kubs“ von Daten in andere „Würfel“ um.

Schrittweise Faltungen, max. Pooling

Wenn wir die Faltungen mit einer Schrittzahl von 2 oder 3 ausführen, können wir den resultierenden Datenwürfel auch in seiner horizontalen Dimension verkleinern. Hierfür gibt es zwei gängige Methoden:

  • Gestrichelte Faltung: ein gleitender Filter wie oben, aber mit einer Schrittlänge > 1
  • Max. Pooling: ein gleitendes Fenster, in dem der MAX-Vorgang angewendet wird (in der Regel auf 2 x 2 Patches, wiederholt alle 2 Pixel)

2b2d4263bb8470b.gif

Illustration: Das Verschieben des Rechenfensters um 3 Pixel führt zu weniger Ausgabewerten. Gestrichelte Faltungen oder Max-Pooling (Maximum auf einem 2 x 2-Fenster, das in einem Schritt von 2 verschoben wird) sind eine Möglichkeit, den Datenwürfel in horizontalen Dimensionen zu verkleinern.

Konvolutionärer Klassifikator

Schließlich fügen wir einen Klassifizierungs-Kopf hinzu, indem wir den letzten Datenwürfel flachlegen und durch eine dichte, Softmax-aktivierte Schicht leiten. Ein typischer Convolutional Klassifikator kann beispielsweise so aussehen:

4a61aaffb6cba3d1.png

Abbildung: Ein Bildklassifikator mit Convolutional- und Softmax-Ebenen. Es werden 3x3- und 1x1-Filter verwendet. Die MaxPool-Ebenen berechnen das Maximum von Gruppen mit 2 × 2 Datenpunkten. Der Klassifizierungs-Head wird mit einer dichten Schicht mit Softmax-Aktivierung implementiert.

In Keras

Der oben dargestellte Convolutional-Stack kann in Keras so geschrieben werden:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. Ihre benutzerdefinierte ConvNet

Praktische Übung

Lassen Sie uns ein Convolutional Neural Network von Grund auf neu erstellen und trainieren. Mit einer TPU können wir sehr schnell iterieren. Öffnen Sie das folgende Notebook, führen Sie die Zellen aus (Umschalttaste + Eingabetaste) und folgen Sie der Anleitung, wenn Sie das Label „ERFORDERLICHE ARBEIT“ sehen.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Ziel ist es, die Genauigkeit von 75% des Lerntransfermodells zu übertreffen. Dieses Modell hatte einen Vorteil, da es mit einem Dataset mit Millionen von Bildern vortrainiert wurde, während wir hier nur 3.670 Bilder haben. Kannst du es zumindest abgleichen?

Weitere Informationen

Wie viele Schichten, wie groß?

Die Auswahl der Ebenengröße ist eher eine Kunst als eine Wissenschaft. Sie müssen das richtige Gleichgewicht zwischen zu wenigen und zu vielen Parametern (Gewichtung und Verzerrungen) finden. Mit zu wenig Gewichten kann das neuronale Netzwerk nicht die Komplexität von Blumenformen darstellen. Bei zu vielen Bildern kann dies anfällig für „Überanpassung“ sein, d.h., Sie spezialisieren sich auf die Trainingsbilder und können nicht verallgemeinern. Mit vielen Parametern wird das Modell auch nur langsam trainiert. In Keras zeigt die Funktion model.summary() die Struktur und die Anzahl der Parameter Ihres Modells an:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

Hier einige Tipps:

  • Mehrere Schichten machen „tiefe“ neuronale Netzwerke effektiv. Für dieses einfache Problem der Blumenerkennung sind 5 bis 10 Schichten sinnvoll.
  • Verwenden Sie kleine Filter. 3 × 3-Filter eignen sich in der Regel überall.
  • Auch 1:1-Filter können verwendet werden und sind kostengünstig. Sie „filtern“ nicht wirklich, sondern berechnen lineare Kombinationen von Kanälen. Sie können sie mit echten Filtern abwechseln. Weitere Informationen zu „1x1-Faltungen“ finden Sie im nächsten Abschnitt.
  • Bei einem solchen Klassifizierungsproblem sollten Sie häufig mit Max-Pooling-Ebenen (oder Convolutionen mit einem Schritt von mehr als 1) herunterskalieren. Es ist Ihnen egal, wo die Blume ist, nur, dass es sich um eine Rose oder einen Löwenzahn handelt. Der Verlust von X- und Y-Informationen ist also nicht wichtig und das Filtern kleinerer Bereiche ist günstiger.
  • Die Anzahl der Filter entspricht in der Regel der Anzahl der Klassen am Ende des Netzwerks. Warum? Sehen Sie sich den Trick zum globalen Durchschnitts-Pooling unten an. Wenn Sie in Hunderte von Klassen klassifizieren, erhöhen Sie die Anzahl der Filter schrittweise in aufeinanderfolgenden Ebenen. Für das Blumen-Dataset mit 5 Klassen reicht eine Filterung mit nur 5 Filtern nicht aus. Sie können in den meisten Ebenen dieselbe Filteranzahl verwenden, z. B. 32, und sie gegen Ende verringern.
  • Die letzten Dense-Ebenen sind teuer. Sie können mehr Gewichte haben als alle Convolutional-Ebenen zusammen. Selbst bei einer sehr angemessenen Ausgabe aus dem letzten Datenwürfel mit 24 × 24 × 10 Datenpunkten würde eine dichte Neuronenschicht aus 100 Neuronen 24 × 24 × 10 × 100=576.000 Gewichtungen kosten. Gehen Sie dabei umsichtig vor oder verwenden Sie globales Durchschnitts-Pooling (siehe unten).

Globales durchschnittliches Pooling

Anstatt am Ende eines Convolutional Neural Networks eine teure dichte Schicht zu verwenden, können Sie den eingehenden Datenwürfel in so viele Teile wie Klassen aufteilen, ihre Werte mitteln und diese durch eine Softmax-Aktivierungsfunktion leiten. Bei dieser Methode für den Klassifizierungsknoten werden keine Gewichte benötigt. In Keras lautet die Syntax tf.keras.layers.GlobalAveragePooling2D().

93240029f59df7c2.png

Lösung

Hier ist das Lösungs-Notebook. Sie können sie verwenden, wenn Sie nicht weiterkommen.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

Behandelte Themen

  • 🤔 Mit Convolutional-Layers experimentiert
  • 🤓 Experimente mit max. Pooling, Schritten, globalem Durchschnitts-Pooling...
  • 😀 schnelle Iteration eines realen Modells auf einer TPU

Bitte nehmen Sie sich einen Moment Zeit, um diese Checkliste durchzugehen.

7. Glückwunsch!

Sie haben Ihr erstes modernes Convolutional Neural Network erstellt und es mit einer Genauigkeit von über 80% trainiert. Dank TPUs kann die Architektur in nur wenigen Minuten iteriert werden. Im nächsten Lab erfahren Sie mehr über moderne Convolutional-Architekturen:

TPUs in der Praxis

TPUs und GPUs sind auf der Cloud AI Platform verfügbar:

Zu guter Letzt freuen wir uns über Feedback. Bitte teilen Sie uns mit, wenn Sie in diesem Lab etwas Ungewöhnliches bemerken oder der Meinung sind, dass es verbessert werden sollte. Sie können Feedback über GitHub-Probleme [ feedback link] geben.

HR.png

Martin Görner ID, klein.jpg
Der Autor: Martin Görner
Twitter: @martin_gorner

tensorflow logo.jpg
www.tensorflow.org