Zintegrowane gradienty

Zobacz na TensorFlow.org Uruchom w Google Colab Zobacz na GitHub Pobierz notatnik Zobacz model piasty TF

Ten samouczek pokazuje, jak zaimplementować Integrated Gradients (IG) , technikę Explainable AI przedstawioną w artykule Axiomatic Attribution for Deep Networks . IG ma na celu wyjaśnienie związku między przewidywaniami modelu w zakresie jego cech. Ma wiele przypadków użycia, w tym zrozumienie ważności funkcji, identyfikowanie skosu danych i debugowanie wydajności modelu.

IG stał się popularną techniką interpretacji ze względu na jej szerokie zastosowanie do dowolnego modelu różnicującego (np. obrazów, tekstu, danych strukturalnych), łatwość implementacji, uzasadnienia teoretyczne i wydajność obliczeniową w porównaniu z alternatywnymi podejściami, które pozwalają na skalowanie do dużych sieci i funkcji przestrzenie, takie jak obrazy.

W tym samouczku przejdziesz krok po kroku przez implementację IG, aby zrozumieć znaczenie funkcji pikseli w klasyfikatorze obrazu. Jako przykład rozważmy ten obraz łodzi strażackiej rozpylającej strumienie wody. Sklasyfikowałbyś ten obraz jako łódź strażacką i mógłbyś wyróżnić piksele tworzące łódź i armatki wodne jako ważne dla Twojej decyzji. Twój model również zaklasyfikuje ten obraz jako łódź strażacką w dalszej części tego samouczka; jednak czy podkreśla te same piksele jako ważne przy wyjaśnianiu swojej decyzji?

Na poniższych obrazach zatytułowanych „Ig Attribution Mask” i „Oryginalna + IG Mask Overlay” widać, że model zamiast tego podświetla (na fioletowo) piksele składające się na armatki wodne i strumienie wody jako ważniejsze niż sama łódź swoją decyzję. W jaki sposób Twój model uogólni się na nowe łodzie strażackie? A co z łodziami strażackimi bez dysz wodnych? Czytaj dalej, aby dowiedzieć się więcej o tym, jak działa IG i jak zastosować IG w swoich modelach, aby lepiej zrozumieć związek między ich przewidywaniami a podstawowymi funkcjami.

Obraz wyjściowy 1

Ustawiać

import matplotlib.pylab as plt
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub

Pobierz przeszkolony klasyfikator obrazów z TF-Hub

IG można zastosować do dowolnego modelu różniczkowego. Zgodnie z duchem oryginalnego artykułu, użyjesz wstępnie wytrenowanej wersji tego samego modelu, Inception V1, którą pobierzesz z TensorFlow Hub .

model = tf.keras.Sequential([
    hub.KerasLayer(
        name='inception_v1',
        handle='https://tfhub.dev/google/imagenet/inception_v1/classification/4',
        trainable=False),
])
model.build([None, 224, 224, 3])
model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 inception_v1 (KerasLayer)   (None, 1001)              6633209   
                                                                 
=================================================================
Total params: 6,633,209
Trainable params: 0
Non-trainable params: 6,633,209
_________________________________________________________________

Ze strony modułu należy pamiętać o następujących kwestiach dotyczących Incepcji V1:

Dane wejściowe : Oczekiwany kształt wejściowy dla modelu to (None, 224, 224, 3) . Jest to gęsty tensor 4D typu dtype float32 i shape (batch_size, height, width, RGB channels) którego elementami są wartości kolorów RGB pikseli znormalizowanych do zakresu [0, 1]. Pierwszym elementem jest None , aby wskazać, że model może przyjmować dowolną całkowitą wielkość partii.

Dane wyjściowe : tf.Tensor logit w kształcie (batch_size, 1001) . Każdy wiersz reprezentuje przewidywany wynik modelu dla każdej z 1001 klas z ImageNet. Dla najwyższego przewidywanego indeksu klasy modelu można użyć tf.argmax(predictions, axis=-1) . Co więcej, można również przekonwertować wynik logitowy modelu na przewidywane prawdopodobieństwa we wszystkich klasach, używając tf.nn.softmax(predictions, axis=-1) w celu ilościowego określenia niepewności modelu, a także zbadania podobnych przewidywanych klas w celu debugowania.

def load_imagenet_labels(file_path):
  labels_file = tf.keras.utils.get_file('ImageNetLabels.txt', file_path)
  with open(labels_file) as reader:
    f = reader.read()
    labels = f.splitlines()
  return np.array(labels)
imagenet_labels = load_imagenet_labels('https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')

Załaduj i wstępnie przetwórz obrazy za pomocą tf.image

Zilustrujesz IG za pomocą dwóch obrazów z Wikimedia Commons : Fireboat i Giant Panda .

def read_image(file_name):
  image = tf.io.read_file(file_name)
  image = tf.io.decode_jpeg(image, channels=3)
  image = tf.image.convert_image_dtype(image, tf.float32)
  image = tf.image.resize_with_pad(image, target_height=224, target_width=224)
  return image
img_url = {
    'Fireboat': 'http://storage.googleapis.com/download.tensorflow.org/example_images/San_Francisco_fireboat_showing_off.jpg',
    'Giant Panda': 'http://storage.googleapis.com/download.tensorflow.org/example_images/Giant_Panda_2.jpeg',
}

img_paths = {name: tf.keras.utils.get_file(name, url) for (name, url) in img_url.items()}
img_name_tensors = {name: read_image(img_path) for (name, img_path) in img_paths.items()}
Downloading data from http://storage.googleapis.com/download.tensorflow.org/example_images/San_Francisco_fireboat_showing_off.jpg
3956736/3954129 [==============================] - 0s 0us/step
3964928/3954129 [==============================] - 0s 0us/step
Downloading data from http://storage.googleapis.com/download.tensorflow.org/example_images/Giant_Panda_2.jpeg
811008/802859 [==============================] - 0s 0us/step
819200/802859 [==============================] - 0s 0us/step
plt.figure(figsize=(8, 8))
for n, (name, img_tensors) in enumerate(img_name_tensors.items()):
  ax = plt.subplot(1, 2, n+1)
  ax.imshow(img_tensors)
  ax.set_title(name)
  ax.axis('off')
plt.tight_layout()

png

Klasyfikuj obrazy

Zacznijmy od sklasyfikowania tych obrazów i wyświetlenia trzech najbardziej wiarygodnych prognoz. Poniżej znajduje się funkcja narzędziowa do pobierania k najpopularniejszych przewidywanych etykiet i prawdopodobieństw.

def top_k_predictions(img, k=3):
  image_batch = tf.expand_dims(img, 0)
  predictions = model(image_batch)
  probs = tf.nn.softmax(predictions, axis=-1)
  top_probs, top_idxs = tf.math.top_k(input=probs, k=k)
  top_labels = imagenet_labels[tuple(top_idxs)]
  return top_labels, top_probs[0]
for (name, img_tensor) in img_name_tensors.items():
  plt.imshow(img_tensor)
  plt.title(name, fontweight='bold')
  plt.axis('off')
  plt.show()

  pred_label, pred_prob = top_k_predictions(img_tensor)
  for label, prob in zip(pred_label, pred_prob):
    print(f'{label}: {prob:0.1%}')

png

fireboat: 32.6%
pier: 12.7%
suspension bridge: 5.7%

png

giant panda: 89.4%
teddy: 0.3%
gibbon: 0.3%

Oblicz zintegrowane gradienty

Twój model, Incepcja V1, to wyuczona funkcja, która opisuje mapowanie między wejściową przestrzenią cech, wartościami pikseli obrazu i przestrzenią wyjściową zdefiniowaną przez wartości prawdopodobieństwa klasy ImageNet z zakresu od 0 do 1. gradienty, które informują, które piksele mają najbardziej strome lokalne względem przewidywania modelu w danym punkcie wzdłuż funkcji przewidywania modelu. Jednak gradienty opisują tylko lokalne zmiany w funkcji przewidywania modelu w odniesieniu do wartości pikseli i nie opisują w pełni funkcji przewidywania całego modelu. Gdy twój model w pełni „nauczy się” relacji między zakresem pojedynczego piksela a właściwą klasą ImageNet, gradient dla tego piksela będzie się nasycał , co oznacza, że ​​będzie coraz mniejszy, a nawet spadnie do zera. Rozważ prostą funkcję modelu poniżej:

def f(x):
  """A simplified model function."""
  return tf.where(x < 0.8, x, 0.8)

def interpolated_path(x):
  """A straight line path."""
  return tf.zeros_like(x)

x = tf.linspace(start=0.0, stop=1.0, num=6)
y = f(x)

png

  • po lewej : Gradienty Twojego modelu dla piksela x są dodatnie w zakresie od 0,0 do 0,8, ale osiągają wartość 0,0 w zakresie od 0,8 do 1,0. Pixel x wyraźnie ma znaczący wpływ na przesuwanie modelu w kierunku 80% przewidywanego prawdopodobieństwa w prawdziwej klasie. Czy to ma sens, że znaczenie piksela x jest małe lub nieciągłe?

  • po prawej : intuicja stojąca za IG polega na akumulowaniu lokalnych gradientów piksela x i przypisywaniu ich znaczenia jako punktacji za to, ile dodaje lub odejmuje do ogólnego prawdopodobieństwa klasy wyjściowej modelu. Możesz podzielić i obliczyć IG na 3 części:

    1. interpolować małe kroki wzdłuż linii prostej w przestrzeni funkcji między 0 (linia bazowa lub punkt początkowy) a 1 (wartość wejściowa piksela)
    2. oblicz gradienty na każdym kroku między przewidywaniami modelu w odniesieniu do każdego kroku
    3. przybliżyć całkę między linią bazową a danymi wejściowymi, gromadząc (skumulowaną średnią) te lokalne gradienty.

Aby wzmocnić tę intuicję, przejdziesz przez te 3 części, stosując IG do przykładowego obrazu „Fireboat” poniżej.

Ustal punkt odniesienia

Linia bazowa to obraz wejściowy używany jako punkt wyjścia do obliczania ważności funkcji. Intuicyjnie można myśleć o wyjaśniającej roli linii bazowej jako reprezentującej wpływ braku każdego piksela na prognozę „Fireboat” w przeciwieństwie do wpływu każdego piksela na prognozę „Fireboat”, gdy jest ona obecna na obrazie wejściowym. W rezultacie wybór linii bazowej odgrywa kluczową rolę w interpretacji i wizualizacji ważności funkcji pikseli. Aby uzyskać dodatkowe omówienie wyboru linii bazowej, zobacz zasoby w sekcji „Następne kroki” u dołu tego samouczka. Tutaj użyjesz czarnego obrazu, którego wartości pikseli wynoszą zero.

Inne opcje, z którymi możesz poeksperymentować, obejmują cały biały obraz lub losowy obraz, który możesz utworzyć za pomocą tf.random.uniform(shape=(224,224,3), minval=0.0, maxval=1.0) .

baseline = tf.zeros(shape=(224,224,3))
plt.imshow(baseline)
plt.title("Baseline")
plt.axis('off')
plt.show()

png

Rozpakuj formuły do ​​kodu

Wzór na zintegrowane gradienty jest następujący:

\(IntegratedGradients_{i}(x) ::= (x_{i} - x'_{i})\times\int_{\alpha=0}^1\frac{\partial F(x'+\alpha \times (x - x'))}{\partial x_i}{d\alpha}\)

gdzie:

\(_{i}\) = element
\(x\) = wejście
\(x'\) = linia bazowa
\(\alpha\) = stała interpolacji do obiektów perturb przez

W praktyce obliczenie całki oznaczonej nie zawsze jest możliwe numerycznie i może być kosztowne obliczeniowo, dlatego obliczamy następujące przybliżenie liczbowe:

\(IntegratedGrads^{approx}_{i}(x)::=(x_{i}-x'_{i})\times\sum_{k=1}^{m}\frac{\partial F(x' + \frac{k}{m}\times(x - x'))}{\partial x_{i} } \times \frac{1}{m}\)

gdzie:

\(_{i}\) = funkcja (pojedynczy piksel)
\(x\) = wejście (tensor obrazu)
\(x'\) = linia bazowa (tensor obrazu)
\(k\) = skalowana stała perturbacji elementu
\(m\) = liczba kroków w aproksymacji sumy Riemanna całki
\((x_{i}-x'_{i})\) = termin określający różnicę w stosunku do linii bazowej. Jest to konieczne do skalowania zintegrowanych gradientów i zachowania ich w zakresie oryginalnego obrazu. Ścieżka od obrazu bazowego do wejścia znajduje się w przestrzeni pikseli. Ponieważ z IG integrujesz w linii prostej (transformacja liniowa), kończy się to w przybliżeniu równaniem całki pochodnej interpolowanej funkcji obrazu w odniesieniu do \(\alpha\) z wystarczającą liczbą kroków. Całka sumuje gradient każdego piksela pomnożony przez zmianę piksela na ścieżce. Łatwiej jest zaimplementować tę integrację jako jednolite kroki od jednego obrazu do drugiego, zastępując \(x := (x' + \alpha(x-x'))\). Tak więc zmiana zmiennych daje \(dx = (x-x')d\alpha\). \((x-x')\) jest stały i jest uwzględniany w całce.

Interpoluj obrazy

\(IntegratedGrads^{approx}_{i}(x)::=(x_{i}-x'_{i})\times\sum_{k=1}^{m}\frac{\partial F(\overbrace{x' + \frac{k}{m}\times(x - x')}^\text{interpolate m images at k intervals})}{\partial x_{i} } \times \frac{1}{m}\)

Najpierw wygenerujesz liniową interpolację między linią bazową a oryginalnym obrazem. Możesz myśleć o obrazach interpolowanych jako o małych krokach w przestrzeni funkcji między linią bazową a danymi wejściowymi, reprezentowanymi przez \(\alpha\) w oryginalnym równaniu.

m_steps=50
alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1) # Generate m_steps intervals for integral_approximation() below.
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)
  delta = input_x - baseline_x
  images = baseline_x +  alphas_x * delta
  return images

Użyjmy powyższej funkcji, aby wygenerować obrazy interpolowane wzdłuż ścieżki liniowej w odstępach alfa między czarnym obrazem bazowym a przykładowym obrazem „Fireboat”.

interpolated_images = interpolate_images(
    baseline=baseline,
    image=img_name_tensors['Fireboat'],
    alphas=alphas)

Zwizualizujmy obrazy interpolowane. Uwaga: innym sposobem myślenia o stałej \(\alpha\) jest to, że konsekwentnie zwiększa ona intensywność każdego interpolowanego obrazu.

fig = plt.figure(figsize=(20, 20))

i = 0
for alpha, image in zip(alphas[0::10], interpolated_images[0::10]):
  i += 1
  plt.subplot(1, len(alphas[0::10]), i)
  plt.title(f'alpha: {alpha:.1f}')
  plt.imshow(image)
  plt.axis('off')

plt.tight_layout();

png

Oblicz gradienty

Przyjrzyjmy się teraz, jak obliczyć gradienty, aby zmierzyć związek między zmianami w funkcji a zmianami w przewidywaniach modelu. W przypadku obrazów gradient mówi nam, które piksele mają najsilniejszy wpływ na przewidywane przez modele prawdopodobieństwa klas.

\(IntegratedGrads^{approx}_{i}(x)::=(x_{i}-x'_{i})\times\sum_{k=1}^{m}\frac{\overbrace{\partial F(\text{interpolated images})}^\text{compute gradients} }{\partial x_{i} } \times \frac{1}{m}\)

gdzie:
\(F()\) = funkcja przewidywania modelu
\(\frac{\partial{F} }{\partial{x_i} }\) = gradient (wektor pochodnych cząstkowych \(\partial\)) funkcji predykcji modelu F względem każdej cechy \(x_i\)

TensorFlow ułatwia obliczanie gradientów dzięki tf.GradientTape .

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)

Obliczmy gradienty dla każdego obrazu wzdłuż ścieżki interpolacji w odniesieniu do prawidłowego wyniku. Przypomnij sobie, że Twój model zwraca tensor w kształcie (1, 1001) z Tensor , które konwertujesz na przewidywane prawdopodobieństwa dla każdej klasy. Musisz przekazać poprawny indeks klasy docelowej ImageNet do funkcji compute_gradients dla twojego obrazu.

path_gradients = compute_gradients(
    images=interpolated_images,
    target_class_idx=555)

Zwróć uwagę na kształt wyjściowy (n_interpolated_images, img_height, img_width, RGB) , który daje nam gradient dla każdego piksela każdego obrazu wzdłuż ścieżki interpolacji. Możesz myśleć o tych gradientach jako o mierzeniu zmian w przewidywaniach modelu dla każdego małego kroku w przestrzeni cech.

print(path_gradients.shape)
(51, 224, 224, 3)

Wizualizacja nasycenia gradientem

Przypomnij sobie, że gradienty, które właśnie obliczone powyżej opisują lokalne zmiany przewidywanego prawdopodobieństwa modelu „Fireboat” i mogą być nasycone .

Te koncepcje są wizualizowane za pomocą gradientów obliczonych powyżej na 2 wykresach poniżej.

pred = model(interpolated_images)
pred_proba = tf.nn.softmax(pred, axis=-1)[:, 555]

png

  • left : Ten wykres pokazuje, jak zaufanie Twojego modelu do klasy „Fireboat” różni się w poszczególnych wersjach alfa. Zwróć uwagę, jak nachylenie lub nachylenie linii w dużej mierze spłaszcza się lub nasyca w zakresie od 0,6 do 1,0, zanim ustali się na końcowym przewidywanym prawdopodobieństwie „łodzi strażackiej” wynoszącym około 40%.

  • right : Prawy wykres pokazuje bardziej bezpośrednio średnie wartości gradientów względem wartości alfa. Zwróć uwagę, jak wartości gwałtownie się zbliżają, a nawet na chwilę spadają poniżej zera. W rzeczywistości twój model „uczy się” najwięcej z gradientów przy niższych wartościach alfa przed nasyceniem. Intuicyjnie możesz myśleć o tym, jak twój model nauczył się pikseli, np. armatek wodnych, aby dokonać prawidłowej prognozy, wysyłając gradienty tych pikseli do zera, ale nadal jest dość niepewny i koncentruje się na fałszywych pikselach mostu lub strumienia wody, gdy wartości alfa zbliżają się do oryginalny obraz wejściowy.

Aby upewnić się, że te ważne piksele armatki wodnej są odzwierciedlane jako ważne dla prognozy „Róża strażacka”, będziesz kontynuować poniżej, aby dowiedzieć się, jak akumulować te gradienty, aby dokładnie przybliżyć, w jaki sposób każdy piksel wpływa na przewidywane prawdopodobieństwo „Ratnicy ognistej”.

Akumuluj gradienty (przybliżenie całkowe)

Istnieje wiele różnych sposobów obliczania liczbowego przybliżenia całki dla IG z różnymi kompromisami w dokładności i zbieżności w różnych funkcjach. Popularna klasa metod nazywa się sumami Riemanna . Tutaj użyjesz reguły trapezowej (na końcu tego samouczka znajdziesz dodatkowy kod do odkrywania różnych metod aproksymacji).

$IntegratedGrads^{około} {i}(x)::=(x {i}-x' {i})\times \overbrace{\sum {k=1}^{m} }^\text{Sum m gradienty lokalne} \text{gradienty(obrazy interpolowane)} \times \overbrace{\frac{1}{m} }^\text{Podziel przez m kroków}$

Z równania widać, że sumujesz m gradientów i dzielisz je przez m kroków. Możesz zaimplementować te dwie operacje razem dla części 3 jako średnią lokalnych gradientów m interpolowanych predykcji i obrazów wejściowych .

def integral_approximation(gradients):
  # riemann_trapezoidal
  grads = (gradients[:-1] + gradients[1:]) / tf.constant(2.0)
  integrated_gradients = tf.math.reduce_mean(grads, axis=0)
  return integrated_gradients

Funkcja integral_approximation pobiera gradienty przewidywanego prawdopodobieństwa klasy docelowej w odniesieniu do interpolowanych obrazów między linią bazową a oryginalnym obrazem.

ig = integral_approximation(
    gradients=path_gradients)

Możesz potwierdzić, że uśrednianie gradientów m interpolowanych obrazów zwraca zintegrowany tensor gradientów o tym samym kształcie, co oryginalny obraz „Wielkiej Pandy”.

print(ig.shape)
(224, 224, 3)

Kładąc wszystko razem

Teraz połączysz 3 poprzednie ogólne części razem w funkcję IntegratedGradients i użyjesz dekoratora @tf.function , aby skompilować go w wysoce wydajny, wywoływany wykres TensorFlow. Jest to realizowane jako 5 mniejszych kroków poniżej:

\(IntegratedGrads^{approx}_{i}(x)::=\overbrace{(x_{i}-x'_{i})}^\text{5.}\times \overbrace{\sum_{k=1}^{m} }^\text{4.} \frac{\partial \overbrace{F(\overbrace{x' + \overbrace{\frac{k}{m} }^\text{1.}\times(x - x'))}^\text{2.} }^\text{3.} }{\partial x_{i} } \times \overbrace{\frac{1}{m} }^\text{4.}\)

  1. Wygeneruj alfa \(\alpha\)

  2. Generuj obrazy interpolowane = \((x' + \frac{k}{m}\times(x - x'))\)

  3. Oblicz gradienty między prognozami wyjściowymi modelu \(F\) w odniesieniu do cech wejściowych = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)

  4. Aproksymacja całkowa poprzez uśrednianie gradientów = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)

  5. Skaluj zintegrowane gradienty względem oryginalnego obrazu = \((x_{i}-x'_{i}) \times \text{integrated gradients}\). Powodem, dla którego ten krok jest konieczny, jest upewnienie się, że wartości atrybucji skumulowane w wielu interpolowanych obrazach są w tych samych jednostkach i wiernie odzwierciedlają znaczenie pikseli na oryginalnym obrazie.

def integrated_gradients(baseline,
                         image,
                         target_class_idx,
                         m_steps=50,
                         batch_size=32):
  # Generate alphas.
  alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1)

  # Collect gradients.    
  gradient_batches = []

  # Iterate alphas range and batch computation for speed, memory efficiency, and scaling to larger m_steps.
  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)

  # Stack path gradients together row-wise into single tensor.
  total_gradients = tf.stack(gradient_batch)

  # Integral approximation through averaging gradients.
  avg_gradients = integral_approximation(gradients=total_gradients)

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

  return integrated_gradients
@tf.function
def one_batch(baseline, image, alpha_batch, target_class_idx):
    # Generate interpolated inputs between baseline and input.
    interpolated_path_input_batch = interpolate_images(baseline=baseline,
                                                       image=image,
                                                       alphas=alpha_batch)

    # Compute gradients between model outputs and interpolated inputs.
    gradient_batch = compute_gradients(images=interpolated_path_input_batch,
                                       target_class_idx=target_class_idx)
    return gradient_batch
ig_attributions = integrated_gradients(baseline=baseline,
                                       image=img_name_tensors['Fireboat'],
                                       target_class_idx=555,
                                       m_steps=240)

Ponownie możesz sprawdzić, czy atrybuty funkcji IG mają taki sam kształt, jak obraz wejściowy „Fireboat”.

print(ig_attributions.shape)
(224, 224, 3)

Artykuł sugeruje liczbę kroków w zakresie od 20 do 300 w zależności od przykładu (chociaż w praktyce może to być wyższa w tysiącach, aby dokładnie przybliżyć całkę). Dodatkowy kod do sprawdzenia odpowiedniej liczby kroków można znaleźć w zasobach „Następne kroki” na końcu tego samouczka.

Wizualizuj atrybucje

Jesteś gotowy, aby zwizualizować atrybucje i nałożyć je na oryginalny obraz. Poniższy kod sumuje wartości bezwzględne zintegrowanych gradientów w kanałach kolorów, tworząc maskę atrybucji. Ta metoda kreślenia przechwytuje względny wpływ pikseli na prognozy modelu.

Patrząc na atrybucje na obrazie „Fireboat”, można zauważyć, że model identyfikuje armatki wodne i dziobki jako przyczyniające się do jego prawidłowego przewidywania.

_ = plot_img_attributions(image=img_name_tensors['Fireboat'],
                          baseline=baseline,
                          target_class_idx=555,
                          m_steps=240,
                          cmap=plt.cm.inferno,
                          overlay_alpha=0.4)

png

Na obrazie „Giant Panda” atrybucje podkreślają fakturę, nos i futro twarzy Pandy.

_ = plot_img_attributions(image=img_name_tensors['Giant Panda'],
                          baseline=baseline,
                          target_class_idx=389,
                          m_steps=55,
                          cmap=plt.cm.viridis,
                          overlay_alpha=0.5)

png

Zastosowania i ograniczenia

Przypadków użycia

  • Zastosowanie technik, takich jak zintegrowane gradienty, przed wdrożeniem modelu może pomóc w opracowaniu intuicji dotyczącej tego, jak i dlaczego działa. Czy cechy wyróżnione tą techniką pasują do Twojej intuicji? Jeśli nie, może to wskazywać na błąd w Twoim modelu lub zbiorze danych albo na nadmierne dopasowanie.

Ograniczenia

  • Gradienty zintegrowane zapewniają ważność funkcji na poszczególnych przykładach, jednak nie zapewniają globalnego znaczenia funkcji w całym zestawie danych.

  • Gradienty zintegrowane zapewniają indywidualne znaczenie funkcji, ale nie wyjaśniają interakcji i kombinacji funkcji.

Następne kroki

W tym samouczku przedstawiono podstawową implementację zintegrowanych gradientów. W następnym kroku możesz użyć tego notatnika, aby samodzielnie wypróbować tę technikę z różnymi modelami i obrazami.

Dla zainteresowanych czytelników dostępna jest dłuższa wersja tego samouczka (zawierająca kod dla różnych linii bazowych, służący do obliczania przybliżeń całkowych i określania wystarczającej liczby kroków), którą można znaleźć tutaj .

Aby pogłębić swoją wiedzę, zapoznaj się z artykułem Axiomatic Attribution for Deep Networks i repozytorium Github , który zawiera implementację w poprzedniej wersji TensorFlow. Możesz także zapoznać się z przypisywaniem funkcji i wpływem różnych poziomów bazowych w witrynie distill.pub .

Interesuje Cię włączenie IG do swoich produkcyjnych przepływów pracy uczenia maszynowego w celu uzyskania ważności funkcji, analizy błędów modelu i monitorowania pochylenia danych? Sprawdź produkt Google Cloud Explainable AI , który obsługuje atrybucje IG. Grupa badawcza Google AI PAIR udostępniła również narzędzie typu „What-if”, które może być wykorzystywane do debugowania modeli, w tym wizualizacji atrybucji funkcji IG.