Titelbild Erklärbarkeit von Deep Learning Modellen mit GRad-CAM

Car Model Classification III: Erklärbarkeit von Deep Learning Modellen mit Grad-CAM

Stephan Müller Blog, Data Science

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

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

Inhalt

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

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

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

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

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

Activations Visualization

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

Activations Beispielbild

Vanilla Gradients

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

Vanilla Gradients Beispielbild

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

Occlusion Sensitivity

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

Occlusion Sensitivity Beispielbild

CNN Fixations

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

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

CNN Fixations Beispielbild

CAM

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

CAM Beispielbild

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

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

Grad-CAM

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

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

INPUT_SHAPE = (224, 224, 3)

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

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

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

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

# Output of conv layer
output = conv_outputs[0]

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

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

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

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

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

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

Detailbetrachtung des Codes

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

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

Beispiele für den Auto-Modell-Classifier

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

Grad-CAM für Fahrzeugaufnahmen von der Vorderseite
Grad-CAM für Fahrzeugaufnahmen von der Vorderseite

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

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

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

Grad-CAM für Fahrzeugaufnahmen von der Seite
Grad-CAM für Fahrzeugaufnahmen von der Seite

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

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

Fazit

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

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

Über den Autor

Stephan Müller

I am a data scientist at STATWORX and I am fascinated by the mathematical machinery which Machine Learning algorithms rely on. My life outside work revolves around sports, in particular field hockey, swimming and running.

ABOUT US


STATWORX
is a consulting company for data science, statistics, machine learning and artificial intelligence located in Frankfurt, Zurich and Vienna. Sign up for our NEWSLETTER and receive reads and treats from the world of data science and AI. If you have questions or suggestions, please write us an e-mail addressed to blog(at)statworx.com.