1. Übersicht
In diesem Lab erfahren Sie mehr über moderne Convolutional Neural Networks und implementieren ein einfaches, aber effektives ConvNet namens „SqueezeNet“.
Dieses Lab enthält die notwendigen theoretischen Erläuterungen zu Convolutional Neural Networks und ist ein guter Ausgangspunkt für Entwickler, die sich mit Deep Learning vertraut machen.
Dieses Lab ist Teil 4 der Serie „Keras auf TPU“. Sie können sie in der folgenden Reihenfolge oder einzeln durchführen.
- Datenpipelines mit TPU-Geschwindigkeit: tf.data.Dataset und TFRecords
- Ihr erstes Keras-Modell mit Lerntransfer
- Convolutional Neural Networks, mit Keras und TPUs
- [DIESES LAB] Moderne ConvNets, SqueezeNet, Xception, mit Keras und TPUs
Lerninhalte
- Keras-Funktionsstil beherrschen
- Modell mit der SqueezeNet-Architektur erstellen
- TPUs verwenden, um schnell zu trainieren und die Architektur zu iterieren
- Zum Implementieren der Datenerweiterung mit tf.data.dataset
- Vortrainiertes großes Modell (Xception) auf TPU optimieren
Feedback
Wenn Sie in diesem Codelab etwas Ungewöhnliches bemerken, teilen Sie uns dies bitte mit. Sie können Feedback über GitHub-Probleme [ feedback link] geben.
2. Kurzanleitung für Google Colaboratory
In diesem Lab wird Google Collaboratory verwendet und es ist keine Einrichtung erforderlich. Colaboratory ist eine Online-Notebook-Plattform für Bildungszwecke. Sie bietet kostenloses CPU-, GPU- und TPU-Training.
Sie können dieses Beispielnotebook öffnen und einige Zellen durchgehen, um sich mit Colaboratory vertraut zu machen.
TPU-Backend auswählen
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 wird bei der ersten Ausführung automatisch hergestellt. Sie können auch die Schaltfläche „Verbinden“ rechts oben verwenden.
Notebookausführung
Wenn Sie Zellen einzeln ausführen möchten, klicken Sie auf eine Zelle und drücken Sie die Umschalttaste + Eingabetaste. Sie können das gesamte Notebook auch mit Laufzeit > Alle ausführen ausführen.
Inhaltsverzeichnis
Alle Notebooks haben ein Inhaltsverzeichnis. Sie können ihn mit dem schwarzen Pfeil auf der linken Seite öffnen.
Ausgeblendete Zellen
In einigen Zellen wird nur der Titel angezeigt. Dies ist eine Colab-spezifische Notebook-Funktion. Sie können darauf doppelklicken, um den darin enthaltenen Code anzuzeigen, aber normalerweise ist er nicht sehr interessant. In der Regel Support- oder Visualisierungsfunktionen. Sie müssen diese Zellen trotzdem ausführen, damit die darin enthaltenen Funktionen definiert werden.
Authentifizierung
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)?
Zusammenfassung
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=...)
Heute verwenden wir TPUs, um einen Blumenklassifikator in interaktiver Geschwindigkeit (Minuten pro Trainingslauf) zu erstellen und zu optimieren.
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 kombinieren dagegen einen klassischen Vektorprozessor mit einer speziellen Matrixmultiplikationseinheit und eignen sich hervorragend für Aufgaben, bei denen große Matrixmultiplikationen dominieren, z. B. für neuronale Netze.
Abbildung: Eine dichte Schicht eines neuronalen Netzes als Matrixmultiplikation, bei der acht Bilder 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. Convolutional Layers können auch als Matrixmultiplikationen dargestellt werden, was jedoch etwas komplizierter ist ( Erläuterung hier, in Abschnitt 1).
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 in einem Gleitkommaformat mit gemischter Präzision von 16–32 Bit.
Gemischte Precision-/Gleitkommazahlen und bfloat16
Die MXU berechnet Matrixmultiplikationen mit bfloat16-Eingaben und float32-Ausgaben. Zwischensummen werden mit einer Genauigkeit von „float32“ ausgeführt.
Das Training eines neuronalen Netzwerks ist in der Regel gegen Rauschen resistent, die durch eine reduzierte Gleitkommagenauigkeit entstehen. In einigen Fällen kann Rauschen sogar dazu beitragen, dass der Optimierer konvergiert. Die 16‑Bit-Gleitkommapräzision wurde traditionell verwendet, um Berechnungen zu beschleunigen. Die Formate „float16“ und „float32“ haben jedoch sehr unterschiedliche Bereiche. Wenn Sie die Genauigkeit von „float32“ auf „float16“ reduzieren, kommt es in der Regel zu Über- und Unterlauf. Es gibt Lösungen, aber in der Regel ist zusätzliche Arbeit erforderlich, damit float16 funktioniert.
Aus diesem Grund hat Google das bfloat16-Format in TPUs eingeführt. bfloat16 ist eine abgeschnittene Gleitkommazahl (FLOAT32) mit genau denselben Exponentenbits und demselben Exponentenbereich 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 mit einer sogenannten systolischen Arrayarchitektur, bei der Datenelemente durch eine Reihe von Hardwarerecheneinheiten fließen. (In der Medizin bezieht sich „systolisch“ auf Herzkontraktionen und Blutfluss, hier auf den Datenfluss.)
Das grundlegende Element einer Matrixmultiplikation ist ein Skalarprodukt zwischen einer Zeile aus einer Matrix und einer Spalte aus der anderen Matrix (siehe Abbildung oben in diesem Abschnitt). Für eine Matrixmultiplikation Y=X*W wäre ein Element des Ergebnisses:
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 diese Punktprodukt in einen GPU-Kern programmieren und dann parallel auf so vielen Kernen wie verfügbar ausführen, um alle Werte der resultierenden Matrix gleichzeitig 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. Sie sind so klein, dass eine TPU 16.000 davon in einer 128 x 128 MXU implementieren und diese Matrixmultiplikation in einem Schritt verarbeiten kann.
Abbildung: Das systolische MXU-Array. Die Rechenelemente sind Multiplikatoren. 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 als Übung überlassen, um zu prüfen, ob Sie das Ergebnis der Matrixmultiplikation auf der rechten Seite erhalten, während die Daten durch das Array fließen.
Außerdem werden die Zwischensummen während der Berechnung der Punktprodukte in einer MXU einfach zwischen benachbarten Recheneinheiten übertragen. 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 „Cloud TPU v2“ auf der Google Cloud Platform anfordern, erhalten Sie eine virtuelle Maschine (VM) mit einer mit PCI verbundenen TPU-Platine. 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 Multiplikation Unit). Diese „Cloud TPU“ wird dann in der Regel über das Netzwerk mit der VM verbunden, die sie angefordert hat. Das vollständige Bild sieht also so aus:
Abbildung: VM mit einem mit dem Netzwerk verbundenen „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 einem Hochleistungs-Computing-Interconnect (HPC) verbunden, wodurch sie als ein sehr großer Beschleuniger erscheinen können. Google nennt sie Pods und sie können bis zu 512 TPU v2-Kerne oder 2048 TPU v3-Kerne umfassen.
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.
Abbildung: Synchronisierung von Gradienten während des Trainings mit dem Allreduce-Algorithmus im 2D-Toroidal-Mesh-HPC-Netzwerk von Google TPU.
Die Software
Training mit großer Batchgröße
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.
Weitere Tipps zur Leistung finden Sie im Leitfaden zur TPU-Leistung. Bei sehr großen Batchgrößen sind bei einigen Modellen besondere Sorgfalt erforderlich. Weitere Informationen finden Sie unter LARSOptimizer.
Funktionsweise: XLA
In TensorFlow-Programmen werden Berechnungsgraphen definiert. Die TPU führt nicht direkt Python-Code aus, sondern den Berechnungsgraphen, der von Ihrem TensorFlow-Programm definiert wurde. 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, wenn die Arbeit an die TPU gesendet wird. Sie müssen XLA nicht explizit in Ihre Build-Kette aufnehmen.
Veranschaulichung: Damit der vom TensorFlow-Programm definierte Berechnungsgraph auf einer TPU ausgeführt werden kann, wird er zuerst in eine XLA-Darstellung (Accelerated Linear Algebra Compiler) übersetzt und dann von XLA in TPU-Maschinencode kompiliert.
TPUs in Keras verwenden
TPUs werden ab Tensorflow 2.1 durch die Keras API unterstützt. Keras-Unterstützung funktioniert auf TPUs und TPU-Pods. Das folgende Beispiel funktioniert mit TPU, GPU(s) und CPU:
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 SieTPUClusterResolver
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 innerhalb des Strategiebereichs (Scope()) definiert werden.
- 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 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 führt bei der Ausführung oft zum Engpass. Im TPU-Leistungsleitfaden finden Sie Tools zur Erkennung von Datenengpässen und weitere Leistungstipps.
- int8- oder int16-Zahlen werden als int32 behandelt. Die TPU hat keine Ganzzahl-Hardware, 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 werden.
tf.py_func
wird auf TPUs nicht unterstützt.
4. [INFO] Einführung in neuronale Klassifikatoren
Zusammenfassung
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 dem Thema "Deep Learning" beginnen, ist dies willkommen. Bitte 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, ... )
Kompaktes neuronales Netzwerk
Dies ist das einfachste neuronale Netzwerk zum Klassifizieren 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.
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, Aktivierung, 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.
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 fünf Neuronen, da wir Blumen in fünf Kategorien einteilen (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 die Aktivierungsfunktion „Softmax“.
Die Anwendung von Softmax auf einen Vektor erfolgt, indem die Exponentialfunktion jedes Elements ermittelt und dann der Vektor normalisiert wird. Normalerweise wird die L1-Norm (Summe der absoluten Werte) verwendet, sodass die Werte addiert 1 ergeben und als Wahrscheinlichkeiten interpretiert werden können.
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 die korrekten Labels für alle Bilder im Dataset 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:
Gradientenabstieg
Das „Training“ des neuronalen Netzes bedeutet, mithilfe von Trainingsbildern und Labels Gewichte und Voreingenommenheiten so anzupassen, dass die Kreuzentropie-Verlustfunktion minimiert wird. So funktionierts:
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 Gewichtungen und allen Verzerrungen berechnen, erhalten wir einen "Gradienten", der für ein bestimmtes Bild, Label und den Gegenwartswert von Gewichtungen und Verzerrungen berechnet wird. Denken Sie daran, dass wir Millionen von Gewichtungen und Verzerrungen haben können, sodass die Berechnung des Farbverlaufs wie eine Menge Arbeit klingt. Glücklicherweise erledigt Tensorflow das für uns. Die mathematische Eigenschaft eines Farbverlaufs besteht darin, 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 das und verwenden die nächsten Batches von Trainingsbildern und ‐labels in einer Trainingsschleife. Hoffentlich nähert sich dies einem Punkt an, an dem die Kreuzentropie minimal ist, obwohl nichts garantiert, dass dieses Minimum einzigartig ist.
Mini-Batching und Impuls
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 noch einen weiteren, pragmatischeren Vorteil: Die Arbeit mit Batches bedeutet auch die Arbeit mit größeren Matrizen, die sich in der Regel leichter auf GPUs und TPUs optimieren lassen.
Die Konvergenz kann jedoch etwas chaotisch sein und sogar zum Stillstand kommen, wenn der Gradientenvektor nur aus Nullen besteht. Bedeutet das, dass wir ein Minimum gefunden haben? Nimmt immer. Eine Farbverlaufskomponente kann bei einem Mindest- oder Höchstwert null sein. Bei einem Gradientenvektor mit Millionen von Elementen, die alle Nullen sind, ist die Wahrscheinlichkeit, dass jede Null einem Minimum und keine einem Maximum entspricht, ziemlich gering. In einem Raum mit vielen Dimensionen kommen Sattelpunkte häufig vor, sodass wir nicht bei ihnen anhalten möchten.
Abbildung: Sattelpunkt. Die Steigung ist 0, aber es ist nicht in allen Richtungen ein Minimum. (Bildnachweis Wikimedia: Von Nicoguaro – Eigenes Werk, 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. Beispiel: Ein Tensor der Form [100, 192, 192, 3] enthält 100 Bilder mit 192 × 192 Pixeln mit drei Werten pro Pixel (RGB).
Kreuzentropie-Verlust: Eine spezielle Verlustfunktion, die häufig in Klassifikatoren verwendet wird.
Ganze Schicht: Eine Schicht von Neuronen, in der jedes Neuron mit allen Neuronen der vorherigen Schicht verbunden ist.
Features: Die Eingaben eines neuronalen Netzes werden manchmal als „Features“ bezeichnet. Die Kunst, herauszufinden, welche Teile eines Datasets (oder Kombinationen von Teilen) in ein neuronales Netzwerk eingespeist werden sollen, um gute Vorhersagen zu erhalten, wird als „Feature Engineering“ bezeichnet.
Labels: Ein anderer Name für „Klassen“ oder richtige Antworten bei einem Klassifizierungsproblem mit beaufsichtigtem Lernen
Lernrate: Bruchteil des Gradienten, mit dem Gewichte und Voreingenommenheiten 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. „Neuron-Ausgaben vor der logistischen Funktion“ wurde zu „Logits“ verkürzt.
loss: die Fehlerfunktion, die die Ausgaben neuronaler Netzwerke mit den richtigen Antworten vergleicht
neuron: berechnet die gewichtete Summe der Eingaben, fügt eine Verzerrung hinzu und speist das Ergebnis über eine Aktivierungsfunktion ein.
One-Hot-Codierung: Klasse 3 von 5 wird als Vektor aus fünf Elementen codiert, alle Nullen mit Ausnahme des dritten, also 1.
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: Eine spezielle Aktivierungsfunktion, die auf einen Vektor wirkt, den Unterschied zwischen der größten Komponente und allen anderen erhöht und den Vektor so normalisiert, dass er eine Summe von 1 hat, sodass er als Vektor von Wahrscheinlichkeiten interpretiert werden kann. Wird als letzter Schritt in Klassifikatoren verwendet.
Tensor: Ein Tensor ist wie eine Matrix, hat aber eine beliebige 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. [INFO] Convolutional Neural Networks
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 Convolutional Neural Networks anfangen, lesen Sie bitte weiter.
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'])
Convolutional Neural Networks (CNN) – Einführung
In einer Schicht eines Convolutional-Netzwerks führt ein „Neuron“ eine gewichtete Summe der Pixel aus, die sich direkt darüber befinden, und zwar nur über einen kleinen Bereich des Bildes. 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 für das gesamte Bild mit denselben Gewichtungen wiederholt. Denken Sie daran, dass in dichten Schichten jedes Neuron seine eigenen Gewichte hatte. Hier gleitet ein einzelner „Patch“ von Gewichten in beide Richtungen über das Bild (eine „Konvolution“). Die Ausgabe hat so viele Werte, wie Pixel im Bild enthalten sind. An den Rändern ist jedoch ein gewisser Abstand erforderlich. Es handelt sich um einen Filtervorgang, bei dem ein Filter mit einer Gewichtung von 4x4x3=48 verwendet wird.
48 Gewichtungen reichen jedoch nicht aus. Um weitere Freiheitsgrade hinzuzufügen, wiederholen wir denselben Vorgang mit einem neuen Satz von Gewichtungen. 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.
Die beiden (oder mehr) Gewichtssätze können durch Hinzufügen einer neuen Dimension als ein Tensor zusammengefasst 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 Convolutional-Layers stapeln und verketten.
Abbildung: Ein Convolutional Neural Network wandelt Datenwürfel in andere Datenwürfel um.
Stufeweise 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 Schiebefenster, auf das der MAX-Vorgang angewendet wird (in der Regel auf 2 × 2 Patches, alle 2 Pixel wiederholt)
Illustration: Das Verschieben des Rechenfensters um 3 Pixel führt zu weniger Ausgabewerten. Mit schrittweisen Convolutionen oder Max-Pooling (Max-Wert in einem 2 × 2 Fenster, das um einen Schritt von 2 verschoben wird) lässt sich der Datenwürfel in den horizontalen Dimensionen verkleinern.
Convolutional Classifier
Schließlich fügen wir einen Klassifizierungskopf an, indem wir den letzten Datenwürfel vereinfachen und durch eine dichte, Softmax-aktivierte Ebene speisen. Ein typischer Convolutional Klassifikator kann beispielsweise so aussehen:
Abbildung: Ein Bildklassifikator mit Convolutional- und Softmax-Ebenen. Es werden 3 × 3- und 1 × 1-Filter verwendet. Die MaxPool-Ebenen berechnen das Maximum von Gruppen mit 2 × 2 Datenpunkten. Der Klassifizierungskopf ist mit einer dichten Schicht mit Softmax-Aktivierung implementiert.
In Keras
Der oben dargestellte Convolutional Stack kann in Keras wie folgt 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. [NEW INFO] Moderne Convolutional-Architekturen
Kurz und bündig
Illustration: Ein Faltungsmodul. Was ist in diesem Fall am besten? Eine Max-Pool-Ebene gefolgt von einer 1x1-Faltungsschicht oder einer anderen Kombination von Ebenen? Probieren Sie sie alle aus, verknüpfen Sie die Ergebnisse und lassen Sie das Netzwerk entscheiden. Rechts: die Convolutional-Architektur „inception“ mit solchen Modulen.
Wenn Sie in Keras Modelle erstellen möchten, bei denen der Datenfluss verzweigt werden kann, müssen Sie den Modellstil „funktional“ verwenden. Hier ein Beispiel:
l = tf.keras.layers # syntax shortcut
y = l.Conv2D(filters=32, kernel_size=3, padding='same',
activation='relu', input_shape=[192, 192, 3])(x) # x=input image
# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation
# many more layers ...
# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)
Weitere günstige Tricks
Kleine 3x3-Filter
In dieser Abbildung sehen Sie das Ergebnis von zwei aufeinanderfolgenden 3 × 3-Filtern. Versuchen Sie, nachzuvollziehen, welche Datenpunkte zum Ergebnis beigetragen haben: Diese beiden aufeinanderfolgenden 3 × 3-Filter berechnen eine Kombination aus einer 5 × 5-Region. Dies ist nicht genau dieselbe Kombination, die ein 5x5-Filter berechnen würde, aber es lohnt sich, es auszuprobieren, da zwei aufeinanderfolgende 3x3-Filter günstiger sind als ein einzelner 5x5-Filter.
1x1-Faltungen?
Mathematisch gesehen ist eine „1 × 1“-Konvolution eine Multiplikation mit einer Konstante, was nicht sehr nützlich ist. Denken Sie bei Convolutional Neural Networks jedoch daran, dass der Filter auf einen Datenwürfel und nicht nur auf ein 2D-Bild angewendet wird. Ein „1x1“-Filter berechnet daher eine gewichtete Summe einer 1x1-Datenspalte (siehe Abbildung). Wenn Sie den Filter über die Daten bewegen, erhalten Sie eine lineare Kombination der Kanäle der Eingabe. Das ist wirklich nützlich. Stellen Sie sich die Kanäle als Ergebnisse einzelner Filtervorgänge vor, z. B. einen Filter für „spitze Ohren“, einen für „Schnurrhaare“ und einen dritten für „Schlitzaugen“, dann berechnet eine 1x1-Faltungsschicht mehrere mögliche lineare Kombinationen dieser Merkmale, was bei der Suche nach „Katze“ nützlich sein könnte. Außerdem werden für 1 × 1-Ebenen weniger Gewichte verwendet.
7. Squeezenet
Eine einfache Möglichkeit, diese Ideen zusammenzuführen, wurde im Artikel „Squeezenet“ vorgestellt. Die Autoren schlagen ein sehr einfaches Faltungsmoduldesign vor, das nur 1x1- und 3x3-Faltungsebenen verwendet.
Illustration: Squeezenet-Architektur, die auf „Feuermodulen“ basiert. Sie wechseln abwechselnd eine 1 × 1-Schicht, die die eingehenden Daten in der vertikalen Dimension „drückt“, gefolgt von zwei parallelen 1 × 1- und 3 × 3-Faltungsebenen, die die Tiefe der Daten wieder „erweitern“.
Praktische Übung
Fahren Sie in Ihrem vorherigen Notebook fort und erstellen Sie ein von SqueezeNet inspiriertes Convolutional Neural Network. Sie müssen den Modellcode in den „funktionalen Stil“ von Keras ändern.
Keras_Flowers_TPU (playground).ipynb
Weitere Informationen
Für diese Übung ist es nützlich, eine Hilfsfunktion für ein SqueezeNet-Modul zu definieren:
def fire(x, squeeze, expand):
y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
return tf.keras.layers.concatenate([y1, y3])
# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
return lambda x: fire(x, squeeze, expand)
# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)
Ziel ist es diesmal, eine Genauigkeit von 80 % zu erreichen.
Mögliche Maßnahmen
Beginnen Sie mit einer einzelnen Convolutional-Schicht, gefolgt von „fire_modules
“, abwechselnd mit MaxPooling2D(pool_size=2)
-Schichten. Sie können mit 2 bis 4 Max-Pooling-Schichten im Netzwerk und mit 1, 2 oder 3 aufeinanderfolgenden Fire-Modulen zwischen den Max-Pooling-Schichten experimentieren.
In Auslösermodulen sollte der Parameter „squeeze“ in der Regel kleiner als der Parameter „expand“ sein. Bei diesen Parametern handelt es sich eigentlich um die Anzahl der Filter. Sie können in der Regel zwischen 8 und 196 liegen. Sie können mit Architekturen experimentieren, bei denen die Anzahl der Filter im Netzwerk allmählich zunimmt, oder mit einfachen Architekturen, bei denen alle Feuermodule die gleiche Anzahl von Filtern haben.
Hier ein Beispiel:
x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB
y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, y)
An dieser Stelle stellen Sie vielleicht fest, dass Ihre Tests nicht so gut verlaufen und das Ziel einer Genauigkeit von 80% unwahrscheinlich erscheint. Zeit für ein paar weitere Tricks.
Batchnormalisierung
Die Batch-Norm unterstützt Sie bei den Konvergenzproblemen, die bei Ihnen auftreten. Im nächsten Workshop erhalten Sie detaillierte Erläuterungen zu dieser Technik. Nutzen Sie sie vorerst als Blackbox-Hilfsprogramm, indem Sie diese Zeile nach jeder Convolutional Layer in Ihrem Netzwerk einfügen, einschließlich der Schichten innerhalb Ihrer Fire_module-Funktion:
y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context
Der Momentum-Parameter muss von seinem Standardwert 0,99 auf 0,9 gesenkt werden, da unser Datensatz klein ist. Lassen Sie uns diese Details vorerst außer Acht lassen.
Datenerweiterung
Wenn Sie die Daten mit einfachen Transformationen wie Links-Rechts-Umkehrung oder Sättigungsänderungen ergänzen, können Sie noch ein paar Prozentpunkte mehr herausholen:
In TensorFlow ist das mit der tf.data.Dataset API ganz einfach. Definieren Sie eine neue Transformationsfunktion für Ihre Daten:
def data_augment(image, label):
image = tf.image.random_flip_left_right(image)
image = tf.image.random_saturation(image, lower=0, upper=2)
return image, label
Verwenden Sie sie dann in der endgültigen Datentransformation (Zelle „Trainings- und Validierungs-Datasets“, Funktion „get_batched_dataset“):
dataset = dataset.repeat() # existing line
# insert this
if augment_data:
dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line
Achten Sie darauf, die Datenerweiterung optional zu machen und den erforderlichen Code hinzuzufügen, damit nur der Trainingsdatensatz erweitert wird. Es macht keinen Sinn, den Validierungsdatensatz zu erweitern.
Jetzt sollte eine Genauigkeit von 80% in 35 Epochen erreicht werden.
Lösung
Hier ist das Lösungs-Notebook. Sie können sie verwenden, wenn Sie nicht weiterkommen.
Keras_Flowers_TPU_squeezenet.ipynb
Behandelte Themen
- 🤔 Keras-Modelle im „funktionalen Stil“
- 🤓 Squeezenet-Architektur
- 🤓 Datenerweiterung mit tf.data.datset
Bitte nehmen Sie sich einen Moment Zeit und gehen Sie diese Checkliste durch.
8. Xception optimiert
Teilbare Faltungen
In letzter Zeit hat eine andere Methode zur Implementierung von Convolutional-Layers an Beliebtheit gewonnen: die tiefenseperierbaren Convolutionen. Ich weiß, das ist ein ziemlich langer Begriff, aber das Konzept ist ganz einfach. In TensorFlow und Keras werden sie als tf.keras.layers.SeparableConv2D
implementiert.
Bei einer trennbaren Convolution wird ebenfalls ein Filter auf das Bild angewendet, aber für jeden Kanal des Eingabebilds werden unterschiedliche Gewichte verwendet. Darauf folgt eine 1 x 1-Faltung, eine Reihe von Punktprodukten, die zu einer gewichteten Summe der gefilterten Kanäle führt. Bei jeder neuen Gewichtung werden so viele gewichtete Neukombinationen der Kanäle wie nötig berechnet.
Abbildung: Trennbare Convolutionen. Phase 1: Faltungen mit einem separaten Filter für jeden Kanal. Phase 2: Lineare Kanalkombinationen Wird mit einem neuen Satz von Gewichtungen wiederholt, bis die gewünschte Anzahl von Ausgabekanälen erreicht ist. Phase 1 kann ebenfalls wiederholt werden, wobei jedes Mal eine neue Gewichtung erfolgt, aber in der Praxis ist dies selten der Fall.
Trennbare Convolutionen werden in den neuesten Architekturen von Convolutional Networks verwendet: MobileNetV2, Xception, EfficientNet. Übrigens haben Sie bisher MobileNetV2 für Lerntransfers verwendet.
Sie sind günstiger als normale Convolutional Neural Networks und in der Praxis genauso effektiv. Hier sehen Sie die Anzahl der Gewichtungen für das obige Beispiel:
Convolutional Layer: 4 x 4 x 3 x 5 = 240
Teilbare Faltungsschicht: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63
Der Leser muss die Anzahl der Multiplikationen berechnen, die erforderlich sind, um die einzelnen Stile der Faltungsebene auf ähnliche Weise anzuwenden. Trennbare Faltungen sind kleiner und rechenintensiver.
Praktische Übung
Führen Sie einen Neustart über das Playground-Notebook „Lerntransfer“ durch, wählen Sie dieses Mal aber Xception als vortrainiertes Modell aus. Xception verwendet nur separierbare Convolutionen. Lass alle Gewichte trainierbar. Wir werden die vortrainierten Gewichte anhand unserer Daten optimieren, anstatt die vortrainierten Schichten direkt zu verwenden.
Keras Flowers transfer learning (playground).ipynb
Ziel: Genauigkeit > 95% (Nein, wirklich, es ist möglich!)
Da dies die letzte Übung ist, erfordert sie etwas mehr Code und Data-Science-Arbeit.
Weitere Informationen zur Feinabstimmung
Xception ist in den standardmäßigen vortrainierten Modellen in tf.keras.application verfügbar.* Denken Sie daran, alle Gewichte dieses Mal trainierbar zu lassen.
pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
include_top=False)
pretrained_model.trainable = True
Um bei der Feinabstimmung eines Modells gute Ergebnisse zu erzielen, müssen Sie auf die Lernrate achten und einen Lernratenplan mit einer Anlaufzeit verwenden. Ein Beispiel:
Wenn Sie mit einer Standard-Lernrate beginnen, würden die vortrainierten Gewichtungen des Modells gestört werden. Beim Starten werden sie nach und nach beibehalten, bis das Modell Ihre Daten gespeichert hat und sie sinnvoll ändern kann. Nach der Rampenphase können Sie mit einer konstanten oder einer exponentiell abnehmenden Lernrate fortfahren.
In Keras wird die Lernrate über einen Callback angegeben, in dem Sie die richtige Lernrate für jede Epoche berechnen können. Keras übergibt für jede Epoche die richtige Lernrate an den Optimierungstool.
def lr_fn(epoch):
lr = ...
return lr
lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)
model.fit(..., callbacks=[lr_callback])
Lösung
Hier ist das Lösungs-Notebook. Sie können sie verwenden, wenn Sie nicht weiterkommen.
07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb
Behandelte Themen
- 🤔 Tiefentrennbare Faltung
- 🤓 Lernpläne
- 😈 Ein vortrainiertes Modell optimieren.
Bitte nehmen Sie sich einen Moment Zeit, um diese Checkliste durchzugehen.
9. Glückwunsch!
Sie haben Ihr erstes modernes Convolutional Neural Network erstellt und mit einer Genauigkeit von über 90 % trainiert. Dank TPUs konnten Sie die nachfolgenden Trainings in nur wenigen Minuten iterieren. Damit sind die vier Codelabs „Keras on TPU“ abgeschlossen:
- Datenpipelines mit TPU-Geschwindigkeit: tf.data.Dataset und TFRecords
- Ihr erstes Keras-Modell mit Lerntransfer
- Convolutional Neural Networks, mit Keras und TPUs
- [DIESES LAB] Moderne ConvNets, SqueezeNet, Xception, mit Keras und TPUs
TPUs in der Praxis
TPUs und GPUs sind auf der Cloud AI Platform verfügbar:
- Auf Deep Learning-VMs
- In AI Platform Notebooks
- In AI Platform Training-Jobs
Wir freuen uns über Feedback. Bitte teilen Sie uns mit, wenn Ihnen in diesem Lab etwas fehlt oder Sie der Meinung sind, dass es verbessert werden sollte. Sie können Feedback über GitHub-Probleme [ feedback link] geben.
|