Kapitel 4. Erklärbarkeit für Bilddaten

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Die in den 1980er Jahren eingeführten Convolutional Neural Networks (CNNs) blieben wie die DNNs bis zum Aufkommen der modernen ML unbenutzt und wurden dann schnell zum Rückgrat moderner Lösungen für Computer Vision Probleme. Seitdem haben Deep-Learning-Modelle, die auf CNNs basieren, bei vielen Computer-Vision-Aufgaben - von der Bildklassifizierung und der semantischen Segmentierung bis hin zu Bildunterschriften und der Beantwortung visueller Fragen - einen beispiellosen Durchbruch erzielt und dabei manchmal fast menschliche Leistungen erreicht. Heutzutage werden hochentwickelte Computer-Vision-Modelle eingesetzt, um intelligente Städte zu planen, die Entwicklung von Vieh und Pflanzen zu überwachen, selbstfahrende Autos zu bauen oder Augenkrankheiten und Lungenkrebs zu erkennen.

Da die Zahl dieser intelligenten Systeme, die sich auf Bildmodelle stützen, immer weiter wächst, ist die Rolle der Erklärbarkeit bei der Analyse und dem Verständnis dieser Systeme wichtiger denn je geworden. Wenn diese hochkomplexen Systeme fehlschlagen, geschieht dies leider oft ohne Vorwarnung oder Erklärung und hat manchmal bedauerliche Folgen. Techniken der erklärenden KI (Explainability AI, XAI) sind unerlässlich, um Vertrauen zu schaffen, nicht nur bei den Nutzern dieser Systeme, sondern vor allem bei den Praktikern, die diese Modelle in Betrieb nehmen.

In diesem Kapitel konzentrieren wir uns auf Erklärungsmethoden, mit denen du zuverlässigere und transparentere ML-Lösungen für Computer Vision erstellen kannst. Bildverarbeitungsaufgaben unterscheiden sich von anderen ML-Aufgaben dadurch, dass die Basismerkmale (d. h. Pixel) selten einzeln von Bedeutung sind. Vielmehr kommt es darauf an, wie diese Merkmale auf Pixelebene kombiniert werden, um übergeordnete Merkmale wie Kanten, Texturen oder Muster zu erkennen. Das erfordert besondere Sorgfalt bei der Diskussion und dem Umgang mit Erklärungsmethoden für Computer Vision Aufgaben. Wir werden sehen, wie viele dieser Werkzeuge angepasst wurden, um diese Probleme zu lösen. So wie CNNs für Bilder entwickelt wurden, wurden auch viele der Erklärungsmethoden, die wir in diesem Kapitel behandeln, für Bilder oder sogar CNNs entwickelt.

Grob gesagt können die meisten Erklärungsmethoden für Bildmodelle entweder als Backpropagation-Methoden, Störungsmethoden, Methoden, die den internen Zustand nutzen, oder als eine Kombination dieser Ansätze klassifiziert werden. Die Techniken, die wir in diesem Kapitel besprechen werden, sind repräsentativ für diese Gruppen. Der LIME-Algorithmus verwendet gestörte Eingangsbeispiele, um ein interpretierbares Modell zu approximieren. Wie der Name schon sagt, beruhen Integrated Gradients und XRAI auf Backpropagation, während Guided Backpropagation, Grad-CAM und ihre Verwandten den internen Zustand des Modells nutzen.

Integrierte Gradienten (IG)

Hier erfährst du, was du über integrierte Farbverläufe wissen musst:

  • IG war einer der ersten erfolgreichen Ansätze zur Erklärung von Modellen.

  • IG ist eine lokale Zuordnungsmethode, was bedeutet, dass sie eine Erklärung für die Vorhersage eines Modells für ein einzelnes Beispielbild liefert.

  • Es erzeugt eine leicht zu interpretierende Salienzmaske, die die Pixel oder Regionen im Bild hervorhebt, die am meisten zur Vorhersage des Modells beitragen.

Profis Nachteile
  • IG war einer der ersten erfolgreichen und am häufigsten verwendeten Ansätze zur Modellierung von Erklärbarkeit.
  • IG kann auf jedes differenzierbare Modell für jeden Datentyp angewendet werden: Bilder, Text, Tabellen usw.
  • Die Implementierung ist einfach und intuitiv; selbst Anfänger können sie anwenden. Außerdem gibt es in vielen XAI-Bibliotheken einfach zu verwendende Implementierungen.
  • IG ist besser für kontrastarme Bilder oder Bilder, die in einer nicht natürlichen Umgebung aufgenommen wurden, wie z. B. Röntgenbilder.
  • IG erfordert die Differenzierbarkeit des Modells und den Zugang zu den Gradienten, weshalb es sich nicht gut für baumbasierte Modelle eignet.
  • Die Ergebnisse können von den Hyperparametern oder der Wahl der Basislinie abhängig sein.

Angenommen, du würdest gebeten, das Bild in Abbildung 4-1 zu klassifizieren. Wie würde deine Antwort lauten? Wie würdest du erklären, wie du diese Entscheidung getroffen hast? Wenn du "Vogel" geantwortet hättest, was genau hätte dich darauf gebracht? War es der Schnabel, die Flügel oder der Schwanz? Wenn du "Kakadu" geantwortet hast, war es wegen des Kammes und des weißen Gefieders? Vielleicht hast du auch gesagt, dass es ein "Schwefelhaubenkakadu" ist, weil der Kamm gelb ist.

Abbildung 4-1. Welche Merkmale verraten uns, dass es sich um einen Schwefelhaubenkakadu handelt? Sind es der Schnabel und die Flügel? Das weiße Gefieder? Der gelbe Kamm? Oder alles zusammen?

Unabhängig von deiner Antwort hast du eine Entscheidung aufgrund bestimmter Merkmale des Bildes getroffen, genauer gesagt aufgrund der Anordnung und der Werte bestimmter Pixel und Pixelbereiche im Bild. Vielleicht deuten der Schnabel und die Flügel darauf hin, dass es sich um ein Vogelbild handelt, während der Kamm und die Färbung darauf hindeuten, dass es sich um einen Kakadu handelt. Die Methode der integrierten Farbverläufe ermöglicht es, die Pixel hervorzuheben, die für die Vorhersage eines Modells (in diesem Fall deines eigenen Gehirns) mehr oder weniger relevant sind.

Die Verwendung von Steigungen zur Bestimmung der Zugehörigkeit von Modellmerkmalen ist intuitiv sinnvoll. Erinnere dich daran, dass die Steigung einer Funktion angibt, wie sich die Funktionswerte ändern, wenn die Eingaben leicht verändert werden. Wenn die Ableitung für nur eine Dimension positiv (oder negativ) ist, bedeutet das, dass die Funktion in Bezug auf die Eingabe zunimmt (oder abnimmt). Da der Gradient ein Vektor von Ableitungen ist, sagt er uns für jedes Eingangsmerkmal, ob die Vorhersage der Modellfunktion zunimmt oder abnimmt, wenn du einen kleinen Schritt in eine bestimmte Richtung des Merkmalsraums machst.1 Je mehr die Modellvorhersage von einem Merkmal abhängt, desto höher ist der Zuordnungswert für dieses Merkmal.

Bei linearen Modellen ist diese Beziehung zwischen Gradienten und Attribution sogar noch deutlicher, da das Vorzeichen eines Koeffizienten genau die positive oder negative Beziehung zwischen der Modellausgabe und dem Merkmalswert angibt. Siehe auch die Diskussion und Beispiele unter "Gradient x Input".

Es kann jedoch problematisch sein, sich allein auf Gradienteninformationen zu verlassen. Gradienten geben nur lokale Informationen über das Verhalten der Modellfunktion, aber diese lineare Interpretation ist einschränkend. Wenn das Modell von seine Vorhersage sicher getroffen hat, machen kleine Änderungen der Eingaben keinen großen Unterschied mehr. Wenn dein Modell z. B. ein Bild eines Kakadus hat und robust ist und eine Vorhersage von 0,88 hat, wird sich die Vorhersage für diese Klasse wahrscheinlich nicht mehr ändern, wenn du ein paar Pixel leicht veränderst (selbst wenn es sich um Pixel handelt, die den Kakadu selbst betreffen). Wenn das Modell zum Beispiel vollständig gelernt hat, wie sich der Wert eines bestimmten Pixels auf die vom Modell vorhergesagte Klasse auswirkt, wird der Gradient der Modellvorhersage für dieses Pixel immer kleiner und geht schließlich gegen Null. Der Gradient für die Vorhersage des Modells in Bezug auf diesen Pixel ist gesättigt.

Dieser Begriff der Sättigung der Steigung der Modellvorhersagefunktion in Bezug auf einen Pixelwert sollte nicht mit dem allgemeineren Begriff der Neuronen-Gradientensättigung verwechselt werden, der beim Training neuronaler Netze auftreten kann, auch wenn die beiden ein ähnliches Konzept ansprechen. In neuronalen Netzen bilden Aktivierungsfunktionen wie sigmoid oder tanh die Menge der realen Zahlen in einem Bereich zwischen 0 und 1 ab (oder zwischen -1 und 1 im Fall von tanh). Ein Neuron gilt als gesättigt, wenn extrem große Gewichte dazu führen, dass das Neuron Werte erzeugt, die sehr nahe an der Bereichsgrenze liegen und somit sehr kleine Steigungen haben.

Im Zusammenhang mit der Messung der Merkmalszuordnung über die Gradienten der Modellfunktion ist die Idee der Sättigung in Bezug auf ein Pixel ähnlich, jetzt aber in Bezug auf die Vorhersage des Modells. Sobald das Modell das vorhergesagte Label "gelernt" hat, wird der Gradient der Modellvorhersage in Bezug auf diese Pixelinformation sehr klein. Siehe z. B. Abbildung 4-3, wo die Vorhersage des Modells für die Zielklasse schließlich sehr flach wird.

Um dieses Problem zu lösen, untersucht die Integrated Gradients-Technik die Modellgradienten entlang eines Pfades im Merkmalsraum und summiert die Gradientenbeiträge entlang des Pfades auf. Auf einer hohen Ebene bestimmen Integrated Gradients die wichtigsten Eingaben, indem sie die Netzwerkeingabe schrittweise von einer Basislinie zur ursprünglichen Eingabe verändern und die Gradienten entlang des Pfades zusammenfassen. Wie du eine Basislinie auswählst, besprechen wir im nächsten Abschnitt. Für den Moment musst du nur wissen, dass die ideale Basislinie keine relevanten Informationen für die Vorhersage des Modells enthalten sollte, sodass wir dem Modell auf dem Weg von der Basislinie zum Bild Informationen (d. h. Merkmale) hinzufügen. Je mehr Informationen das Modell erhält, desto sinnvoller ändert sich die Vorhersage. Durch die Anhäufung von Gradienten entlang des Pfades können wir den Gradienten des Modells nutzen, um zu sehen, welche Eingangsmerkmale am meisten zur Vorhersage des Modells beitragen. Wir werden zunächst erörtern, wie man eine geeignete Basislinie auswählt und dann beschreiben, wie man die Gradienten effektiv akkumuliert, um das Problem der gesättigten Gradienten zu vermeiden.

Auswahl einer Baseline

Um objektiv feststellen zu können, welche Pixel für unser vorhergesagtes Label wichtig sind, verwenden wir ein Basisbild als Vergleich. Wie du in Kapitel 2 gesehen hast, gibt es Grundlinien für verschiedene Erklärungsmethoden, und unser Grundlinienbild erfüllt einen ähnlichen Zweck wie die Grundlinie für Shapley-Werte. Auch bei Bildern ist eine gute Basislinie eine, die neutrale oder uninformative Pixelinformationen enthält, und es gibt verschiedene Basislinien, die du verwenden kannst. Bei der Arbeit mit Bildmodellen werden am häufigsten schwarze Bilder, weiße Bilder oder Rauschen verwendet, wie in Abbildung 4-2 dargestellt. Es kann aber auch von Vorteil sein, ein Basisbild zu verwenden, das den Status quo in den Bildern darstellt. Ein Computer-Vision-Modell zur Klassifizierung von Formularen kann zum Beispiel ein Basisbild der Formularvorlage verwenden, oder ein Modell für die Qualitätskontrolle in einer Fabrik kann ein Basisfoto des leeren Fließbands enthalten.

Abbildung 4-2. Häufig verwendete Ausgangsbilder für Bildmodelle sind ein schwarzes Bild, ein weißes Bild und ein Bild mit Gaußschem Rauschen.

Wir beginnen mit einer einfachen Basislinie, die aus einem komplett schwarzen Bild besteht (d. h. ohne Pixelinformationen), und betrachten den geradlinigen Pfad von der Basislinie zum Eingangsbild. Anschließend untersuchen wir die Vorhersageergebnisse des Modells für seine vorhergesagte Klasse, wie in Abbildung 4-3 dargestellt. Eine lineare Interpolation zwischen zwei Punkten x , y ist gegeben durch α y + ( 1 - α ) x wobei die Werte von α von 0 bis 1 reichen.

Abbildung 4-3. An einem bestimmten Punkt auf dem geradlinigen Weg von der Grundlinie zum vollständigen Eingangsbild, etwa wenn α = 0 . 1 wird das Modell sehr sicher in der Vorhersage "Schwefelhaubenkakadu".

Wir können diesen geradlinigen Pfad in Python mit der hier beschriebenen Funktion interpolate_images erreichen (das vollständige Codebeispiel findest du im Notizbuch Integrated Gradients im GitHub-Repository):

def interpolate_images(baseline,
                       image,
                       alphas):
    alphas_x = alphas[:, tf.newaxis, tf.newaxis, tf.newaxis]
    baseline_x = tf.expand_dims(baseline, axis=0)
    input_x = tf.expand_dims(image, axis=0)
    images = alphas_x * input_x + (1 - alphas_x) * baseline_x
    return images

Die Funktion interpolate_images erzeugt eine Reihe von Bildern als die Werte der α variieren, beginnend mit dem Grundlinienbild, wenn α = 0 und endet mit dem vollständigen Eingangsbild, wenn α = 1 wie in Abbildung 4-4 dargestellt.

Abbildung 4-4. Da der Wert von α von 0 bis 1 variiert, erhalten wir eine Reihe von Bildern, die einen geradlinigen Pfad im Bildraum von der Grundlinie zum Eingangsbild bilden.

Als α zunimmt und mehr Informationen in unser Basisbild einfließen, steigt das Signal, das an das Modell gesendet wird, und unser Vertrauen in das, was tatsächlich im Bild enthalten ist. Wenn α = 0 ist, kann das Modell (oder irgendjemand sonst) natürlich keine genaue Vorhersage treffen. Es gibt keine Informationen im Bild! Wenn wir jedoch α erhöhen und uns entlang der geraden Linie bewegen, wird der Inhalt des Bildes klarer und das Modell kann eine vernünftige Vorhersage treffen.

Wenn wir uns das mathematisch vorstellen, wird das Vertrauen in die Vorhersage des Modells durch den Wert der letzten Softmax-Ausgabeschicht quantifiziert. Wenn wir prediction mit unserem trainierten Modell auf den interpolierten Bildern aufrufen, können wir das Vertrauen des Modells in das Label "Schwefelhaubenkakadu" direkt überprüfen:

LABEL = 'sulfur-crested cockatoo'
pred = model(interpolated_images)

idx_cockatoo = np.where(imagenet_labels==LABEL)[0][0]
pred_proba = tf.nn.softmax(pred, axis=-1)[:, idx_cockatoo]

Es überrascht nicht, dass irgendwann vor der α = 1 hat das Modell einen Aha-Moment und die Modellvorhersage wird zum "Kakadu", wie in Abbildung 4-3 gezeigt wird, wenn α . 15 .

Hier können wir auch sehen, wie wichtig die Wahl der Basislinie ist. Wie hätten sich die Vorhersagen unseres Modells verändert, wenn wir mit einer weißen Basislinie begonnen hätten? Oder mit einer Basislinie aus zufälligem Rauschen? Wenn wir die gleiche Grafik wie in Abbildung 4-3 erstellen, aber die weiße Basislinie und die Rauschbasislinie verwenden, erhalten wir unterschiedliche Ergebnisse. Für die weiße Basislinie springt das Vertrauen des Modells in die vorhergesagte Klasse etwa um α 0 . 25 , während bei der Gaußschen Rauschbasislinie das Aha-Erlebnis erst bei α 0 . 9 wie in Abbildung 4-5 zu sehen. Der vollständige Code für diese Beispiele befindet sich im Repository des Buches.

Abbildung 4-5. Bei Verwendung einer weißen Basislinie (oben) oder einer Basislinie, die auf Gaußschem Rauschen basiert (unten), braucht das Modell länger, um das gleiche Vertrauen in das wahre Label zu erreichen.

Farbverläufe akkumulieren

Der letzte Schritt bei der Anwendung integrierter Gradienten ist und dann die Festlegung eines Weges, wie diese Gradienten verwendet werden können, um zu entscheiden, welche Pixel oder Pixelbereiche am effektivsten zu dem Aha-Erlebnis beigetragen haben, das wir in Abbildung 4-3 gesehen haben, als α bei etwa 0,15 lag und das Modell eine Konfidenz von über 0,98 aufwies. Wir wollen wissen, wie das Netzwerk von der Nullvorhersage zur richtigen Bezeichnung gekommen ist. An dieser Stelle kommt der Gradiententeil der Integrated Gradients-Technik ins Spiel. Der Gradient einer skalarwertigen Funktion misst die Richtung des steilsten Anstiegs in Bezug auf die Eingaben der Funktion. In diesem Zusammenhang ist die Funktion, die wir betrachten, die endgültige Ausgabe des Modells für die Zielklasse, und die Eingaben sind die Pixelwerte.

Wir können TensorFlows tf.GradientTape zur automatischen Differenzierung verwenden, um den Gradienten unserer Modellfunktion zu berechnen. Wir müssen TensorFlow nur sagen, dass es die Tensoren des Eingangsbildes während der Modellberechnung "beobachten" soll. Beachte, dass wir hier TensorFlow verwenden, aber jede Bibliothek zur automatischen Differenzierung für andere ML-Frameworks funktioniert genauso gut:

def compute_gradients(images, target_class_idx):
    with tf.GradientTape() as tape:
        tape.watch(images)
        logits = model(images)
        probs = tf.nn.softmax(logits, axis=-1)[:, target_class_idx]
    return tape.gradient(probs, images)

Da das Modell einen (1,1001)-förmigen Tensor mit Logits für jede vorhergesagte Klasse zurückgibt, schneiden wir auf target_class_idx, dem Index der Zielklasse, so dass wir nur die vorhergesagte Wahrscheinlichkeit für die Zielklasse erhalten. Bei einer Sammlung von Bildern gibt die Funktion compute_gradients die Gradienten der Modellfunktion zurück.

Leider ist die direkte Verwendung der Gradienten problematisch, da sie in eine Sättigung geraten können, d. h. die Wahrscheinlichkeiten für die Zielklasse erreichen ein Plateau, lange bevor der Wert für α 1 erreicht. Wenn wir uns den Durchschnittswert der Pixelgradienten ansehen, sehen wir, dass das Modell am meisten lernt, wenn der Wert von Alpha niedriger ist, also genau um den Aha-Moment bei α 0 . 1 . Danach, wenn α größer als 0,2 ist, gehen die Steigungen auf Null, sodass nichts Neues mehr gelernt wird, wie in Abbildung 4-6 zu sehen ist.

Abbildung 4-6. Das Modell lernt am meisten, wenn der Wert von Alpha niedriger ist. Danach, wenn α > 0 . 2 gehen die Pixelgradienten auf Null.

Wir wollen wissen, welche Pixel am meisten dazu beigetragen haben, dass das Modell die richtige Ausgangsklasse vorhersagen konnte. Durch die Integration über einen Pfad vermeidet der Integrierte Gradient das Problem, dass lokale Gradienten gesättigt werden. Die Idee ist, dass wir die lokalen Gradienten der Pixel akkumulieren, während wir uns entlang des geradlinigen Pfades vom Ausgangsbild zum Eingangsbild bewegen. Auf diese Weise akkumulieren wir die lokalen Gradienten eines Pixels und addieren oder subtrahieren seinen Wichtigkeitswert zur Gesamtwahrscheinlichkeit des Modells für die Ausgabeklasse. Der Wichtigkeitswert des i-ten Pixel-Merkmalswertes eines Bildes ist formell x für das Modell f ist definiert als:

IG i ( f , x , x ' ) = α=0 α=1 ( x i - x i ' ) f(x '+α(x-x ' )) x i d α

Hier x ' das Grundlinienbild. Auch wenn es auf den ersten Blick nicht so aussieht, handelt es sich um das Integral der Steigung des i-ten Merkmals auf der geraden Strecke zwischen dem Basisbild und dem Eingangsbild. Um dies im Code zu berechnen, müssten wir eine numerische Annäherung mit Riemannschen Summen verwenden (siehe "Annäherung von Integralen mit Riemannschen Summen" weiter unten in diesem Kapitel) und über m Schritte summieren. Der Parameter m ( ) ist wichtig, und bei der Wahl des richtigen Werts ist ein Kompromiss zu beachten. Wenn er zu klein ist, wird die Annäherung ungenau. Ist die Anzahl der Schritte zu groß, ist die Annäherung zwar nahezu perfekt, aber die Berechnungszeit ist lang. Du wirst wahrscheinlich mit der Anzahl der Schritte experimentieren wollen.

Bei der Wahl der Anzahl der Schritte, die für die integrale Annäherung verwendet werden sollen, schlägt das Originalpapier2 wird empfohlen, zwischen 20 und 300 Schritten zu experimentieren. Dies kann jedoch je nach Datensatz und Anwendungsfall variieren. Ein guter Ausgangspunkt für natürliche Bilder, wie sie im ImageNet zu finden sind, ist zum Beispiel m = 50 . In der Praxis kann es für manche Anwendungen notwendig sein, eine Integralannäherung mit einem Fehler von 5% (oder weniger!) des tatsächlichen Integrals zu erhalten. In diesen Fällen können einige tausend Schritte erforderlich sein, obwohl die visuelle Konvergenz in der Regel mit viel weniger Schritten erreicht werden kann. In der Praxis haben wir festgestellt, dass 10 bis 30 Schritte eine gute Ausgangsbasis sind.

Sobald du die Annäherungen berechnet hast, kannst du die Qualität der Annäherung überprüfen, indem du die durch die Verwendung der integrierten Gradienten erhaltene Zuordnungsbewertung mit der Differenz zwischen der Zuordnungsbewertung des Eingabebildes und der Zuordnungsbewertung des Basisbildes vergleichst. Der folgende Codeblock zeigt dir, wie du das machst:

# The baseline's prediction and attribution score
baseline_prediction = model(tf.expand_dims(baseline, 0))
baseline_score = tf.nn.softmax(tf.squeeze(baseline_prediction))[target_class_idx]

# Your model's prediction and attribution score
input_prediction = model(tf.expand_dims(input, 0))
input_score = tf.nn.softmax(tf.squeeze(input_prediction))[target_class_idx]

# Compare with the attribution score from Integrated Gradients
ig_score = tf.math.reduce_sum(attributions)
delta = ig_score - (input_score - baseline_score)

Wenn der absolute Wert von delta größer als 0,05 ist, solltest du die Anzahl der Schritte bei der Annäherung erhöhen. Den vollständigen Code findest du im Code für die Funktion check_convergence im Notizbuch Integrierte Gradienten zu diesem Buch.

Viele der großen Cloud-Provider bieten verwaltete Implementierungen von verschiedenen XAI-Techniken an. Für benutzerdefinierte Modelle und für Modelle, die mit AutoML trainiert wurden, bietet Google Cloud Erklärungen über Shapley-Samples, Integrated Gradients und XRAI (siehe "XRAI"). Wenn du Erklärungen für eine Instanz anforderst, berechnet die Google Cloud-Implementierung von Integrated Gradients auch den Approximationsfehler für dich und gibt diesen zusammen mit den Erklärungen zurück.

Ein hoher Approximationsfehler (z. B. über 0,05) zeigt an, dass die Qualität der Erklärung möglicherweise nicht zuverlässig ist und du die XAI-Konfigurationen anpassen musst. Insbesondere wenn du mit selbst trainierten Modellen arbeitest, kannst du bestimmte Parameter konfigurieren, um deine Erklärungen zu verbessern und den Annäherungsfehler zu verringern, indem du die folgenden Eingaben änderst:

  • Erhöhung der Anzahl der Integralschritte

  • Ändern der Eingabebasislinie(n)

  • Hinzufügen weiterer Input-Baselines

Abbildung 4-7. Wenn die Anzahl der Rechtecke gegen unendlich geht, geht der Fehler zwischen der Annäherung durch die Riemannsche Summe und der wahren Fläche unter der Kurve gegen Null, wenn es sich um einigermaßen brauchbare Funktionen handelt. Dies stellt einen Kompromiss dar, wenn man Riemannsche Summen zur Annäherung an stetige Integrale verwendet.

Die Verwendung des Hyperparameters m für die Anzahl der Schritte können wir das Integral für die Berechnung der Integrierten Gradienten auf folgende Weise annähern:

IG i ca. ( f , x , x ' ) = ( x i - x i ' ) k=1 m 1 m f(x) x i x=interpoliertBilder

Im Notizbuch, das Integrated Gradients im GitHub Repository für dieses Buch behandelt, kannst du sehen, wie jede Komponente dieser Summe direkt in Python und TensorFlow in der Funktion integrated_gradients berechnet wird. Zuerst wird die α erstellt und die Gradienten entlang der geraden Strecke in Stapeln gesammelt. Hier bestimmt das Argument num die Anzahl der Schritte, die bei der integralen Annäherung verwendet werden sollen:

  # Generate alphas.
  alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1)

  # Collect gradients.    
  gradient_batches = []

  # Iterate alphas range and batch speed, efficiency, and scaling
  for alpha in tf.range(0, len(alphas), batch_size):
    from_ = alpha
    to = tf.minimum(from_ + batch_size, len(alphas))
    alpha_batch = alphas[from_:to]

    gradient_batch = one_batch(baseline, image, alpha_batch, target_class_idx)
    gradient_batches.append(gradient_batch)

Dann werden diese stapelweisen Gradienten zu einem einzigen Tensor zusammengefasst und die integrale Annäherung wird berechnet, wie im folgenden Code gezeigt. Die Anzahl der Gradienten wird durch die Anzahl der Schritte m_steps gesteuert:

  # Concatenate path gradients.
  total_gradients = tf.concat(gradient_batches, axis=0)

  # Compute Integral approximation of all gradients.
  avg_gradients = integral_approximation(gradients=total_gradients)

Schließlich skalieren wir die Annäherung und geben die Ergebnisse des integrierten Gradienten zurück:

  # Scale Integrated Gradients with respect to input.
  integrated_gradients = (image - baseline) * avg_gradients

Du kannst diese Zuordnungen visualisieren und sie über das Originalbild legen. Der folgende Code summiert die absoluten Werte der integrierten Farbverläufe über die Farbkanäle, um eine Attributionsmaske zu erstellen:

  attributions = integrated_gradients(baseline=black_baseline,
                                      image=input_image,
                                      target_class_idx=target_class_idx,
                                      m_steps=m_steps)
  attribution_mask = tf.reduce_sum(tf.math.abs(attributions), axis=-1)

Anschließend kannst du die Zuordnungsmaske mit dem Originalbild überlagern, wie in Abbildung 4-8 gezeigt. Den vollständigen Code für dieses Beispiel findest du im Notizbuch im GitHub-Repository.

Abbildung 4-8. Nach der Berechnung der Merkmalszuweisungen durch die Integrated Gradients-Technik zeigt die Überlagerung der Zuweisungsmaske über das Original, welche Teile des Bildes am meisten zur Klassenvorhersage des Modells beigetragen haben.
Abbildung 4-9. Die Ergebnisse der Anwendung von integrierten Farbverläufen mit einer weißen Grundlinie im Vergleich zu einer schwarzen Grundlinie sind bei einem überwiegend weißen Bild, wie einem Schwefelhaubenkakadu, sehr unterschiedlich.

Der Code und die Diskussion in diesem Abschnitt zeigen, was wirklich "unter der Haube" passiert, wenn du Integrierte Gradienten für die Erklärbarkeit von Modellen implementierst. Es gibt auch weitere High-Level-Bibliotheken, die genutzt werden können und einfach zu implementieren sind. Insbesondere die von der People + AI Research (PAIR)-Gruppe bei Google entwickelte Saliency-Bibliothek enthält benutzerfreundliche Implementierungen von Integrated Gradients, seinen vielen Varianten und anderen Erklärungsmethoden. Im Notebook im GitHub-Repository des Buches kannst du nachlesen, wie die Bibliothek saliency verwendet werden kann , um mit Hilfe von Integrated Gradients Zuordnungsmasken zu finden.

Verbesserungen an integrierten Gradienten

Die Methode der integrierten Gradienten ist eine der am weitesten verbreiteten und bekanntesten gradientenbasierten Zuordnungsmethoden zur Erklärung von Deep Networks. Bei einigen Eingabebeispielen kann diese Methode jedoch zu verfälschten oder verrauschten Pixelzuordnungen führen, die nicht mit der vom Modell vorhergesagten Klasse übereinstimmen. Das liegt zum Teil an der Anhäufung von Rauschen in Regionen mit korrelierten, hochgradigen Gradienten für irrelevante Pixel, die entlang des geraden Pfades auftreten, der bei der Berechnung der integrierten Gradienten verwendet wird. Dies hängt auch eng mit der Wahl der Basislinie zusammen, die bei der Berechnung der Integrierten Gradienten für ein Bild verwendet wird.

Es wurden verschiedene Techniken eingeführt, um die Probleme zu lösen, die bei der Verwendung von Integrierten Gradienten auftreten können. Wir werden zwei Variationen des klassischen Ansatzes der integrierten Farbverläufe besprechen: Integrierte Farbverläufe verwischen und geführte integrierte Farbverläufe.

Integrierte Unschärfeverläufe (Blur-IG)

Im Abschnitt "Wahl der Basislinie" hast du gesehen, dass bei der Implementierung von integrierten Gradienten die Wahl der Basislinie sehr wichtig ist und erhebliche Auswirkungen auf die resultierenden Erklärungen haben kann. Blur Integrated Gradients (Blur-IG) geht speziell auf die Probleme ein, die bei der Wahl einer bestimmten Basislinie auftreten. Kurz gesagt, Blur-IG macht die Angabe einer Basislinie als Parameter überflüssig und empfiehlt stattdessen die Verwendung des unscharfen Eingangsbildes als Basislinie bei der Implementierung von Integrierten Farbverläufen.

Dies geschieht durch die Anwendung eines Gaußschen Unschärfefilters, der durch seine Varianz parametrisiert ist α . Anschließend berechnen wir die Integrierten Gradienten entlang der geraden Linie von diesem unscharfen Bild zum echten, unscharfen Bild. Als σ steigt, wird das Bild immer unschärfer, wie in Abbildung 4-10 dargestellt. Der maximale Maßstab σ max sollte so gewählt werden, dass das maximal unscharfe Bild keine Informationen mehr enthält, d. h. das Bild ist so unscharf, dass es nicht mehr klassifiziert werden kann, was sich auf dem Bild befindet.

Abbildung 4-10. Ohne Unschärfe sagt das Modell "Stieglitz" mit 97,5 % Sicherheit voraus, aber mit σ = 6 . 7 wird die beste Vorhersage des Modells zur "Sicherheitsnadel".

Die Idee ist, dass für verschiedene Skalenwerte von σ unterschiedliche Merkmale erhalten oder zerstört werden, je nachdem, wie groß das Merkmal selbst ist. Je kleiner die Variation des Merkmals ist, desto kleiner ist der Wert von σ desto kleiner ist der Wert von σ, bei dem es zerstört wird, wie die Details in den Flügelmustern des Stieglitzes in Abbildung 4-10 zeigen. Wenn σ kleiner als 3 ist, ist das schwarz-weiße Muster auf den Flügeln noch erkennbar. Doch bei größeren Werten von σ sind die Flügel und der Kopf nur noch verschwommen.

Wir können die Saliency Maps vergleichen, die bei der Verwendung normaler integrierter Farbverläufe im Vergleich zu integrierten Weichzeichner-Farbverläufen entstehen (siehe Abbildung 4-11). Mit der Bibliothek saliency ist dies in nur wenigen Codezeilen möglich:

# Construct the saliency object.
integrated_gradients = saliency.IntegratedGradients()
blur_ig = saliency.BlurIG()

# Baseline is a black image.
baseline = np.zeros(im.shape)

# Compute the IG mask and the Blur IG mask.
integrated_gradients_mask_3d = integrated_gradients.GetMask(
  im, call_model_function, call_model_args, x_steps=25, x_baseline=baseline, 
  batch_size=20)
blur_ig_mask_3d = blur_ig.GetMask(
  im, call_model_function, call_model_args, batch_size=20)

In diesem Codeblock ist call_model_function eine generische Funktion, die angibt, wie die Eingaben an ein bestimmtes Modell übergeben werden und wie die Ausgaben für die Berechnung der Saliency-Masken zustande kommen. Sie kann mit jedem ML-Framework verwendet werden. Den vollständigen Code für dieses Beispiel findest du im Notizbuch zu integrierten Farbverläufen. Bei diesem Beispiel eines amerikanischen Stieglitzes liefert Blur-IG viel überzeugendere Zuordnungen als die Vanilla Integrated Gradients.

Abbildung 4-11. Die Saliency Map für Blur-IG erkennt die Teile des Bildes, aus denen der Stieglitz besteht, viel besser.

Geführte integrierte Gradienten (Guided IG)

Guided Integrated Gradients (Guided IG) versucht, die Integrated Gradients zu verbessern, indem es den geradlinigen Pfad, der bei der Implementierung verwendet wird, verändert. Anstatt einen geradlinigen Pfad von der Grundlinie zum Eingangsbild zu verwenden, nutzt Guided IG einen angepassten Pfad, um Karten zu erstellen, die besser mit der Vorhersage des Modells übereinstimmen. Anstatt die Pixelintensitäten in einer festen geraden Richtung von der Basislinie zum Eingangsbild zu bewegen, treffen wir bei jedem Schritt eine Auswahl. Genauer gesagt bewegt sich Guided IG in die Richtung, in der die Merkmale (d. h. die Pixel) den kleinsten absoluten Wert der partiellen Ableitungen haben. Wenn die Intensität der Pixel gleich der des Eingangsbildes wird, werden sie ignoriert.

Die Idee dahinter ist, dass der typische geradlinige Pfad, der von den bisher besprochenen integrierten Gradiententechniken verwendet wird, möglicherweise durch Punkte im Merkmalsraum führt, in denen die Gradientennorm groß ist und nicht in die Richtung des Integrationspfads zeigt. Infolgedessen führt der naive, geradlinige Pfad zu Rauschen und einer Anhäufung von Gradienten in gesättigten Regionen, was dazu führt, dass falschen Pixeln oder Regionen bei der Berechnung von Saliency Maps eine zu hohe Bedeutung beigemessen wird. Guided IG vermeidet dieses Problem, indem es stattdessen entlang eines angepassten Pfades im Merkmalsraum navigiert und dabei die Geometrie der Modelloberfläche im Merkmalsraum berücksichtigt. In Abbildung 4-12 wird das Ergebnis der Anwendung von Vanilla Integrated Gradients mit dem von Guided Integrated Gradients verglichen. Den vollständigen Code für dieses Beispiel findest du im Integrated Gradients-Notizbuch im GitHub-Repository dieses Buches.

Für das Beispielbild in Abbildung 4-12 scheint sich die Salienzkarte für das Guided IG Beispiel mehr auf den Stieglitz im Bild zu konzentrieren als die Salienzkarte für Integrated Gradients, aber beide Methoden scheinen keine besonders überzeugenden Erklärungen zu liefern. Das könnte darauf hindeuten, dass unser Modell mehr Training oder mehr Daten braucht. Oder vielleicht sind sowohl Integrated Gradients als auch Guided IG einfach nicht gut für diese Aufgabe oder diesen Datensatz geeignet und eine andere Methode würde besser funktionieren. Es gibt keine XAI-Methode, die für alle gleich gut geeignet ist. Deshalb ist es wichtig, ein gut ausgestattetes Toolkit an Techniken zu haben, die du bei der Analyse deiner Modellvorhersagen einsetzen kannst.

Abbildung 4-12. Die Saliency Map für das Guided IG-Beispiel konzentriert sich mehr auf den Stieglitz im Bild als die Saliency Map für Integrated Gradients, aber beide Methoden scheinen keine besonders gute Arbeit zu leisten, um überzeugende Erklärungen zu liefern.

XRAI

Hier erfährst du, was du über XRAI wissen musst:

  • XRAI ist eine regionenbasierte Zuordnungsmethode, die auf integrierten Gradienten aufbaut .

  • XRAI bestimmt die wichtigen Regionen indem es das Eingangsbild anhand einer Ähnlichkeitsmetrik in ähnliche Regionen segmentiert und dann die Attributionswerte für diese ähnlichen Regionen bestimmt.

  • XRAI ist eine lokale Erklärungsmethode, die auf jedes DNN-basierte Modell angewendet werden kann, solange es eine Möglichkeit gibt, die Eingangsmerkmale mithilfe einer Ähnlichkeitsmetrik in Segmente zu gruppieren.

Profis Nachteile
  • XRAI verbessert andere gradientenbasierte Techniken wie Vanilla Integrated Gradients.

  • XRAI kann schneller sein als störungsbasierte Methoden wie LIME, die mehrere Abfragen an das Modell erfordern.

  • Am besten funktioniert es bei natürlichen Bildern, wie z. B. dem Bild eines Tieres oder eines Objekts, wie sie auch in den Benchmark-Datensätzen ImageNet und CIFAR vorkommen.

  • XRAI ist nur für Bildmodelle nützlich.

  • Es gibt eine geringere Granularität als eine Technik wie Integrated Gradients, die eine Zuordnung auf Pixelebene ermöglicht.

  • XRAI wird nicht für kontrastarme Bilder oder Bilder empfohlen, die in einer nicht natürlichen Umgebung aufgenommen wurden, wie z. B. Röntgenbilder.

Die Saliency Maps von , die mit Hilfe von Integrated Gradients erstellt wurden, bieten ein leicht verständliches Werkzeug, um zu sehen, welche Pixel am meisten zur Vorhersage eines Modells für ein bestimmtes Bild beitragen. XRAI baut auf der Methode der Integrated Gradients auf, indem es Pixel zu Regionen zusammenfasst. Anstatt einzelne Pixel hervorzuheben, die am wichtigsten waren, heben die von XRAI erstellten Saliency Maps Pixelregionen hervor, die im Bild von Interesse sind .

Eine Schlüsselkomponente und der erste Schritt des XRAI-Algorithmus ist die Segmentierung des Bildes, um die Regionen von Interesse zu bestimmen. Die Bildsegmentierung ist ein beliebter Anwendungsfall in der Computer Vision, der darauf abzielt, ein Bild in mehrere Regionen aufzuteilen, die konzeptionell ähnlich sind, wie in Abbildung 4-13 dargestellt.

Abbildung 4-13. Bei der Bildsegmentierung wird jedem Pixel eines Bildes eine Klasse zugewiesen. Hier sind einige Beispiele aus dem Common Objects in Context (COCO)-Datensatz.

Die Bildsegmentierung ist ein gut untersuchtes Problem in der Computer Vision, und Deep-Learning-Architekturen wie U-Net, Fast R-CNNs und Mask R-CNNs wurden speziell für diese Herausforderung entwickelt und können Spitzenergebnisse liefern. Einer der wichtigsten Schritte des XRAI-Algorithmus verwendet einen Algorithmus namens Felzenszwalb-Algorithmus, um ein Eingangsbild in ähnliche Regionen zu segmentieren, ähnlich wie ein Clustering-Algorithmus für die nächsten Nachbarn. Der Felzenszwalb-Algorithmus basiert nicht auf Deep Learning.3 Stattdessen handelt es sich um einen graphenbasierten Ansatz, der auf dem Minimum-Spanning-Tree-Algorithmus von Kruskal basiert und eine unglaublich effiziente Methode zur Bildsegmentierung darstellt. Der entscheidende Vorteil des Felzenszwalb-Algorithmus ist, dass er die wichtigen nichtlokalen Regionen eines Bildes erfasst, die global relevant sind, und gleichzeitig rechnerisch effizient ist mit einer Zeitkomplexität 𝒪 ( n log n ) wobei n die Anzahl der Pixel ist.

Die Idee ist, ein Bild als einen zusammenhängenden Graphen darzustellen G = ( V , E ) von Scheitelpunkten V und Kanten E wobei jedes Pixel ein Knoten im Graphen ist und die Kanten benachbarte Pixel miteinander verbinden. Der Segmentierungsalgorithmus prüft dann iterativ die Wichtigkeit jeder Region und verfeinert die Graphenpartitionen, indem er kleinere Regionen zu größeren Segmenten zusammenfasst, bis eine optimale Segmentierung gefunden ist. Das Ergebnis ist die in Abbildung 4-14 dargestellte Segmentierung.

Abbildung 4-14. Der Felzenszwalb-Segmentierungsalgorithmus stellt ein Bild als gewichteten, ungerichteten Graphen dar und teilt den Graphen dann so auf, dass die Variation über zwei verschiedene Komponenten hinweg größer ist als die Variation über jede einzelne Komponente.

Die Empfindlichkeit gegenüber den Unterschieden innerhalb der Gruppe und zwischen den Gruppen wird durch eine Schwellenwertfunktion gesteuert. Die Strenge dieser Schwelle wird durch den Parameter k . Du kannst dir das so vorstellen k als Einstellung des Beobachtungsmaßstabs für den Segmentierungsalgorithmus betrachten. Abbildung 4-15 zeigt die resultierenden Bildsegmentierungen für verschiedene Werte von k . Diese Bilder wurden mit dem Paket segmentation der Bibliothek scikit-image erstellt. Der Code für dieses Beispiel ist im GitHub-Repository dieses Buches verfügbar. Wie du dort sehen kannst, ist ein größerer Wert von k eine Präferenz für größere Komponenten, während ein kleinerer Wert von k kleinere Regionen zulässt. Es ist wichtig zu beachten, dass k keine Mindestgröße der Komponenten garantiert. Kleinere Komponenten sind weiterhin erlaubt, sie erfordern nur einen größeren Unterschied zwischen benachbarten Komponenten.

Abbildung 4-15. Der Parameter k steuert die Schwellenwertfunktion für den Felzenszwalb-Segmentierungsalgorithmus. Ein größerer Wert von k bewirkt eine Bevorzugung größerer Komponenten, während ein kleinerer Wert von k für kleinere Regionen sorgt.

Wie XRAI funktioniert

XRAI kombiniert die Ergebnisse der Anwendung von Integrated Gradients auf ein Eingangsbild mit der Bildsegmentierung, die der im vorherigen Abschnitt beschriebene Algorithmus von Felzenszwalb liefert. Da Integrated Gradients Zuordnungen auf Pixelebene liefert, kann XRAI durch die Aggregation dieser lokalen Merkmalszuordnungen über die global relevanten Segmente, die aus der Bildsegmentierung hervorgehen, jedes Segment in eine Rangfolge bringen und die Segmente ordnen, die am meisten zur Vorhersage einer bestimmten Klasse beitragen.

Wenn ein Segment, z. B. das Segment, das aus dem Körper und dem Kamm des Kakadus in Abbildung 4-14 besteht, viele Pixel enthält, die über Integrated Gradients als salient eingestuft werden, dann würde dieses Segment auch über XRAI als hoch salient eingestuft werden. Ein viel kleinerer Bereich, wie z. B. das Segment, das das Auge des Kakadus darstellt, würde dagegen von XRAI nicht so hoch eingestuft werden, auch wenn die Pixel laut den Ergebnissen der Anwendung von Integrated Gradients hohe Salienzwerte haben. Dies schützt vor einzelnen Pixeln oder kleinen Pixelsegmenten, die bei der Anwendung der Integrierten Farbverläufe allein fälschlicherweise eine hohe Salienz aufweisen.

Dabei ist jedoch zu beachten, wie empfindlich das Segmentierungsergebnis ist und wie eine bestimmte Wahl von Hyperparametern das Ergebnis verfälschen kann. Um dies zu berücksichtigen, wird das Bild mehrmals mit verschiedenen Werten (50, 100, 150, 250, 500, 1200) für den Skalenparameter segmentiert k . Darüber hinaus werden Segmente, die kleiner als 20 Pixel sind, vollständig ignoriert. Da für einen einzelnen Parameter die Vereinigung der Segmente das gesamte Bild ergibt, ergibt die Vereinigung aller Segmente, die sich aus allen Parametern ergeben, eine Fläche, die etwa dem Sechsfachen der gesamten Bildfläche entspricht, wobei sich mehrere Segmente überlappen. Jede der Regionen aus dieser Übersegmentierung wird bei der Aggregation der untergeordneten Zuordnungen verwendet.

Zusammenfassend lässt sich sagen, dass bei der Implementierung von XRAI zunächst die Methode der integrierten Farbverläufe mit einer schwarzen und einer weißen Grundlinie angewendet wird, um die Zuordnungen auf Pixelebene zu bestimmen (siehe Abbildung 4-16). Gleichzeitig wird der graphenbasierte Segmentierungsalgorithmus von Felzenszwalb mehrfach angewendet, wobei eine Reihe von Skalenparametern für k = 50, 100, 150, 250, 500, 1200 verwendet wird. Dies führt zu einer Übersegmentierung des Originalbildes. XRAI fasst dann die Zuordnungen auf Pixelebene zusammen, indem es die Werte der integrierten Gradientenausgabe in jedem der entstandenen Segmente addiert und jedes Segment von der größten bis zur geringsten Auffälligkeit einstuft. Das Ergebnis ist eine Heatmap, die die Bereiche des Originalbildes hervorhebt, die am stärksten zur Klassenvorhersage des Modells beitragen. Wenn wir diese Heatmap über das Originalbild legen, können wir sehen, welche Regionen am stärksten zur Vorhersage von "Schwefelhaubenkakadu" beitragen.

Abbildung 4-16. XRAI kombiniert die Ergebnisse der Methode der Integrierten Gradienten mit den übersegmentierten Regionen, die aus mehreren Anwendungen des Segmentierungsalgorithmus von Felzenszwalb stammen. Die Zuordnungen auf Pixelebene werden dann über die übersegmentierten Regionen aggregiert und in eine Rangfolge gebracht, um zu bestimmen, welche Regionen für das Modell am wichtigsten sind.

XRAI einführen

XRAI ist eine Post-hoc-Erklärungsmethode und kann auf jedes DNN-basierte Modell angewendet werden. Schauen wir uns ein Beispiel für die Implementierung von XRAI mit der saliency Bibliothek an, die von der People + AI Research (PAIR) Gruppe bei Google entwickelt wurde. Im folgenden Code-Block laden wir ein VGG-16-Modell, das mit dem ImageNet-Datensatz trainiert wurde, und ändern die Ausgaben so, dass wir die Modellvorhersage m.output sowie eine der Faltungsblockschichten block5_conv3 erfassen können. Den vollständigen Code für dieses Beispiel findest du im XRAI for Image Explainability-Notebook im GitHub-Repository dieses Buches:

m = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True)
conv_layer = m.get_layer('block5_conv3')
model = tf.keras.models.Model([m.inputs], [conv_layer.output, m.output])

Um die XRAI-Attribute zu erhalten, erstellen wir ein saliency -Objekt für XRAI und rufen die Methode GetMask mit ein paar Schlüsselargumenten auf:

xrai_object = saliency.XRAI()
xrai_attributions = xrai_object.GetMask(image,
                                        call_model_function,
                                        call_model_args,
                                        batch_size=20)

Das Argument image ist ziemlich selbsterklärend: Es ist das Bild, für das wir die XRAI-Attribute erhalten wollen, die als Numpy-Array übergeben werden. Kommen wir nun zu den anderen Argumenten: call_model_function und call_model_args. Mit call_model_function übergeben wir die Eingaben an unser Modell und erhalten die Ausgaben, die für die Berechnung einer Saliency-Maske erforderlich sind. Es ruft das Modell auf und erwartet daher Eingabebilder. Alle Argumente, die beim Aufrufen und Ausführen des Modells benötigt werden, werden von call_model_args verarbeitet. Das letzte Argument, expected_keys, teilt der Funktion die Liste der Schlüssel mit, die in der Ausgabe erwartet werden. Wir verwenden die call_model_function, die im folgenden Code definiert ist, und bekommen entweder die Gradienten in Bezug auf die Eingaben oder die Gradienten in Bezug auf die Faltungszwischenschicht zurück:

class_idx_str = 'class_idx_str'
def call_model_function(images, call_model_args=None, expected_keys=None):
    target_class_idx = call_model_args[class_idx_str]
    images = tf.convert_to_tensor(images)
    with tf.GradientTape() as tape:
        if expected_keys==[saliency.base.INPUT_OUTPUT_GRADIENTS]:
            tape.watch(images)
            _, output_layer = model(images)
            output_layer = output_layer[:,target_class_idx]
            gradients = np.array(tape.gradient(output_layer, images))
            return {saliency.base.INPUT_OUTPUT_GRADIENTS: gradients}
        else:
            conv_layer, output_layer = model(images)
            gradients = np.array(tape.gradient(output_layer, conv_layer))
            return {saliency.base.CONVOLUTION_LAYER_VALUES: conv_layer,
                    saliency.base.CONVOLUTION_OUTPUT_GRADIENTS: gradients}

Du erinnerst dich vielleicht daran, dass du bei der Implementierung von Integrierten Gradienten die Anzahl der Schritte für die Berechnung des Linienintegrals als Hyperparameter einstellen kannst. Da XRAI auf die Ausgabe von Integrated Gradients angewiesen ist, fragst du dich vielleicht, wo und wie du diesen Hyperparameter für XRAI anpasst. In der Bibliothek saliency werden diese Art von Hyperparametern mit einer Unterklasse namens XRAIParameters gesteuert. Die Standardanzahl der Schritte ist auf 100 eingestellt. Um die Anzahl der Schritte auf 200 zu ändern, erstellst du einfach ein XRAIParameters Objekt und übergibst es ebenfalls an die Funktion GetMask:

xrai_params = saliency.XRAIParameters()
xrai_params.steps = 200

xrai_attributions_fast = xrai_object.GetMask(im,
                                             call_model_function,
                                             call_model_args,
                                             extra_parameters=xrai_params,
                                             batch_size=20)

Schließlich können wir das Objekt xrai_attributions, das durch den Aufruf von GetMask an zurückgegeben wird, aufzeichnen, um eine Heatmap der Zuschreibungen für das Bild zu erhalten, wie in Abbildung 4-17 gezeigt.

Abbildung 4-17. XRAI erstellt eine Heatmap der Zuordnungen für ein bestimmtes Eingabebild. Bei diesem Bild eines Schwefelhaubenkakadus entsprechen die relevantesten Regionen dem Körper des Vogels, seinem Schnabel und seinem ausgeprägten Kamm.

Um zu sehen, welche Regionen des Originalbildes am auffälligsten waren, konzentriert sich der folgende Code nur auf die auffälligsten 30% und erstellt einen Maskenfilter, der über das Originalbild gelegt wird. Das Ergebnis ist Abbildung 4-18:

mask = xrai_attributions > np.percentile(xrai_attributions, 60)
im_mask = np.array(im_orig)
im_mask[~mask] = 0
ShowImage(im_mask, title='Top 30%', ax=P.subplot(ROWS, COLS, 3))
Abbildung 4-18. Indem wir die XRAI-Attribute filtern, können wir die Heatmap über das Originalbild legen, um nur die auffälligsten Regionen hervorzuheben.

Grad-CAM

Hier erfährst du, was du über Grad-CAM wissen musst:

  • Grad-CAM ist die Abkürzung für Gradient-weighted Class Activation Mapping. Grad-CAM war eine der ersten Erklärbarkeitstechniken; sie verallgemeinert CAM, das nur für bestimmte Modellarchitekturen verwendet werden konnte.

  • Grad-CAM untersucht die Gradienteninformationen, die durch die letzte (oder jede) Faltungsschicht des Netzes fließen.

  • Sie erstellt eine Heatmap zur Lokalisierung, die die Regionen in einem Bild hervorhebt, die für die Vorhersage eines bestimmten Klassenlabels am einflussreichsten sind.

Profis Nachteile
  • Grad-CAM benötigt nur einen Vorwärtsdurchlauf des Modells, ist also rechnerisch effizient und kann leicht von Hand oder mit Open-Source-Bibliotheken implementiert werden.
  • Grad-CAM ist für eine Vielzahl von CNN-Modellen und -Aufgaben anwendbar, z. B. CNNs mit vollständig verknüpften Schichten (für Klassifizierungsaufgaben), CNNs mit multimodalen Eingaben (für die Beantwortung visueller Fragen) oder CNNs für Textausgaben (für Bildunterschriften).
  • Grad-CAM kann mit anderen Pixelraumvisualisierungen kombiniert werden, um hochauflösende klassenunterscheidende Visualisierungen zu erstellen (siehe "Geführte Backpropagation und geführte Grad-CAM").
  • Grad-CAM erzeugt niedrig aufgelöste Heatmaps, die zu falschen oder irreführenden Ergebnissen führen können, weil sie Regionen im Bild zuordnen, die für das Modell nicht von Bedeutung waren. Sei vorsichtig, wenn du die Ergebnisse von Grad-CAM interpretierst.
  • Grad-CAM schneidet bei Multiklassen-Klassifizierungsmodellen mit einer großen Anzahl von Klassenlabels nicht so gut ab wie andere XAI-Methoden.
  • Grad-CAM schlägt fehl, wenn das Bild mehrere Objekte derselben Klasse enthält. Ein Bildklassifikator zur Erkennung einer Katze, der ein Bild mit zwei Katzen erhält, wird beispielsweise eine unzuverlässige Heatmap erstellen.

Grad-CAM ist eine der ursprünglich für Bildmodelle entwickelten Erklärungsmethoden und kann unter auf jedes CNN-basierte Netzwerk angewendet werden. Grad-CAM ist eine Post-hoc-Erklärungstechnik und erfordert keine Änderungen an der Architektur oder ein neues Training. Stattdessen greift Grad-CAM auf die internen Faltungsschichten des Modells zu, um die Regionen zu bestimmen, die den größten Einfluss auf die Vorhersagen des Modells haben. Da Grad-CAM das Modell nur vorwärts durchläuft, ohne Backpropagation, ist es auch rechnerisch effizient.

Wie Grad-CAM funktioniert

Um zu verstehen, wie Grad-CAM funktioniert, müssen wir zunächst wissen, was Class Activation Map (CAM) ist und wie sie funktioniert, denn Grad-CAM ist im Wesentlichen eine Verallgemeinerung von CAM. Wenn du ein Bildmodell erstellst, besteht deine Modellarchitektur in der Regel aus einem Stapel von Faltungsschichten und Pooling-Schichten. Denke zum Beispiel an die klassische VGG-16-Modellarchitektur, die in Abbildung 4-19 dargestellt ist. Es gibt fünf Faltungsblöcke plus Pooling-Blöcke, die als Merkmalsextraktoren fungieren, gefolgt von drei voll verknüpften Schichten (FC) und der abschließenden Softmax-Vorhersageschicht. Die CAM ist eine Lokalisierungskarte des Bildes, die als gewichtete Aktivierungskarte berechnet wird. Dies geschieht durch eine gewichtete Summe der Aktivierungskarten der letzten Faltungsschicht des Modells.

Genauer gesagt, und zur Veranschaulichung mit einem Beispiel, nehmen wir die letzte Faltungsschicht (kurz vor der letzten Pooling-Schicht) des VGG-16-Modells in Abbildung 4-19, das auf im ImageNet-Datensatz trainiert wurde. Die Dimension dieser letzten Faltungsschicht ist 7×7×512. Es gibt also 512 Merkmalskarten, die 1.000 Klassenlabels zugeordnet sind, d. h. die Labels, die dem ImageNet entsprechen.

Abbildung 4-19. VGG-16 besteht aus Blöcken von Faltungsschichten und Pooling-Schichten. CAM ist eine gewichtete Aktivierungskarte, die auf die letzte Faltungsschicht angewendet wird.

Jede Feature Map wird indiziert durch i und j indiziert, die die Breite und Höhe der Faltungsschicht darstellen (in diesem Fall i = j = 7 ). Notationally, A ij k die Aktivierung am Ort ( i , j ) der Merkmalskarte A k . Diese Merkmalskarten werden dann mit Hilfe des Global Average Pooling zusammengeführt und CAM berechnet eine endgültige Punktzahl Y c für jede Klasse c durch eine gewichtete Summe der gepoolten Feature-Maps, wobei die Gewichte durch die Gewichte zwischen den einzelnen Klassen gegeben sind. k -te Feature Map mit der c -ten Klasse verbinden:

Y c = k w k c i,j A ij k

Wenn du dann die Steigung von Y c nimmt, d.h. die Punktzahl für die Klasse c in Bezug auf die Merkmalskarten, kannst du den Gewichtungsterm abtrennen w k c herauslösen, so dass du (nach ein bisschen Mathe4) du erhältst:

w k c = i,j Y c A ij k

Dieser Gewichtswert ist fast genau derselbe wie das Gewicht der Neuronen, das in Grad-CAM verwendet wird! Für Grad-CAM ziehst du auch die Aktivierungen heraus A k aus der letzten Faltungsschicht und berechnest den Gradienten der Klassenbewertung Y c in Bezug auf diese A k . In gewisser Weise erfassen diese Gradienten die Informationen, die durch die letzte Faltungsschicht fließen; du willst sie nutzen, um jedem Neuron für eine bestimmte Klasse Wichtigkeitswerte zuzuweisen c . Dieses Wichtigkeitsgewicht wird (ähnlich wie bei CAM) wie folgt berechnet:

α k c = 1 Z i,j Y c A ij k

Der letzte Schritt von Grad-CAM besteht dann darin, eine gewichtete Kombination der Aktivierungskarten zu erstellen, die diese α k c als Gewichte und wendet eine ReLU auf diese Linearkombination an, wie in Abbildung 4-20 dargestellt. So,

L Grad-CAM c = ReLU k α k c A k

Du verwendest hier eine ReLU, weil uns nur die Pixel interessieren, deren Intensität erhöht werden sollte, um die Klassenbewertung zu erhöhen Y c . Erinnere dich daran, dass ReLU negative Werte auf Null abbildet. Wenn wir also ReLU nach der gewichteten Summe anwenden, erfassen wir nur den positiven Einfluss auf die Klassenbewertung. Da die Form von A k die gleiche Form hat wie die letzte Faltungsschicht, entsteht eine grobe Heatmap, die über das Originalbild gelegt werden kann, um zu zeigen, welche Regionen den größten Einfluss auf das Modell zur Vorhersage der Klasse hatten c . Durch die Mittelwertbildung und das Zusammenfassen dieser Merkmalskarten eignet sich Grad-CAM außerdem am besten, um Einflussbereiche im Bild darzustellen, anstatt exakte Pixel. Ein Überblick über den Grad-CAM-Prozess ist in Abbildung 4-20 dargestellt.

Abbildung 4-20. Ein Überblick über Grad-CAM. Die endgültigen Aktivierungskarten A k werden verwendet, um eine gewichtete Summe zu berechnen, die dann durch eine ReLU-Schicht geleitet wird.

Die von Grad-CAM erstellte grobe Heatmap ist problematisch und kann zu irreführenden Ergebnissen führen. Da die Heatmap die gleichen Dimensionen hat wie die endgültigen Faltungsfeature-Maps A k hat, wird sie normalerweise hochgerechnet, um sie an die Form des Originalbildes anzupassen. Die letzte Faltungsschicht der VGG-16 ist beispielsweise 7×7×512 groß, sodass die aus der gewichteten Summe der Aktivierungskarten ermittelte Heatmap die Dimension 7×7 hat, die dann hochgerechnet werden muss, um das Originalbild mit den Maßen 224×224 zu überlagern. Dieses Upsampling kann zu irreführenden Ergebnissen führen, vor allem wenn dein Datensatz aus großen Bildern besteht, deren Form viel größer ist als die interne Aktivierungskarte, oder wenn er Bildmuster und Artefakte enthält, die durch eine Faltung nicht richtig abgetastet werden.

Du fragst dich vielleicht, wie genau Grad-CAM die CAM verbessert, vor allem, wenn sie im Wesentlichen die gleichen Gewichtungen verwenden. Der Vorteil von Grad-CAM ist, dass die Konstruktion von CAM sehr einschränkend ist. Sie erfordert, dass die Feature Maps direkt vor den Softmax-Layern liegen. CAM funktioniert also nur bei bestimmten CNN-Modellarchitekturen, d. h. bei solchen, bei denen die letzten Schichten ein Faltungsmerkmal sind, das einer Global Average Pooling-Schicht zugeordnet ist, die einer Softmax-Vorhersageschicht zugeordnet ist. Das Problem ist, dass diese Architektur möglicherweise nicht die beste Leistung bringt. Indem wir einen Gradienten nehmen und die Terme neu anordnen, kann Grad-CAM die CAM verallgemeinern und funktioniert genauso gut für eine Vielzahl von Architekturen für andere bildbasierte Aufgaben, wie z. B. Bildunterschriften oder die Beantwortung visueller Fragen.

In der Beschreibung von Grad-CAM haben wir nur über die CAM der letzten Faltungsschicht gesprochen. Wie du vielleicht schon gemerkt hast, ist die von uns beschriebene Technik recht allgemein und kann verwendet werden, um Aktivierungen für jede Schicht des tiefen neuronalen Netzes zu erklären.

Einführung von Grad-CAM

Der in Abbildung 4-20 dargestellte Grad-CAM-Algorithmus ist ziemlich einfach und kann direkt von Hand implementiert werden, vorausgesetzt, du hast Zugang zu den internen Schichten deines CNN-Modells. Es gibt jedoch eine benutzerfreundliche Implementierung, die in der saliency Bibliothek verfügbar ist. Schauen wir uns an einem Beispiel an, wie das funktioniert. Du beginnst mit der Erstellung eines TensorFlow-Modells. Im folgenden Codeblock laden wir eine vortrainierte VGG-16-Modellarchitektur, die mit dem ImageNet-Datensatz trainiert wurde. Wir wählen auch die vorletzte Faltungsschicht block5_3 aus, die wir zur Erstellung der Aktivierungskarten verwenden werden. Wenn wir das eigentliche Modell erstellen, werden sowohl die Ausgaben der Faltungsschicht als auch die VGG-16-Ausgaben zurückgegeben, sodass wir weiterhin Vorhersagen treffen können. Den vollständigen Code für dieses Beispiel findest du im Grad-CAM-Notebook im GitHub-Repository für dieses Buch:

vgg16 = tf.keras.applications.vgg16.VGG16(
    weights='imagenet', include_top=True)
conv_layer = m.get_layer('block5_conv3')
model = tf.keras.models.Model(
    [vgg16.inputs], [conv_layer.output, vgg16.output])

Um Grad-CAM anzuwenden, erstellst du ein saliency Objekt, rufst die Grad-CAM Methode auf und wendest dann GetMask an, wobei du das Beispielbild und die call_model_function übergibst. Der folgende Codeblock zeigt, wie das gemacht wird. Die call_model_function ist eine Schnittstelle zu einem Modell, um die Informationen der Faltungsebene und die Gradienten des Modells zurückzugeben. Das Ergebnis ist eine Grad-CAM-Maske, mit der eine Heatmap erstellt werden kann, die einflussreiche Regionen im Bild anzeigt:

# Construct the saliency object. This alone doesn't do anything.
grad_cam = saliency.GradCam()

# Compute the Grad-CAM mask.
grad_cam_mask_3d = grad_cam.GetMask(im, call_model_function, 
call_model_args)

Historisch gesehen ist Grad-CAM eine wichtige Technik. Sie war eine der ersten Techniken, die die internen Faltungsschichten eines CNN-Modells nutzte, um Erklärungen für die Modellvorhersage abzuleiten. Bei der Implementierung und Interpretation der Ergebnisse von Grad-CAM solltest du jedoch vorsichtig sein. Aufgrund des Upsamplings und der Glättungsstufe der Faltungsschicht können einige Regionen der Heatmap wichtig erscheinen, obwohl sie in Wirklichkeit gar keinen Einfluss auf das Modell hatten. Es wurden Verbesserungen vorgenommen, um diese Bedenken auszuräumen (siehe den nächsten Abschnitt "Verbesserung von Grad-CAM" und den späteren Abschnitt "Geführtes Grad-CAM"), aber die Ergebnisse sollten kritisch und im Vergleich mit anderen Techniken betrachtet werden.

Verbesserung von Grad-CAM

Nach der Veröffentlichung der Originalarbeit im Jahr 2017,5 wurde festgestellt, dass Grad-CAM die Aufmerksamkeit des Modells fälschlicherweise Regionen des Bildes zuschreiben konnte, die für die Vorhersage eigentlich nicht von Bedeutung waren. Grad-CAM wendet eine natürliche Glättung oder Interpolation auf seine ursprünglichen Heatmaps an, indem es sie auf die Größe der ursprünglichen Dimensionen des Eingangsbildes vergrößert. Abbildung 4-21 zeigt ein Beispiel dafür, wie die Grad-CAM-Ausgabe mit und ohne Glättung aussieht.

Abbildung 4-21. Grad-CAM nimmt ein Upsampling von der Größe der Feature Map auf die Größe des Originalbildes vor und wendet eine natürliche Glättung an. Dies kann zu irreführenden Ergebnissen führen und die Aufmerksamkeit des Modells fälschlicherweise auf Regionen lenken, die keinen Einfluss hatten.

Die Glättung führt zu einem optisch ansprechenderen Bild mit nahtlosen Veränderungen in den Farben der Heatmap, kann aber auch sehr irreführend sein. Da die ursprüngliche Region auf eine viel kleinere Bildgröße fokussiert war, können wir nicht sagen, dass die verloren gegangenen Pixel den gleichen Einfluss auf das Modell gehabt hätten wie die verbleibenden um sie herum.6 Deshalb haben die Forscher Grad-CAM++ und HiResCAM entwickelt, um diese Probleme zu lösen. Abbildung 4-22 zeigt ein Beispiel dafür, wie sich die Ergebnisse von Grad-CAM und Grad-CAM++ unterscheiden. Diese neueren Verfahren haben dazu beigetragen, diese Bedenken auszuräumen und können genauere Zuordnungskarten erstellen. Doch selbst wenn die regionale Ungenauigkeit behoben ist, bleibt Grad-CAM ein fehlerhaftes Verfahren, da es die ursprüngliche Größe der Merkmalskarten auf die Größe des Eingangsbildes hochrechnet.

Abbildung 4-22. Eine Heatmap aus der Anwendung von Grad-CAM und Grad-CAM++ für die Klassifizierung eines gesunden Heidelbeerblattes. Im Grad-CAM-Bild ist die Heatmap in der Mitte des Blattes am auffälligsten, zeigt aber auch einen gewissen Einfluss des Hintergrunds. Bei Grad-CAM++ sind die aktivierten Pixel gleichmäßiger über das ganze Blatt verteilt, obwohl ein sehr einflussreicher Bereich links unten immer noch dem Hintergrund zugeschrieben wird. (Printleser können das Farbbild unter https://oreil.ly/xai-fig-4-22 sehen .)

LIME

Hier erfährst du, was du über LIME wissen musst: :

  • LIME steht für lokale interpretierbare modellagnostische Erklärungen. Es handelt sich um eine post hoc, störungsbasierte Erklärungsmethode.

  • LIME kann für Regressions- oder Klassifikationsmodelle verwendet werden. In der Praxis wird LIME jedoch hauptsächlich für Klassifikationsmodelle eingesetzt.

  • LIME funktioniert, indem es Bereiche eines Bildes verändert, sie ein- oder ausschaltet und die Schlussfolgerungen wiederholt, um zu sehen, welche Bereiche den größten Einfluss auf die Vorhersage des Modells haben.

  • LIME verwendet ein inhärent interpretierbares Modell, um den Einfluss oder die Wichtigkeit der Eingangsmerkmale zu messen.

Profis Nachteile
  • LIME ist eine sehr beliebte Technik zur Erstellung von Zuordnungen auf Pixelebene.
  • Sie ist einfach zu implementieren und hat eine gut gepflegte Python-Implementierung (siehe GitHub-Repository).
  • Der Algorithmus und die Umsetzung sind intuitiv und einfach zu erklären.
  • Es gibt eine große Auswahl an Visualisierungsmöglichkeiten.
  • Erklärungen sind spröde und möglicherweise nicht genau. Da LIME eine lokale Interpretation eines komplexen Modells ist, können Erklärungen bei stark nichtlinearen Modellen besonders schlecht sein.
  • LIME neigt dazu, Hintergrundregionen fälschlicherweise als einflussreich einzustufen.
  • Je nach Komplexität deines Modells kann die Erstellung von Erklärungen sehr langsam sein, da das Modell bei Störungen der Eingaben mehrfach abgefragt wird.

Aufgrund seines Alters ist LIME eine der beliebteren Erklärungsmethoden. Er kann auch für Tabellen- und Textdaten verwendet werden, und der Algorithmus ist für jede dieser Datenmodalitäten ähnlich, wenn auch mit einigen Modifikationen. Wir besprechen hier die Details der Implementierung von LIME mit Bildern, weil sie eine schöne visuelle Vorstellung davon vermitteln, wie LIME im Allgemeinen funktioniert (siehe Kapitel 5 für eine Diskussion darüber, wie LIME mit Text funktioniert).

So funktioniert LIME

LIME ist eine post hoc, modellunabhängige, störungsbasierte Erklärungsmethode. Das bedeutet, dass sie auf jedes maschinelle Lernmodell (z. B. neuronale Netze, SVM, Random Forest usw.) angewendet werden kann, nachdem das Modell trainiert worden ist. Im Wesentlichen behandelt LIME das trainierte Modell wie eine API, die ein Beispiel nimmt und einen Vorhersagewert erzeugt. Um zu erklären, warum das Modell eine bestimmte Vorhersage für eine bestimmte Eingabe trifft, gibt der LIME-Algorithmus viele leicht veränderte Beispiele der ursprünglichen Eingabe an das Modell weiter und misst dann, wie sich die Vorhersagen des Modells durch diese kleinen Änderungen der Eingabe verändern. Die Störungen erfolgen auf der Merkmalsebene der Eingabe, d. h. Bilder, Pixel und Pixelregionen werden verändert, um eine neue gestörte Eingabe zu erzeugen. Auf diese Weise werden die Pixel oder Pixelregionen, die den größten Einfluss auf die Vorhersage des Modells haben, als mehr oder weniger einflussreich für die Vorhersage des Modells für den jeweiligen Eingangsfall hervorgehoben.

Um ein wenig mehr ins Detail zu gehen, wollen wir zwei Schlüsselkomponenten der Implementierung von LIME näher erläutern: Erstens, wie man eine Störung eines Bildes erzeugt und zweitens, was es bedeutet, zu messen, wie sich die Modellvorhersage bei diesen Störungen verändert.

Für eine bestimmte Vorhersage wird das Eingangsbild in interpretierbare Komponenten oder Regionen des Bildes unterteilt. LIME unterteilt das Bild in Regionen, die Superpixel genannt werden. Ein Superpixel ist eine auf Ähnlichkeit basierende Gruppierung der einzelnen Pixel eines Bildes in ähnliche Komponenten (siehe die Diskussion des Algorithmus von Felzenszwalb im früheren Abschnitt "XRAI"). Abbildung 4-23 zeigt zum Beispiel, wie das Bild des Schwefelhaubenkakadus in Superpixel unterteilt werden kann. Die Superpixel-Regionen stellen die interpretierbaren Komponenten des Bildes dar.

Abbildung 4-23. Bei der Implementierung von LIME wird das Originalbild in Superpixel-Regionen segmentiert, die die interpretierbaren Komponenten des Bildes darstellen.

Die Superpixelregionen in Abbildung 4-23 wurden mit dem Quickshift-Segmentierungsalgorithmus aus der Bibliothek scikit-image erstellt. Dies ist der Standard-Segmentierungsalgorithmus, der in dem weit verbreiteten Open-Source-Python-Paket LIME verwendet wird (siehe den nächsten Abschnitt "Implementierung von LIME"). Quickshift basiert auf einer Annäherung an die kernelisierte Mittelwertverschiebung und berechnet die hierarchische Segmentierung auf mehreren Skalen gleichzeitig. Quickshift hat zwei Hauptparameter: Der Parameter sigma bestimmt die Skala der lokalen Dichteannäherung, und max_dist bestimmt die Ebene der hierarchischen Segmentierung. Außerdem gibt es einen Parameter ratio, der das Verhältnis zwischen dem Abstand im Farbraum und dem Abstand im Bildraum beim Vergleich der Ähnlichkeit von zwei Pixeln bestimmt. Der folgende Code erzeugt die Segmentierung in Abbildung 4-23. Das vollständige Codebeispiel findest du im LIME-Notebook im GitHub-Repository für dieses Buch:

from skimage.segmentation import quickshift

segments = quickshift(im_orig, kernel_size=4,
                      max_dist=200, ratio=0.2)

LIME stört dann diese interpretierbaren Komponenten, indem es die Werte der Pixel in jeder Superpixel-Region so verändert, dass sie grau sind. So entstehen mehrere neue Variationen oder Störungen des Eingangsbildes. Jede dieser neuen gestörten Instanzen wird dann an das Modell weitergegeben, um neue Vorhersagewerte für die Klasse zu generieren, die ursprünglich vorhergesagt wurde. In Abbildung 4-24 wird das Originalbild zum Beispiel durch das Ausgrauen bestimmter Superpixelbereiche verändert. Diese gestörten Beispiele werden dann an das trainierte Modell (in diesem Fall ein tiefes neuronales Netz) weitergegeben, und das Modell liefert die Wahrscheinlichkeit, dass das Bild einen Schwefelhaubenkakadu enthält. Diese neuen Vorhersagen bilden einen Datensatz, mit dem das lineare Modell von LIME trainiert wird, um festzustellen, wie viel jede interpretierbare Komponente zur ursprünglichen Vorhersage beiträgt.

Abbildung 4-24. Das Vertrauen des Modells in die vorhergesagte Klasse "Schwefelhaubenkakadu" für das Originalbild beträgt 0,833. Wenn bestimmte Superpixel entfernt werden (indem die Region ausgegraut wird), ändert sich die Vorhersage des Modells für die höchste Klasse. Bei einflussreichen Regionen ist die Veränderung größer als bei weniger wichtigen Regionen.

In der LIME-Implementierung werden Superpixel "ein-" oder "ausgeschaltet", indem die Pixelwerte eines Segments auf grau gesetzt werden. So entsteht eine Sammlung von gestörten Bildern, die dem Modell zur Vorhersage übergeben werden. Es ist auch möglich, die Superpixelregionen in den Mittelwert der einzelnen Pixelwerte in der Superpixelregion zu ändern, wie in Abbildung 4-25 dargestellt.

Abbildung 4-25. Es ist auch möglich, Bilder zu stören, indem man die Werte der Superpixelregionen so einstellt, dass sie dem Durchschnitt der einzelnen Pixelregionen im Bild entsprechen.

Jetzt wollen wir besprechen, wie LIME die Beiträge der Superpixelmerkmale quantitativ misst. Dazu wird ein kleineres, interpretierbares Modell trainiert, das Erklärungen für das ursprüngliche Modell liefert. Dieses kleinere Modell kann alles Mögliche sein, aber der wichtige Aspekt ist, dass es von sich aus interpretierbar ist. In der Originalarbeit,7 verwenden die Autoren das Beispiel eines linearen Modells. Lineare Modelle sind von Natur aus interpretierbar, weil die Gewichtung jedes Merkmals direkt anzeigt, wie wichtig dieses Merkmal für die Vorhersage des Modells ist.

Dieses interpretierbare, lineare Modell wird dann auf einem Datensatz trainiert, der aus den gestörten Beispielen und den Vorhersagen des ursprünglichen Modells besteht, wie in Abbildung 4-24 dargestellt. Diese Störungen sind eigentlich nur einfache binäre Darstellungen des Bildes, die das "Vorhandensein" oder "Nichtvorhandensein" der einzelnen Superpixelbereiche anzeigen. Da wir uns für die Störungen interessieren, die dem Originalbild am nächsten kommen, werden die Beispiele mit den meisten vorhandenen Superpixeln stärker gewichtet als die Beispiele mit den meisten fehlenden Superpixeln. Diese Nähe kann mit einer beliebigen Distanzmetrik für Bilder gemessen werden. Der Gedanke dahinter ist, dass auch ein hochkomplexes Modell, wie z. B. ein tiefes neuronales Netz oder ein SVM, mit einem lokal gewichteten, linearen Modell das lokale Verhalten bei einer bestimmten Eingangsinstanz erfassen kann. Je empfindlicher das komplexe Modell auf ein bestimmtes Eingangsmerkmal reagiert, desto mehr Einfluss hat dieses Merkmal auch auf das lineare, interpretierbare Modell.

LIME einführen

Es gibt ein schönes, benutzerfreundliches Python-Paket für die Anwendung von LIME auf Tabellen-, Bild- und Textklassifikatoren, das unter für jeden Klassifikator mit mindestens zwei Labelklassen funktioniert. Sehen wir uns als Beispiel an, wie man LIME auf das Inception v3 Bildklassifizierungsmodell anwendet. Der folgende Code zeigt, wie wir das Bild in TensorFlow laden und eine Vorhersage für ein Bild treffen. Wenn wir das Inception-Modell laden, geben wir include_top=True an, um die letzte Vorhersageschicht des Modells zu erhalten, und setzen weights='imagenet', um die auf dem ImageNet-Datensatz vortrainierten Gewichte zu erhalten:

inception = tf.keras.applications.InceptionV3(
    include_top=True, weights='imagenet')
model = tf.keras.models.Model(inception.inputs, inception.output)

Jetzt können wir anhand eines Bildes Erklärungen für die Vorhersage des Inception-Modells erstellen, indem wir ein LimeImageExplainer Objekt erstellen und dann die Methode explain_instance aufrufen. Der folgende Codeblock zeigt, wie das geht:

explainer = lime_image.LimeImageExplainer()
explanation = explainer.explain_instance(image.astype('double'),
                                         inception.predict,
                                         top_labels=20,
                                         hide_color=0,
                                         num_features=5)

Die meisten der Parameter in diesem Codeblock sind selbsterklärend. Die letzten beiden sind jedoch erwähnenswert. Erstens gibt der Parameter hide_color an, dass wir die Superpixel-Regionen ausschalten und durch graue Pixel ersetzen werden. Der Parameter num_features gibt an, wie viele Merkmale für die Erklärung verwendet werden sollen. Weniger Merkmale führen zu einfacheren, verständlichen Erklärungen. Bei komplexeren Modellen kann es jedoch notwendig sein, diesen Wert groß zu halten (die Standardeinstellung ist num_features=100000).

Um die Erklärungen für dieses Beispiel zu visualisieren, rufen wir anschließend get_image_and_mask für die resultierende Erklärung auf. Dies wird im folgenden Codeblock gezeigt; den vollständigen Code für dieses Beispiel findest du im LIME-Notizbuch im Buch-Repository:

temp, mask = explanation.get_image_and_mask(explanation.top_labels[0],
                                            positive_only=True,
                                            num_features=20,
                                            hide_rest=True)
plt.imshow(mark_boundaries(temp, mask))
plt.show()

Das Ergebnis ist in Abbildung 4-26 zu sehen, die die Superpixel-Regionen hervorhebt, die am positivsten zur Vorhersage "Schwefelhaubenkakadu" beigetragen haben.

Abbildung 4-26. LIME verwendet ein lineares Modell, das auf Störungen des ursprünglichen Eingangsbildes trainiert wurde, um festzustellen, welche Superpixelregionen den größten Einfluss auf die Vorhersage des komplexen Modells haben.

Es ist auch möglich zu sehen, welche Superpixel-Regionen einen negativen Beitrag leisten. Dazu setzt du positive_only auf False. Das Ergebnis ist das in Abbildung 4-27 gezeigte Bild. Die Regionen, die positiv zur Vorhersage beitragen, sind grün dargestellt, während die Regionen, die die Vorhersage negativ beeinflussen, rot dargestellt sind.

Abbildung 4-27. Eine LIME-Erklärung. Die Regionen, die das Modell beeinflusst haben, werden als Heatmap dargestellt, wobei einflussreichere Regionen eine dunklere Farbe haben, wobei Grün positiv zur Klassifizierung beiträgt und Rot negativ. (Printleser können das Farbbild unter https://oreil.ly/xai-fig-4-27 sehen .)

Das Ergebnis ist eine segmentierte Karte des Bildes, die danach gewichtet ist, wie stark diese Region die Vorhersage des Modells beeinflusst hat. Anders als bei den Shapley-Werten gibt es keine Grenzen oder Garantien für die Werte der Region. So ist es zum Beispiel denkbar, dass LIME mehrere Regionen als besonders einflussreich gewichtet.

Leider ist die Eleganz von LIME, Gewichtungen durch das Ein- und Ausschalten von Bildbereichen zu erzeugen, auch sein Nachteil. Da durch die gestörten Bilder ganze Bereiche aus der Vorhersage entfernt werden, verlagert sich die Aufmerksamkeit des Modells auf das, was im Bild sichtbar bleibt. LIME bittet das Modell also nicht um eine "eingeschränkte" Vorhersage des Originalbildes, sondern um die Betrachtung eines völlig neuen Bildes. Da jedoch nicht das gesamte Bild gestört wird, wie bei Integrated Gradients, ist es möglich, dass gelernte Konzepte im Modell nicht mehr aktiviert werden. Wir bitten das Modell, uns zu sagen, wie es das Bild vorhersagen würde, indem wir uns ansehen, wie sich die Vorhersagen nur in Bezug auf einen Merkmalswert ändern, und davon ausgehen, dass ein Vergleich zwischen verschiedenen Merkmalen zu etwas Ähnlichem führt wie die ursprüngliche Vorhersage des Modells. Das kann manchmal zu unsinnigen Erklärungen führen, wie in Abbildung 4-28 zu sehen ist.

Abbildung 4-28. Ein Beispiel dafür, wie der Störungsansatz von LIME zu scheinbar unsinnigen Erklärungen führen kann. Auf dem Bild des Stieglitzes trägt ein großer Teil des Hintergrunds (fast so viel wie der Vogel selbst) zur Vorhersage bei. Auf dem Bild des Kakadus sehen wir ebenfalls, dass der Hintergrund einen positiven Einfluss auf das Modell hat, während Teile des Vogels auch einen negativen Einfluss haben. (Printleser können das Farbbild unter https://oreil.ly/xai-fig-4-28 sehen .)

Eine Möglichkeit, dieses Problem zu lösen, besteht darin, die Parameter des Segmentierungsschritts anzupassen: Je feinkörniger die Segmente sind, desto geringer ist die Wahrscheinlichkeit, dass diese Superpixel zur Bildvorhersage beitragen. Letztlich ist es wie bei allen Implementierungen wichtig, sich dieses Artefakts bewusst zu sein, sowohl bei der Implementierung der LIME-Technik als auch bei der Interpretation der Ergebnisse.

Als weiteres Beispiel haben wir LIME auf einen nicht natürlichen Datensatz angewendet, den PlantVillage-Datensatz, der Bilder von Pflanzenblättern mit Krankheiten enthält und versucht, die Art der Krankheit vorherzusagen. Diese Bilder sind eine Kombination aus einem sehr natürlichen Bild (Pflanzenblätter) und einer viel strukturierteren Umgebung (Innenbeleuchtung, monochromer Hintergrund). Das verwendete Modell, Schuler, war mit einer Gesamtvorhersagegenauigkeit von 99,8 % sehr genau. Wir haben die LIME-Erklärungen auch mit einem anderen, etwas weniger genauen Modell, Yosuke, verglichen.

Abbildung 4-29. Beispiele für die Verwendung von LIME, um die Klassifizierung zwischen zwei verschiedenen Modellen zu erklären. (Printleser können das Farbbild unter https://oreil.ly/xai-fig-4-29 sehen .)

Wie du in den Beispielen in Abbildung 4-29 sehen kannst, hat LIME festgestellt, dass die Hintergründe der Bilder zu den einflussreichsten Bereichen bei der Vorhersage gehören. Da der Hintergrund für alle Bilder im Datensatz gleich ist, scheint es sehr unwahrscheinlich, dass dies die Ursache für die Vorhersagen ist!

Geführte Backpropagation und geführte Grad-CAM

Hier erfährst du, was du über Guided Backprop (oft so abgekürzt) und Guided Grad-CAM wissen musst:

  • Guided Backprop baut auf DeConvNets auf, das die inneren Schichten eines Faltungsnetzes untersucht.

  • Guided Backprop entspricht der Gradientenerklärung, bei der negative Gradienteneinträge auf Null gesetzt werden, während Backpropagation durch eine ReLU-Einheit erfolgt.

  • Guided Grad-CAM kombiniert die Ausgabe von Grad-CAM und Guided Backprop durch ein elementweises Produkt, um schärfere Visualisierungen in den Saliency Maps zu erzeugen.

Profis Nachteile
  • Guided Backprop sorgt für eine schärfere und feinkörnigere Visualisierung der Saliency Attribution Maps.
  • Geführte Grad-CAM-Salienzkarten lokalisieren relevante Regionen, heben aber auch feinkörnige Pixeldetails hervor.
  • Einiges deutet darauf hin, dass Guided Backprop und seine Varianten bei grundlegenden "Sanity"-Prüfungen fehlschlagen und nur eine minimale Empfindlichkeit gegenüber Tests zur Randomisierung von Modellparametern und Daten aufweisen.a

a Julius Adebayo et al., "Sanity Checks for Saliency Maps", arXiv, 2020, https://arxiv.org/pdf/1810.03292.pdf.

Wie wir in diesem Kapitel gesehen haben, sind die Gradienten eines neuronalen Netzwerks ein nützliches Werkzeug, um zu messen, wie sich Informationen in einem Modell ausbreiten, um schließlich eine Vorhersage zu erstellen. Die Idee dahinter ist, dass du durch die Messung der Gradienten durch Backpropagation die Pixel oder Pixelbereiche hervorheben kannst, die am meisten zur Entscheidung des Modells beigetragen haben. Trotz dieses intuitiven Ansatzes können die Ergebnisse von Saliency Maps, die sich ausschließlich auf Gradienteninformationen stützen, in der Praxis sehr verrauscht und schwer zu interpretieren sein. Guided Backprop stützt sich ebenfalls auf die Modellgradienten, um eine Saliency Map zu erstellen, ändert aber den Backpropagation-Schritt leicht, um die ReLU-Nichtlinearitäten zu behandeln.

Geführter Backprop und DeConvNets

Die Technik des Guided Backprop ist eng verwandt mit einer früheren Erklärungsmethode namens DeConvNets. Wir werden zunächst beschreiben, wie DeConvNets funktionieren, und dann sehen, wie Guided Backprop diesen Ansatz verbessert. Wie der Name schon sagt, basieren DeConvNets auf Dekonvolutionsebenen, auch bekannt als transponierte Faltungen. Du kannst dir eine Dekonvolution als Umkehrung einer Faltungsschicht vorstellen, ihre Aufgabe ist es, die Operation einer Faltungsschicht "rückgängig" zu machen. Abbildung 4-30 zeigt die typische Architektur eines DeConvNet.

Abbildung 4-30. Ein typisches Entfaltungsnetzwerk mit einem VGG-16-Backbone. Die Architektur des DeConvNet beginnt mit den üblichen Faltungsund Max-Pooling-Schichten, gefolgt von Dekonvolution- und Unpooling-Schichten.

Wie du in der Abbildung sehen kannst, beginnt die DeConvNet-Architektur mit einem gewöhnlichen Faltungsnetzwerk. Jede Faltungsschicht lässt einen Kernel über die Eingangskanäle laufen und berechnet eine Ausgabe, die auf den Gewichten des Filters basiert. Die Größe der Ausgabe einer Faltungsschicht wird durch die Kernelgröße, das Padding und den Stride bestimmt. Wenn du zum Beispiel einen Eingangstensor mit der Form (5,5) und eine Faltungsschicht mit der Kernelgröße 3×3, einem Stride von 2 und einem Padding von Null hast, ist die Ausgabe ein Tensor mit der Form (2,2), wie links in Abbildung 4-31 dargestellt. Die neun Werte des Basis-Tensors (5,5) werden als Linearkombination zusammengefasst, um den einzelnen Wert des resultierenden (2,2)-Tensors zu erhalten. Wenn die Eingabe mehrere Kanäle hat, wird die Faltung auf jeden Kanal angewendet.

Der zweite Teil des DeConvNet sind die Dekonvolutionsschichten (oder transponierten Faltungsschichten). DeConvNets ähneln Faltungsnetzen, arbeiten aber in umgekehrter Weise (Umkehrung der Filter, Umkehrung des Poolings usw.), sodass sie die räumliche Auflösung des ursprünglichen Eingangstensors rekonstruieren. Das DeConvNet besteht aus zwei Komponenten: der Dekonvolution und der Unpooling-Schicht. Wir besprechen zuerst, wie die Entfaltungsschichten funktionieren. Die Entfaltung verwendet ebenfalls einen Faltungsfilter, erzwingt aber eine zusätzliche Auffüllung sowohl außerhalb als auch innerhalb der Eingabewerte, um den Tensor mit einer größeren Form zu rekonstruieren. Bei dem gerade beschriebenen Faltungsschritt wird der (2,2)-Tensor durch die Entfaltung auf einen Tensor der Form (5,5) zurückgeführt, wie im Bild rechts in Abbildung 4-31 dargestellt. Der Entfaltungsfilter hat die Größe 3×3. Um den (2,2)-Tensor in einen Tensor der Form (5,5) umzuwandeln, fügen wir an den Außenseiten und zwischen den Eingabewerten zusätzliche Füllungen hinzu (in Abbildung 4-31 rot).

Abbildung 4-31. Eine Entfaltungsschicht (rechts) rekonstruiert die ursprüngliche räumliche Auflösung der Eingabe für eine Faltungsschicht (links).

Die nächste zu besprechende Komponente des DeConvNet sind die Unpooling-Schichten. Die Max-Pooling-Schichten eines Faltungsnetzes lassen einen Filter über die Eingabe laufen und nehmen nur das Maximum aller Werte im Filter als Ausgabe auf. Bei der Maximalverdichtung gehen naturgemäß viele Informationen verloren. Um das Unpooling durchzuführen, müssen wir uns an die Position erinnern, an der der Maximalwert im ursprünglichen Max-Pooling-Filter aufgetreten ist. Diese Stellen werden als Switch-Variablen bezeichnet. Beim Unpooling setzen wir den Maximalwert aus dem Max-Pooling wieder an seine ursprüngliche Position und lassen die restlichen Werte im Filter auf Null stehen, wie in Abbildung 4-32 dargestellt.

Abbildung 4-32. Wenn du eine Max-Pooling-Ebene mit "Unpooling" umkehrst, merkt sich die Switch-Variable, wo der Max-Wert lag.

Die Idee bei der Verwendung von DeConvNets als Erklärungsmethode ist es, die internen Aktivierungsschichten eines trainierten CNN zu visualisieren, indem die Faltungsblöcke eines CNN mit Hilfe von Entfaltungsschichten Block für Block "rückgängig" gemacht werden. Letztendlich bildet das DeConvNet den Filter einer Aktivierungsschicht auf den ursprünglichen Bildraum ab und ermöglicht es dir, Muster in den Bildern zu finden, die eine hohe Filteraktivierung verursacht haben.

Durch die Anwendung von Faltung und Max-Pooling gehen einige Informationen des ursprünglichen Eingangstensors verloren. Das liegt daran, dass der Faltungsfilter Werte aggregiert und das Max-Pooling nur einen Wert aus dem gesamten Filter zurückgibt und den Rest fallen lässt. Die Entfaltung macht den Faltungsschritt rückgängig, aber sie ist eine unvollkommene Rekonstruktion des ursprünglichen Tensors.

Die Methode der Guided Backpropagation ist ähnlich wie bei DeConvNets. Der Unterschied liegt darin, wie Guided Backprop die Backpropagation des Gradienten durch die ReLU-Aktivierungsfunktionen handhabt. Ein DeConvNet überträgt nur positive Signale zurück, d.h. es setzt alle negativen Signale aus dem Rückwärtsdurchlauf auf Null. Die Idee dahinter ist, dass wir nur an den Bildmerkmalen interessiert sind, die eine Aktivierungsschicht erkennt, und nicht am Rest, also konzentrieren wir uns nur auf positive Werte. Dazu wird der Backward Pass mit einer binären Maske multipliziert, so dass nur positive Werte erhalten bleiben. Beim Guided Backprop beschränkst du ebenfalls nur die positiven Werte der Eingabe auf eine Schicht. Es wird also eine binäre Maske sowohl für den Backward Pass als auch für den Forward Pass angewendet. Das bedeutet, dass es mehr Nullwerte in der endgültigen Ausgabe gibt, aber es führt zu schärferen Saliency Maps und feinkörnigeren Visualisierungen.

Der Name "Guided" weist darauf hin, dass bei dieser Methode zusätzlich zu den Informationen aus dem Rückwärtsdurchlauf auch Informationen aus dem Vorwärtsdurchlauf verwendet werden, um eine Salienzkarte zu erstellen. Die Informationen aus dem Vorwärtsdurchlauf helfen dabei, die Entfaltung zu steuern. Dies ist ähnlich wie der Unterschied zwischen Guided Integrated Gradients und Vanilla Integrated Gradients, bei dem Informationen über die Basislinie und die Eingabe verwendet werden, um den Pfad bei der Berechnung eines Linienintegrals zu bestimmen.

Geführte Grad-CAM

Guided Grad-CAM kombiniert das Beste von Grad-CAM und Guided Backprop. Wie wir im Abschnitt über Grad-CAM gesehen haben, besteht eines der Probleme bei Grad-CAM darin, dass die grobe Heatmap, die von den Aktivierungsschichten erzeugt wird, hochgerechnet werden muss, damit sie mit dem ursprünglichen Eingangsbild verglichen werden kann. Dieses Upsampling und die anschließende Glättung führen zu einer niedriger aufgelösten Heatmap. Die ursprünglichen Autoren von Grad-CAM haben Guided Grad-CAM vorgeschlagen, um die hochauflösende Ausgabe von Guided Backprop mit den klassenspezifischen Gradienteninformationen von Grad-CAM zu kombinieren. Damit sind zwar nicht alle Probleme von Grad-CAM gelöst, da es sich immer noch auf die Ergebnisse der Grad-CAM-Technik stützt, die einige grundsätzliche Probleme aufweist (siehe "Grad-CAM" für eine ausführlichere Diskussion darüber), aber es ist eine Verbesserung. Guided Grad-CAM kombiniert Grad-CAM und Guided Backprop, indem es ein elementweises Produkt aus beiden Ergebnissen bildet, wie in Abbildung 4-33 dargestellt.

Abbildung 4-33. Guided Grad-CAM kombiniert die Ergebnisse von Grad-CAM und Guided Backpropagation, indem es das elementweise Produkt bildet. So entsteht eine Visualisierung.

Sowohl für Guided Backprop als auch für Guided Grad-CAM gibt es benutzerfreundliche Implementierungen in der Captum-Bibliothek. Schauen wir uns ein Beispiel an, um zu sehen, wie diese Techniken in Code umgesetzt werden. Captum basiert auf PyTorch, also laden wir zunächst ein Inception v3-Modell, das auf dem ImageNet-Datensatz trainiert worden ist. Dies geschieht im folgenden Codeblock (den vollständigen Code für diese Beispiele findest du im Guided Backprop Notebook im GitHub-Repository dieses Buches):

import torch
model = torch.hub.load('pytorch/vision:v0.10.0',
                       'inception_v3',
                       pretrained=True)
model.eval()

In diesem Codeblock teilt model.eval() PyTorch mit, dass wir das Modell für Inferenzen (d.h. für die Auswertung) und nicht für das Training verwenden. Um mit Guided Backprop Attributionen zu erstellen, sind nur ein paar Codezeilen erforderlich. Zuerst erstellen wir unser GuidedBackProp Attributionsobjekt, indem wir das zuvor erstellte Inception-Modell übergeben. Dann rufen wir die Methode attribute auf und übergeben das Eingabebeispiel (als Stapel) und die Zielklassen-ID, für die wir Erklärungen erstellen wollen. Hier stellen wir target=top5_catid[0] so ein, dass die am besten vorhergesagte Klasse für das gegebene Eingabebild verwendet wird, wie im folgenden Codeblock gezeigt :

gbp = GuidedBackprop(model)
# Computes Guided Backprop attribution scores for class 89 (cockatoo)
gbp_attribution = gbp.attribute(input_batch, target=top5_catid[0])

Das Ergebnis ist eine Attributionsmaske, die wir dann mit der Captum-Visualisierungsbibliothek visualisieren können. Das Ergebnis ist in Abbildung 4-34 dargestellt.

Abbildung 4-34. Guided Grad-CAM kombiniert die Ergebnisse von Grad-CAM und Guided Backprop, indem es ein elementweises Produkt aus den Ergebnissen der beiden Methoden bildet.

Du kannst Grad-CAM mit der Captum-Bibliothek auf ganz ähnliche Weise implementieren. Erinnere dich: Grad-CAM erstellt eine grobe Heatmap aus den internen Aktivierungsschichten des CNN-Modells. Diese internen Aktivierungen können von jeder der Faltungsschichten des Modells stammen. Wenn du Grad-CAM implementierst, gibst du also an, welche Faltungsschicht für die Erstellung der Heatmap verwendet werden soll. Bei Guided Grad-CAM gibst du ebenfalls an, welche Schicht des Modells verwendet werden soll. Das wird im folgenden Codeblock gezeigt. Bei der Erstellung des GuidedGradCam Objekts übergeben wir das Modell sowie den Layer model.Mixed_7c; dies ist der letzte Faltungslayer des Inception v3 Modells:

from captum.attr import GuidedGradCam

guided_gc = GuidedGradCam(model, model.Mixed_7c)
ggc_attribution = guided_gc.attribute(
input_batch, target=top5_catid[0])

Sobald wir die Zuordnungen haben, können wir das Ergebnis mit der Captum-Visualisierungsbibliothek wie zuvor visualisieren. Den vollständigen Code für dieses Beispiel findest du im Guided Backprop-Notizbuch im GitHub-Repository.

Zusammenfassung

Computer-Vision-Modelle sind in vielen Bereichen von entscheidender Bedeutung, von der Gesundheitsfürsorge und Sicherheit bis hin zu Produktion und Landwirtschaft. Die Erklärbarkeit ist wichtig, um die Vorhersagen eines Modells zu überprüfen und sicherzustellen, dass ein Modell keine falschen Korrelationen in den Daten lernt. In diesem Kapitel haben wir uns verschiedene Erklärungsmethoden angesehen, die bei der Arbeit mit Bilddaten verwendet werden.

Grob gesagt lassen sich die Erklärungs- und Zuordnungsmethoden für Computer-Vision-Modelle in ein paar grobe Kategorien einteilen: Backpropagation-Methoden, Störungsmethoden, Methoden, die den internen Zustand des Modells nutzen, und Methoden, die verschiedene Ansätze kombinieren. Die Erklärungsmethoden, die wir in diesem Kapitel besprochen haben, sind repräsentative Beispiele für diese Kategorien, und jede Methode hat ihre eigenen Vor- und Nachteile.

Integrated Gradients und seine vielen Variationen fallen in die Kategorie der Backpropagationstechniken. XRAI kombiniert Integrated Gradients mit segmentierungsbasierter Maskierung, um die Bildbereiche zu bestimmen, die für die Vorhersage des Modells am wichtigsten sind. Durch die Übersegmentierung des Bildes und die Zusammenfassung kleinerer wichtiger Regionen zu größeren Regionen auf der Basis von Attributionswerten entstehen so besser verwertbare Saliency Maps als bei der alleinigen Verwendung von Integrated Gradients auf Pixelebene. Methoden wie Grad-CAM und Grad-CAM++ basieren ebenfalls auf Gradienten, aber sie nutzen den internen Zustand des Modells. Genauer gesagt nutzt Grad-CAM die Klassenaktivierungskarten der internen Faltungsschichten des Modells, um eine Heatmap der einflussreichen Regionen für ein Eingabebild zu erstellen.

LIME ist ein modellunabhängiger Ansatz, der das Modell als undurchsichtig behandelt und die Pixel bestimmt, die für die Vorhersage des Modells relevant sind, indem die Werte der Eingangspixel gestört werden. Diese Methoden verwenden Gradienten des Modells, um Saliency Maps (auch Sensitivity Maps oder Pixel Attribution Maps genannt) zu erstellen, die Regionen eines Bildes darstellen, die für die endgültige Klassifizierung des Modells besonders wichtig sind. Zuletzt haben wir Guided Backpropagation und Guided Grad-CAM besprochen, die verschiedene Ansätze miteinander kombinieren. Guided Grad-CAM kombiniert Guided Backprop und Grad-CAM unter Verwendung eines elementweisen Produkts, um das Beste aus beiden Methoden herauszuholen und einige der Probleme zu lösen, die bei der Verwendung von Grad-CAM auftreten.

Im nächsten Kapitel werden wir uns mit Erklärungsmethoden befassen, die üblicherweise für textbasierte Modelle verwendet werden, und wie einige der Techniken, die wir bereits kennengelernt haben, für den Bereich der natürlichen Sprache angepasst werden können.

1 Dies ist analog zu vielen verlustbasierten Funktionen für das Training von DNNs, die den Gradienten und die Leistungsänderung des Modells im Verlustraum messen.

2 Mukun Sundararajan et al., "Axiomatic Attribution for Deep Networks", Proceedings of the 34th International Conference on Machine Learning, PMLR 70 (2017).

3 Pedro F. Felzenszwalb und Daniel P. Huttenlocher, "Efficient Graph-Based Image Segmentation", International Journal of Computer Vision 59.2 (2004): 167-81.

4 Ramprasaath R. Selvaraju et al., "Grad-CAM: Visual Explanations from Deep Networks via Gradient-Based Localization", Computer Vision Foundation, https://oreil.ly/cU9sG.

5 Das Grad-CAM-Papier wurde im Jahr 2019 überarbeitet und aktualisiert.

6 Die Befürworter von Grad-CAM behaupten, dass diese Hochskalierung akzeptabel ist, weil sie das Downsampling der CNNs des Modells widerspiegelt, aber für dieses Argument gibt es keine solide theoretische Grundlage oder Bewertungen, die diese Behauptung belegen.

7 Marco Tulio Ribeiro et al., "'Why Should I Trust You?' Explaining the Predictions of Any Classifier," Proceedings of the 22nd SIGKDD International Conference on Knowledge Discovery and Data Mining (August 2016).

Get Erklärbare KI für Praktiker now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.