עזרה להגן על שונית המחסום הגדולה עם TensorFlow על Kaggle הצטרפו אתגר

שיפועים משולבים

הצג באתר TensorFlow.org הפעל בגוגל קולאב הצג ב-GitHub הורד מחברת ראה דגם TF Hub

מדריך זה מדגים כיצד ליישם Gradients Integrated (IG) , טכניקת AI ניתנת להסבר שהוצגה במאמר Axiomatic Attribution for Deep Networks . IG שואפת להסביר את הקשר בין התחזיות של מודל במונחים של תכונותיו. יש לו מקרי שימוש רבים, כולל הבנת חשיבות התכונות, זיהוי הטיית נתונים וניפוי ביצועי מודל.

IG הפכה לטכניקת פרשנות פופולרית בשל ישימותה הרחבה על כל מודל שניתן להבדיל (כגון תמונות, טקסט, נתונים מובנים), קלות היישום, הצדקות תיאורטיות ויעילות חישובית ביחס לגישות חלופיות המאפשרות להתאים אותה לרשתות גדולות ולפיצ'רים גדולים. חללים כגון תמונות.

במדריך זה, תעברו על יישום של IG שלב אחר שלב כדי להבין את חשיבות תכונת הפיקסלים של מסווג תמונה. כדוגמה, שקול תמונה זו של סירת כיבוי אש המרססת סילוני מים. הייתם מסווגים את התמונה הזו כסירת כיבוי אש ועשוי להדגיש את הפיקסלים המרכיבים את הסירה ותותחי המים כחשובים להחלטתכם. הדגם שלך גם יסווג תמונה זו כסירת אש בהמשך הדרכה זו; עם זאת, האם הוא מדגיש את אותם פיקסלים כחשובים כאשר מסבירים את ההחלטה שלו?

בתמונות למטה שכותרתן "מסכת ייחוס IG" ו-"Original + IG Mask Overlay" אתה יכול לראות שהדגם שלך מדגיש במקום זאת (בסגול) את הפיקסלים המרכיבים את תותחי המים וסילוני המים של הסירה כחשובים יותר מהסירה עצמה. ההחלטה שלה. איך המודל שלך יכלל על סירות כיבוי חדשות? מה לגבי סירות כיבוי ללא סילוני מים? המשך לקרוא כדי ללמוד עוד על אופן הפעולה של IG וכיצד ליישם IG על המודלים שלך כדי להבין טוב יותר את הקשר בין התחזיות שלהם לתכונות הבסיסיות.

תמונת פלט 1

להכין

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

הורד סיווג תמונות מיומן מראש מ-TF-Hub

ניתן ליישם IG על כל דגם שניתן להבדיל. ברוח המאמר המקורי, תשתמשו בגרסה מאומנת מראש של אותו דגם, Inception V1, אותה תורידו מ- 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
_________________________________________________________________

מדף המודול, עליך לזכור את הדברים הבאים לגבי Inception V1:

תשומות : צורת הקלט הצפויה עבור המודל היא (None, 224, 224, 3) . זהו טנזור 4D צפוף של dtype float32 וצורה (batch_size, height, width, RGB channels) שהאלמנטים שלו הם ערכי צבע RGB של פיקסלים המנורמלים לטווח [0, 1]. האלמנט הראשון הוא None כדי לציין שהמודל יכול לקחת כל גודל אצווה של מספר שלם.

פלטים : tf.Tensor של לוגיטים בצורה של (batch_size, 1001) . כל שורה מייצגת את הציון החזוי של המודל עבור כל אחת מ-1,001 כיתות מ-ImageNet. עבור אינדקס המחלקות החזוי העליון של המודל, אתה יכול להשתמש ב- tf.argmax(predictions, axis=-1) . יתרה מזאת, אתה יכול גם להמיר את פלט הלוגיט של המודל להסתברויות חזויות בכל המחלקות באמצעות tf.nn.softmax(predictions, axis=-1) כדי לכמת את אי הוודאות של המודל וכן לחקור מחלקות חזויות דומות לניפוי באגים.

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

טען ועבד מראש תמונות עם tf.image

תוכלו להמחיש IG באמצעות שתי תמונות מ- Wikimedia Commons : סירת אש ופנדה ענקית .

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

סיווג תמונות

בואו נתחיל בסיווג התמונות האלה והצגת שלושת התחזיות הכי בטוחות. להלן פונקציית עזר כדי לאחזר את התוויות וההסתברויות החזויות המובילות.

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%

חשב מעברי צבע משולבים

המודל שלך, Inception V1, הוא פונקציה נלמדת המתארת ​​מיפוי בין מרחב תכונת הקלט שלך, ערכי פיקסלים של תמונה ומרחב פלט המוגדר על ידי ערכי הסתברות של מחלקה ImageNet בין 0 ל-1. שיטות פרשנות מוקדמות עבור רשתות עצביות הוקצו ציוני חשיבות תכונה באמצעות מעברי צבע, שאומרים לך לאילו פיקסלים יש את המקומי התלול ביותר ביחס לחיזוי המודל שלך בנקודה נתונה לאורך פונקציית החיזוי של המודל שלך. עם זאת, מעברי צבע מתארים רק שינויים מקומיים בפונקציית החיזוי של המודל שלך ביחס לערכי הפיקסלים ואינם מתארים במלואם את כל פונקציית חיזוי המודל שלך. כאשר הדגם שלך "לומד" במלואו את הקשר בין הטווח של פיקסל בודד למחלקה הנכונה של ImageNet, השיפוע עבור הפיקסל הזה ירווי , כלומר יהפוך קטן יותר ויותר ואפילו יגיע לאפס. שקול את פונקציית המודל הפשוטה להלן:

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

  • שמאל : ההדרגות של הדגם שלך עבור פיקסל x חיוביות בין 0.0 ל-0.8, אך עבור ל-0.0 בין 0.8 ל-1.0. ל-Pixel x יש בבירור השפעה משמעותית על דחיפת הדגם שלך לכיוון של 80% הסתברות חזויה במעמד האמיתי. האם זה הגיוני שחשיבותו של פיקסל x קטנה או בלתי רציפה?

  • מימין : האינטואיציה מאחורי IG היא לצבור שיפועים מקומיים של פיקסל x ולייחס את חשיבותו כציון לכמה הוא מוסיף או מפחית להסתברות הכוללת של מחלקת הפלט של המודל שלך. אתה יכול לפרק ולחשב IG ב-3 חלקים:

    1. אינטרפולציה של צעדים קטנים לאורך קו ישר ברווח התכונה בין 0 (קו בסיס או נקודת התחלה) ל-1 (ערך פיקסל קלט)
    2. חישוב מעברי צבע בכל שלב בין התחזיות של המודל שלך ביחס לכל שלב
    3. הערך את האינטגרל בין קו הבסיס לקלט שלך על ידי צבירת (ממוצע מצטבר) שיפועים מקומיים אלה.

כדי לחזק את האינטואיציה הזו, תעבור על 3 החלקים הללו על ידי החלת IG על תמונת "סירת האש" לדוגמה למטה.

קבע קו בסיס

קו בסיס הוא תמונת קלט המשמשת כנקודת מוצא לחישוב חשיבות התכונה. באופן אינטואיטיבי, אתה יכול לחשוב על תפקידו ההסברתי של קו הבסיס כמייצג את ההשפעה של היעדר כל פיקסל על חיזוי "סירת האש" כדי בניגוד להשפעתו של כל פיקסל על חיזוי "סירת האש" כאשר הוא קיים בתמונת הקלט. כתוצאה מכך, הבחירה בקו הבסיס ממלאת תפקיד מרכזי בפירוש ובהמחשה של חשיבות תכונות הפיקסלים. לדיון נוסף בבחירת קו הבסיס, עיין במשאבים בסעיף "השלבים הבאים" בתחתית מדריך זה. כאן תשתמש בתמונה שחורה שכל ערכי הפיקסלים שלה הם אפס.

אפשרויות אחרות שאתה יכול להתנסות בהן כוללות תמונה לגמרי לבנה, או תמונה אקראית, שתוכל ליצור עם 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

פרק נוסחאות לקוד

הנוסחה עבור מעברי צבע משולבים היא כדלקמן:

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

איפה:

\(_{i}\) = תכונה
\(x\) = קלט
\(x'\) = קו בסיס
\(\alpha\) = קבוע אינטרפולציה כדי להפריע לתכונות על ידי

בפועל, חישוב אינטגרל מוגדר לא תמיד אפשרי מבחינה מספרית ויכול להיות יקר מבחינה חישובית, אז אתה מחשב את הקירוב המספרי הבא:

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

איפה:

\(_{i}\) = תכונה (פיקסל בודד)
\(x\) = קלט (טנזור תמונה)
\(x'\) = קו בסיס (טנזור תמונה)
\(k\) = קבוע הפרעות של תכונה בקנה מידה
\(m\) = מספר השלבים בקירוב סכום רימן של האינטגרל
\((x_{i}-x'_{i})\) = מונח להפרש מקו הבסיס. זה הכרחי כדי לשנות את קנה המידה של מעברי הצבע המשולבים ולשמור אותם במונחים של התמונה המקורית. הנתיב מתמונת הבסיס לקלט הוא בחלל פיקסלים. מכיוון שעם IG אתה משתלב בקו ישר (טרנספורמציה ליניארית), זה בסופו של דבר שווה ערך לאיבר האינטגרלי של הנגזרת של פונקציית התמונה המשולבת ביחס ל- \(\alpha\) עם מספיק שלבים. האינטגרל מסכם את השיפוע של כל פיקסל כפול השינוי בפיקסל לאורך הנתיב. קל יותר ליישם את השילוב הזה כצעדים אחידים מתמונה אחת לאחרת, תוך החלפת \(x := (x' + \alpha(x-x'))\). אז השינוי של המשתנים נותן \(dx = (x-x')d\alpha\). המונח \((x-x')\) הוא קבוע ומוכלל מתוך האינטגרל.

אינטרפולציה של תמונות

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

ראשית, תיצור אינטרפולציה ליניארית בין קו הבסיס לתמונה המקורית. אתה יכול לחשוב על תמונות משולבות כעל שלבים קטנים ברווח התכונה שבין קו הבסיס לקלט שלך, המיוצגים על ידי \(\alpha\) במשוואה המקורית.

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

הבה נשתמש בפונקציה שלמעלה כדי ליצור תמונות משולבות לאורך נתיב ליניארי במרווחי אלפא בין תמונת קו בסיס שחורה לתמונת "סירת האש" לדוגמה.

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

בואו נדמיין את התמונות המשולבות. הערה: דרך נוספת לחשוב על הקבוע \(\alpha\) היא שהוא מגביר באופן עקבי את עוצמת כל תמונה באינטרפולציה.

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

חישוב מעברי צבע

כעת נסתכל כיצד לחשב שיפועים על מנת למדוד את הקשר בין שינויים בתכונה לבין שינויים בתחזיות המודל. במקרה של תמונות, הגרדיאנט אומר לנו לאילו פיקסלים יש את ההשפעה החזקה ביותר על המודלים החזויים של הסתברויות מחלקות.

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

איפה:
\(F()\) = פונקציית החיזוי של המודל שלך
\(\frac{\partial{F} }{\partial{x_i} }\) = שיפוע (וקטור של נגזרות חלקיות \(\partial\)) של פונקציית החיזוי של הדגם F שלך ביחס לכל תכונה \(x_i\)

TensorFlow הופך את מעברי המחשוב לקלים עבורך עם 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)

הבה נחשב את ההדרגות עבור כל תמונה לאורך נתיב האינטרפולציה ביחס לפלט הנכון. זכור שהמודל שלך מחזיר Tensor בצורת (1, 1001) עם Tensor שאתה ממיר להסתברויות חזויות עבור כל מחלקה. עליך להעביר את אינדקס מחלקות היעד הנכון של ImageNet לפונקציה compute_gradients עבור התמונה שלך.

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

שימו לב לצורת הפלט של (n_interpolated_images, img_height, img_width, RGB) , שנותנת לנו את השיפוע עבור כל פיקסל של כל תמונה לאורך נתיב האינטרפולציה. אתה יכול לחשוב על שיפועים אלה כמדידת השינוי בתחזיות המודל שלך עבור כל צעד קטן במרחב התכונות.

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

הדמיית רוויה שיפועית

זכור שהשיפועים שזה עתה חישבת למעלה מתארים שינויים מקומיים בהסתברות החזויה של הדגם שלך ל"סירת אש" ויכולים להרוות .

מושגים אלה מומחשים באמצעות ההדרגות שחישבת למעלה ב-2 החלקות למטה.

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

png

  • משמאל : העלילה הזו מראה כיצד הביטחון של הדוגמנית שלך במחלקה "סירת אש" משתנה על פני אלפא. שימו לב כיצד השיפועים, או השיפוע של הקו, משתטחים או מרווים במידה רבה בין 0.6 ל-1.0 לפני התייצבות בהסתברות החזויה הסופית של "סירת האש" של כ-40%.

  • מימין : העלילה הימנית מציגה את גודלי ההדרגות הממוצעים על פני אלפא בצורה ישירה יותר. שימו לב כיצד הערכים מתקרבים בחדות ואפילו יורדים לזמן קצר מתחת לאפס. למעשה, המודל שלך "לומד" הכי הרבה מהדרגות בערכים נמוכים יותר של אלפא לפני הרוויה. באופן אינטואיטיבי, אתה יכול לחשוב על זה מכיוון שהמודל שלך למד את הפיקסלים, למשל תותחי מים כדי לבצע את החיזוי הנכון, לשלוח את שיפוע הפיקסלים הללו לאפס, אבל הוא עדיין די לא בטוח ומתמקד בפיקסלים מזויפים של גשר או סילון מים ככל שערכי האלפא מתקרבים ל- תמונת קלט מקורית.

כדי לוודא שהפיקסלים החשובים הללו של תותחי המים ישתקפו כחשובים לתחזית "סירת האש", תמשיך להלן כדי ללמוד כיצד לצבור שיפועים אלה כדי להעריך במדויק כיצד כל פיקסל משפיע על ההסתברות החזויה של "סירת האש".

צבירת שיפועים (קירוב אינטגרלי)

ישנן דרכים רבות ושונות שבהן אתה יכול ללכת על חישוב הקירוב המספרי של אינטגרל עבור IG עם פשרות שונות בדיוק והתכנסות בין פונקציות שונות. מחלקה פופולרית של שיטות נקראת סכומים של רימן . כאן תשתמש בכלל הטרפז (תוכל למצוא קוד נוסף כדי לחקור שיטות קירוב שונות בסוף מדריך זה).

$IntegratedGrads^{approx} {i}(x)::=(x {i}-x' {i})\times \overbrace{\sum {k=1}^{m} }^\text{Sum m מעברי צבע מקומיים} \text{gradients(interpolated images)} \times \overbrace{\frac{1}{m} }^\text{חלק ב-m שלבים}$

מהמשוואה, אתה יכול לראות שאתה מסכם מעל m שיפועים ומחלק ב- m צעדים. אתה יכול ליישם את שתי הפעולות יחד עבור חלק 3 כממוצע של הגרדיאנטים המקומיים של m תחזיות אינטרפולציה ותמונות קלט .

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

הפונקציה integral_approximation לוקחת את הגרדיאנטים של ההסתברות החזויה של מחלקת היעד ביחס לתמונות המשולבות בין קו הבסיס לתמונה המקורית.

ig = integral_approximation(
    gradients=path_gradients)

אתה יכול לאשר ממוצע על פני שיפועים של m תמונות אינטרפולציה מחזיר טנזור שיפועים משולב עם אותה צורה כמו התמונה המקורית של "פנדה ענקית".

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

מחברים את הכל ביחד

כעת תשלבו את 3 החלקים הכלליים הקודמים יחד לפונקציה IntegratedGradients ותשתמשו במעצב @tf.function כדי להרכיב אותו לגרף TensorFlow בעל ביצועים גבוהים. זה מיושם כ-5 שלבים קטנים יותר להלן:

\(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. צור אלפא \(\alpha\)

  2. צור תמונות משולבות = \((x' + \frac{k}{m}\times(x - x'))\)

  3. חישוב שיפועים בין תחזיות פלט של דגם \(F\) ביחס לתכונות קלט = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)

  4. קירוב אינטגרלי באמצעות ממוצע שיפועים = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)

  5. קנה מידה של מעברי צבע משולבים ביחס לתמונה המקורית = \((x_{i}-x'_{i}) \times \text{integrated gradients}\). הסיבה ששלב זה נחוץ היא לוודא שערכי הייחוס שנצברו על פני מספר תמונות משולבות נמצאים באותן יחידות ומייצגים נאמנה את חשיבות הפיקסלים בתמונה המקורית.

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)

שוב, אתה יכול לבדוק שלייחוס תכונות ה-IG יש את אותה צורה כמו לתמונת הקלט של "סירת האש".

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

המאמר מציע שמספר השלבים ינוע בין 20 ל-300 בהתאם לדוגמא (אם כי בפועל זה יכול להיות גבוה יותר באלף האלפים כדי להעריך במדויק את האינטגרל). תוכל למצוא קוד נוסף כדי לבדוק את מספר השלבים המתאים במשאבי "השלבים הבאים" בסוף מדריך זה.

דמיינו ייחוסים

אתה מוכן לדמיין ייחוסים, ולכסות אותם על התמונה המקורית. הקוד שלהלן מסכם את הערכים האבסולוטיים של ההדרגות המשולבות על פני ערוצי הצבע כדי לייצר מסכת ייחוס. שיטת רישום זו לוכדת את ההשפעה היחסית של פיקסלים על תחזיות המודל.

בהסתכלות על הייחוסים בתמונת "סירת האש", ניתן לראות את הדגם מזהה את תותחי המים והפיות כתורמים לתחזית הנכונה שלו.

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

בתמונת "פנדה ענקית", הייחוסים מדגישים את המרקם, האף והפרווה של פניה של הפנדה.

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

שימושים ומגבלות

מקרי שימוש

  • שימוש בטכניקות כמו Integrated Gradients לפני פריסת המודל שלך יכול לעזור לך לפתח אינטואיציה כיצד ולמה זה עובד. האם התכונות המודגשות בטכניקה זו תואמות את האינטואיציה שלך? אם לא, זה עשוי להעיד על באג במודל או במערך הנתונים שלך, או על התאמת יתר.

מגבלות

  • Gradients משולבים מספקים חשיבות תכונות בדוגמאות בודדות, עם זאת, היא אינה מספקת חשיבות תכונות גלובלית על פני מערך נתונים שלם.

  • Gradients משולבים מספקים חשיבות תכונות בודדות, אך הם אינם מסבירים אינטראקציות ושילובים של תכונות.

הצעדים הבאים

מדריך זה הציג יישום בסיסי של Integrated Gradients. כשלב הבא, תוכל להשתמש במחברת זו כדי לנסות את הטכניקה הזו עם דגמים ותמונות שונות בעצמך.

לקוראים המתעניינים, יש גרסה ארוכה יותר של הדרכה זו (הכוללת קוד לקווי בסיס שונים, לחישוב קירובים אינטגרלים ולקביעת מספר מספיק של שלבים) שתוכל למצוא כאן .

כדי להעמיק את ההבנה שלך, עיין במאמר Axiomatic Attribution for Deep Networks ומאגר Github , המכיל יישום בגרסה קודמת של TensorFlow. תוכל גם לחקור את ייחוס התכונות ואת ההשפעה של קווי בסיס שונים ב- distill.pub .

מעוניין לשלב IG בזרימות העבודה של למידת מכונה בייצור עבור חשיבות תכונות, ניתוח שגיאות מודל וניטור הטיית נתונים? בדוק את המוצר Explainable AI של Google Cloud התומך בייחוסי IG. קבוצת המחקר של Google AI PAIR גם הוציאה בקוד פתוח את הכלי What-if שניתן להשתמש בו לאיתור באגים במודל, כולל הדמיה של ייחוס תכונות IG.