Gradienti integrati

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza su GitHub Scarica quaderno Vedi modello TF Hub

Questo tutorial mostra come implementare i gradienti integrati (IG) , una tecnica di intelligenza artificiale spiegabile introdotta nel documento Axiomatic Attribution for Deep Networks . IG mira a spiegare la relazione tra le previsioni di un modello in termini di caratteristiche. Ha molti casi d'uso tra cui la comprensione dell'importanza delle funzionalità, l'identificazione della distorsione dei dati e il debug delle prestazioni del modello.

IG è diventata una tecnica di interpretabilità popolare grazie alla sua ampia applicabilità a qualsiasi modello differenziabile (ad es. immagini, testo, dati strutturati), facilità di implementazione, giustificazioni teoriche ed efficienza computazionale rispetto ad approcci alternativi che gli consentono di scalare su reti di grandi dimensioni e funzionalità spazi come le immagini.

In questo tutorial, illustrerai passo dopo passo un'implementazione di IG per comprendere l'importanza delle caratteristiche dei pixel di un classificatore di immagini. Ad esempio, considera questa immagine di un battello antincendio che spruzza getti d'acqua. Classificheresti questa immagine come una nave antincendio e potresti evidenziare i pixel che compongono la barca e i cannoni ad acqua come importanti per la tua decisione. Il tuo modello classificherà anche questa immagine come una nave antincendio più avanti in questo tutorial; tuttavia, evidenzia gli stessi pixel importanti quando spiega la sua decisione?

Nelle immagini sottostanti intitolate "Maschera di attribuzione IG" e "Overlay maschera IG originale" puoi vedere che il tuo modello evidenzia invece (in viola) i pixel che comprendono i cannoni ad acqua e i getti d'acqua della barca come più importanti della barca stessa per sua decisione. In che modo il tuo modello si generalizzerà alle nuove navi antincendio? E le barche dei pompieri senza getti d'acqua? Continua a leggere per saperne di più su come funziona IG e su come applicare IG ai tuoi modelli per comprendere meglio la relazione tra le loro previsioni e le caratteristiche sottostanti.

Immagine di uscita 1

Impostare

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

Scarica un classificatore di immagini preaddestrato da TF-Hub

IG può essere applicato a qualsiasi modello differenziabile. Nello spirito del documento originale, utilizzerai una versione pre-addestrata dello stesso modello, Inception V1, che scaricherai da 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
_________________________________________________________________

Dalla pagina del modulo, è necessario tenere presente quanto segue su Inception V1:

Input : la forma di input prevista per il modello è (None, 224, 224, 3) . Questo è un denso tensore 4D di dtype float32 e shape (batch_size, height, width, RGB channels) i cui elementi sono valori di colore RGB dei pixel normalizzati all'intervallo [0, 1]. Il primo elemento è None per indicare che il modello può accettare qualsiasi dimensione batch intera.

Output : Un tf.Tensor di logit a forma di (batch_size, 1001) . Ogni riga rappresenta il punteggio previsto del modello per ciascuna delle 1.001 classi di ImageNet. Per l'indice di classe più previsto del modello puoi usare tf.argmax(predictions, axis=-1) . Inoltre, puoi anche convertire l'output logit del modello in probabilità previste in tutte le classi usando tf.nn.softmax(predictions, axis=-1) per quantificare l'incertezza del modello ed esplorare classi previste simili per il debug.

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')

Carica e preelabora le immagini con tf.image

Illustrerai IG usando due immagini da Wikimedia Commons : un Fireboat e un 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

Classifica le immagini

Iniziamo classificando queste immagini e visualizzando le prime 3 previsioni più sicure. Di seguito è riportata una funzione di utilità per recuperare le prime k etichette e probabilità previste.

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%

Calcola gradienti integrati

Il tuo modello, Inception V1, è una funzione appresa che descrive una mappatura tra lo spazio delle funzionalità di input, i valori dei pixel dell'immagine e uno spazio di output definito dai valori di probabilità della classe ImageNet compresi tra 0 e 1. I primi metodi di interpretabilità per le reti neurali assegnavano punteggi di importanza delle funzionalità utilizzando gradienti, che indicano quali pixel hanno il locale più ripido rispetto alla previsione del modello in un determinato punto lungo la funzione di previsione del modello. Tuttavia, i gradienti descrivono solo le modifiche locali nella funzione di previsione del modello rispetto ai valori dei pixel e non descrivono completamente l'intera funzione di previsione del modello. Quando il tuo modello "impara" completamente la relazione tra l'intervallo di un singolo pixel e la classe ImageNet corretta, il gradiente per questo pixel si saturerà , il che significa che diventerà sempre più piccolo e addirittura azzera. Considera la funzione modello semplice di seguito:

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

  • a sinistra : i gradienti del tuo modello per pixel x sono positivi tra 0,0 e 0,8 ma vanno a 0,0 tra 0,8 e 1,0. Pixel x ha chiaramente un impatto significativo sullo spostamento del modello verso l'80% di probabilità prevista sulla classe reale. Ha senso che l'importanza di pixel x sia piccola o discontinua?

  • a destra : l'intuizione alla base di IG è accumulare i gradienti locali di pixel x e attribuirne l'importanza come punteggio per quanto aggiunge o sottrae alla probabilità complessiva della classe di output del modello. Puoi scomporre e calcolare IG in 3 parti:

    1. interpolare piccoli passi lungo una linea retta nello spazio delle funzioni compreso tra 0 (una linea di base o un punto iniziale) e 1 (input il valore del pixel)
    2. calcola i gradienti a ogni passaggio tra le previsioni del modello rispetto a ciascun passaggio
    3. approssimare l'integrale tra la linea di base e l'input accumulando (media cumulativa) questi gradienti locali.

Per rafforzare questa intuizione, camminerai attraverso queste 3 parti applicando IG all'immagine di esempio "Fireboat" qui sotto.

Stabilisci una linea di base

Una linea di base è un'immagine di input utilizzata come punto di partenza per calcolare l'importanza della caratteristica. Intuitivamente, puoi pensare al ruolo esplicativo della linea di base come a rappresentare l'impatto dell'assenza di ciascun pixel sulla previsione "Fireboat" per contrastare il suo impatto di ciascun pixel sulla previsione "Fireboat" quando presente nell'immagine di input. Di conseguenza, la scelta della linea di base gioca un ruolo centrale nell'interpretazione e nella visualizzazione dell'importanza delle caratteristiche dei pixel. Per ulteriori discussioni sulla selezione di base, vedere le risorse nella sezione "Passaggi successivi" in fondo a questo tutorial. Qui utilizzerai un'immagine nera i cui valori di pixel sono tutti zero.

Altre scelte che potresti sperimentare includono un'immagine completamente bianca o un'immagine casuale, che puoi creare con 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

Decomprimere le formule nel codice

La formula per i gradienti integrati è la seguente:

\(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}\)

dove:

\(_{i}\) = funzione
\(x\) = input
\(x'\) = linea di base
\(\alpha\) = costante di interpolazione per perturbare le caratteristiche di

In pratica, calcolare un integrale definito non è sempre numericamente possibile e può essere computazionalmente costoso, quindi si calcola la seguente approssimazione numerica:

\(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}\)

dove:

\(_{i}\) = funzione (singolo pixel)
\(x\) = ingresso (tensore dell'immagine)
\(x'\) = linea di base (tensore dell'immagine)
\(k\) = costante di perturbazione dell'elemento in scala
\(m\) = numero di passi nell'approssimazione della somma di Riemann dell'integrale
\((x_{i}-x'_{i})\) = un termine per la differenza dalla linea di base. Ciò è necessario per ridimensionare i gradienti integrati e mantenerli nei termini dell'immagine originale. Il percorso dall'immagine di base all'input è nello spazio dei pixel. Poiché con IG stai integrando in una linea retta (trasformazione lineare) questo finisce per essere più o meno equivalente al termine integrale della derivata della funzione immagine interpolata rispetto a \(\alpha\) con passaggi sufficienti. L'integrale somma il gradiente di ciascun pixel moltiplicato per la variazione del pixel lungo il percorso. È più semplice implementare questa integrazione come passaggi uniformi da un'immagine all'altra, sostituendo \(x := (x' + \alpha(x-x'))\). Quindi la modifica delle variabili dà \(dx = (x-x')d\alpha\). Il termine \((x-x')\) è costante e viene scomposto dall'integrale.

Interpolare le immagini

\(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}\)

Innanzitutto, genererai un'interpolazione lineare tra la linea di base e l'immagine originale. Puoi pensare alle immagini interpolate come a piccoli passi nello spazio delle caratteristiche tra la linea di base e l'input, rappresentato da \(\alpha\) nell'equazione originale.

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

Usiamo la funzione precedente per generare immagini interpolate lungo un percorso lineare a intervalli alfa tra un'immagine di base nera e l'immagine di esempio "Fireboat".

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

Visualizziamo le immagini interpolate. Nota: un altro modo di pensare alla costante \(\alpha\) è che aumenta costantemente l'intensità di ciascuna immagine interpolata.

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

Calcola gradienti

Ora diamo un'occhiata a come calcolare i gradienti per misurare la relazione tra le modifiche a una caratteristica e le modifiche alle previsioni del modello. Nel caso delle immagini, il gradiente ci dice quali pixel hanno l'effetto più forte sulle probabilità di classe previste dai modelli.

\(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}\)

dove:
\(F()\) = la funzione di previsione del modello
\(\frac{\partial{F} }{\partial{x_i} }\) = gradiente (vettore di derivate parziali \(\partial\)) della funzione di previsione del modello F relativa a ciascuna caratteristica \(x_i\)

TensorFlow semplifica il calcolo dei gradienti con un 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)

Calcoliamo i gradienti per ogni immagine lungo il percorso di interpolazione rispetto all'output corretto. Ricorda che il tuo modello restituisce un Tensor a forma di (1, 1001) con logit che converti in probabilità previste per ciascuna classe. Devi passare l'indice di classe di destinazione ImageNet corretto alla funzione compute_gradients per la tua immagine.

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

Nota la forma di output di (n_interpolated_images, img_height, img_width, RGB) , che ci fornisce il gradiente per ogni pixel di ogni immagine lungo il percorso di interpolazione. Puoi pensare a questi gradienti come a una misurazione del cambiamento nelle previsioni del tuo modello per ogni piccolo passaggio nello spazio delle funzionalità.

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

Visualizzazione della saturazione del gradiente

Ricorda che i gradienti che hai appena calcolato sopra descrivono i cambiamenti locali alla probabilità prevista del tuo modello di "Fireboat" e possono saturare .

Questi concetti vengono visualizzati utilizzando i gradienti che hai calcolato sopra nei 2 grafici sottostanti.

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

png

  • a sinistra : questo grafico mostra come la fiducia del tuo modello nella classe "Fireboat" varia tra gli alfa. Si noti come i gradienti, o pendenza della linea, si appiattiscano o si saturano in gran parte tra 0,6 e 1,0 prima di stabilirsi alla probabilità finale prevista "Fireboat" di circa il 40%.

  • a destra : il grafico a destra mostra le magnitudini medie dei gradienti rispetto all'alfa in modo più diretto. Nota come i valori si avvicinano bruscamente e scendono anche brevemente sotto lo zero. In effetti, il tuo modello "impara" di più dai gradienti a valori alfa più bassi prima della saturazione. Intuitivamente, puoi pensare a questo poiché il tuo modello ha imparato i pixel, ad esempio i cannoni ad acqua per fare la previsione corretta, inviando questi gradienti di pixel a zero, ma è ancora piuttosto incerto e si concentra su pixel spuri del ponte o del getto d'acqua mentre i valori alfa si avvicinano al immagine di input originale.

Per assicurarti che questi importanti pixel del cannone ad acqua siano considerati importanti per la previsione "Fireboat", continuerai di seguito per imparare come accumulare questi gradienti per approssimare accuratamente l'impatto di ogni pixel sulla tua probabilità prevista "Fireboat".

Accumula gradienti (approssimazione integrale)

Esistono molti modi diversi per calcolare l'approssimazione numerica di un integrale per IG con diversi compromessi in termini di precisione e convergenza tra funzioni variabili. Una classe di metodi popolare è chiamata sums di Riemann . Qui utilizzerai la regola trapezoidale (puoi trovare codice aggiuntivo per esplorare diversi metodi di approssimazione alla fine di questo tutorial).

$IntegratedGrads^{approssimativamente} {i}(x)::=(x {i}-x' {i})\times \overbrace{\sum {k=1}^{m} }^\text{Somma m gradienti locali} \text{gradients(immagini interpolate)} \times \overbrace{\frac{1}{m} }^\text{Dividi per m passi}$

Dall'equazione, puoi vedere che stai sommando su m gradienti e dividendo per m passi. È possibile implementare le due operazioni insieme per la parte 3 come media dei gradienti locali di m previsioni interpolate e immagini di input .

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

La funzione integral_approximation prende i gradienti della probabilità prevista della classe target rispetto alle immagini interpolate tra la linea di base e l'immagine originale.

ig = integral_approximation(
    gradients=path_gradients)

Puoi confermare che la media tra i gradienti delle m immagini interpolate restituisce un tensore dei gradienti integrato con la stessa forma dell'immagine originale "Giant Panda".

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

Mettere tutto insieme

Ora combinerai le 3 parti generali precedenti insieme in una funzione IntegratedGradients e utilizzerai un decoratore di funzioni @tf. per compilarlo in un grafico TensorFlow richiamabile ad alte prestazioni. Questo viene implementato come 5 passaggi più piccoli di seguito:

\(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. Genera alfa \(\alpha\)

  2. Genera immagini interpolate = \((x' + \frac{k}{m}\times(x - x'))\)

  3. Calcola i gradienti tra le previsioni di output del modello \(F\) rispetto alle caratteristiche di input = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)

  4. Approssimazione integrale tramite gradienti medi = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)

  5. Ridimensiona i gradienti integrati rispetto all'immagine originale = \((x_{i}-x'_{i}) \times \text{integrated gradients}\). Il motivo per cui questo passaggio è necessario è assicurarsi che i valori di attribuzione accumulati su più immagini interpolate siano nelle stesse unità e rappresentino fedelmente l'importanza dei pixel sull'immagine originale.

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)

Ancora una volta, puoi verificare che le attribuzioni delle funzioni IG abbiano la stessa forma dell'immagine di input "Fireboat".

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

Il documento suggerisce che il numero di passaggi sia compreso tra 20 e 300 a seconda dell'esempio (sebbene in pratica questo possa essere maggiore negli anni 1.000 per approssimare accuratamente l'integrale). Puoi trovare codice aggiuntivo per verificare il numero appropriato di passaggi nelle risorse "Passaggi successivi" alla fine di questo tutorial.

Visualizza le attribuzioni

Sei pronto per visualizzare le attribuzioni e sovrapporle all'immagine originale. Il codice seguente somma i valori assoluti dei gradienti integrati attraverso i canali di colore per produrre una maschera di attribuzione. Questo metodo di tracciamento cattura l'impatto relativo dei pixel sulle previsioni del modello.

Osservando le attribuzioni sull'immagine "Fireboat", puoi vedere che il modello identifica i cannoni ad acqua e le bocchette come contributo alla sua corretta previsione.

_ = 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

Nell'immagine "Giant Panda", le attribuzioni evidenziano la trama, il naso e la pelliccia del viso del Panda.

_ = 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

Usi e limitazioni

Casi d'uso

  • L'impiego di tecniche come i gradienti integrati prima di distribuire il modello può aiutarti a sviluppare l'intuizione su come e perché funziona. Le caratteristiche evidenziate da questa tecnica corrispondono al tuo intuito? In caso contrario, ciò potrebbe essere indicativo di un bug nel modello o nel set di dati o di un overfitting.

Limitazioni

  • Gradienti integrati fornisce l'importanza delle funzionalità su singoli esempi, tuttavia, non fornisce l'importanza delle funzionalità globali in un intero set di dati.

  • Gradienti integrati fornisce l'importanza delle singole funzionalità, ma non spiega le interazioni e le combinazioni delle funzionalità.

Prossimi passi

Questo tutorial ha presentato un'implementazione di base di Integrated Gradients. Come passaggio successivo, puoi utilizzare questo taccuino per provare tu stesso questa tecnica con diversi modelli e immagini.

Per i lettori interessati, esiste una versione più lunga di questo tutorial (che include codice per diverse linee di base, per calcolare approssimazioni integrali e per determinare un numero sufficiente di passaggi) che puoi trovare qui .

Per approfondire la tua comprensione, dai un'occhiata al documento Axiomatic Attribution for Deep Networks e Github repository , che contiene un'implementazione in una versione precedente di TensorFlow. Puoi anche esplorare l'attribuzione delle funzionalità e l'impatto di diverse linee di base su distill.pub .

Interessato a incorporare IG nei flussi di lavoro di machine learning di produzione per l'importanza delle funzionalità, l'analisi degli errori del modello e il monitoraggio della distorsione dei dati? Dai un'occhiata al prodotto Explainable AI di Google Cloud che supporta le attribuzioni IG. Il gruppo di ricerca Google AI PAIR ha anche reso open source lo strumento What-if che può essere utilizzato per il debug dei modelli, inclusa la visualizzazione delle attribuzioni delle funzioni IG.