Yardım Kaggle üzerinde TensorFlow ile Büyük Bariyer Resifi korumak Meydan Üyelik

Entegre gradyanlar

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın GitHub'da görüntüle Not defterini indir TF Hub modeline bakın

Bu öğretici Entegre Degradeleri (IG), bir uygulamak gösterilmiştir açıklanabilir AI yazıda tanıtılan tekniği Derin Ağları için Aksiyomatik Atıf . IG, bir modelin tahminleri arasındaki ilişkiyi özellikleri açısından açıklamayı amaçlar. Özelliğin önemini anlama, veri eğriliğini belirleme ve model performansında hata ayıklama dahil olmak üzere birçok kullanım durumu vardır.

IG, herhangi bir türevlenebilir modele (örn. görüntüler, metin, yapılandırılmış veriler) geniş uygulanabilirliği, uygulama kolaylığı, teorik gerekçeler ve geniş ağlara ve özelliklere ölçeklenmesine izin veren alternatif yaklaşımlara göre hesaplama verimliliği nedeniyle popüler bir yorumlanabilirlik tekniği haline geldi. resimler gibi boşluklar.

Bu öğreticide, bir görüntü sınıflandırıcının piksel özelliğinin önemini anlamak için adım adım bir IG uygulamasını gözden geçireceksiniz. Bir örnek olarak, bu dikkate görseli su yangın söndürme püskürtme jetleri. Bu görüntüyü bir itfaiye gemisi olarak sınıflandırır ve kararınız için önemli olan tekneyi ve su toplarını oluşturan pikselleri vurgulayabilirsiniz. Modeliniz, bu öğreticide daha sonra bu resmi bir itfaiye gemisi olarak da sınıflandıracaktır; ancak, kararını açıklarken aynı pikselleri önemli olarak vurguluyor mu?

Aşağıdaki "IG Attribution Mask" ve "Orijinal + IG Mask Overlay" başlıklı resimlerde, modelinizin bunun yerine teknenin tazyikli sularını ve su jetlerini oluşturan pikselleri teknenin kendisinden daha önemli olarak vurguladığını (mor renkle) görebilirsiniz. onun kararı. Modeliniz yeni itfaiye teknelerine nasıl genellenecek? Su jeti olmayan itfaiye teknelerine ne dersiniz? IG'nin nasıl çalıştığı ve IG'nin modellerinize nasıl uygulanacağı hakkında daha fazla bilgi edinmek ve tahminler ile temel özellikler arasındaki ilişkiyi daha iyi anlamak için okumaya devam edin.

Çıktı Resmi 1

Kurmak

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

TF-Hub'dan önceden eğitilmiş bir görüntü sınıflandırıcı indirin

IG herhangi bir türevlenebilir modele uygulanabilir. Orijinal kağıdın ruhla, sen den indirecektir aynı model, Inception V1, önceden eğitilmiş sürümünü kullanacaktır 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
_________________________________________________________________

Modül sayfasından Inception V1 ile ilgili aşağıdakileri aklınızda tutmanız gerekir:

Girişler: model için beklenen giriş şekli (None, 224, 224, 3) . Bu d_type float32 ve şekli yoğun bir 4D tensör olan (batch_size, height, width, RGB channels) , öğeleri [0, 1] normalize piksel RGB renk değerleridir. İlk unsurdur None model, herhangi bir tamsayı toplu boyutunu alabilir belirtmek için.

Çıkışlar: Bir tf.Tensor şeklinde logits arasında (batch_size, 1001) . Her satır, ImageNet'ten her 1,001 sınıfın her biri için modelin tahmin edilen puanını temsil eder. Modelin üst tahmin sınıf indeksi için kullanabileceğiniz tf.argmax(predictions, axis=-1) . Ayrıca, aynı zamanda kullanarak tüm sınıflara tahmin ihtimallere modelin logit çıkış dönüştürebilir tf.nn.softmax(predictions, axis=-1) modelin belirsizlik ölçmek hem de ayıklama benzer tahmin edilen sınıfları keşfetmek için.

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')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt
16384/10484 [==============================================] - 0s 0us/step
24576/10484 [======================================================================] - 0s 0us/step

Yükleyin ve önişlem görüntüleri tf.image

Sen iki görüntüleri kullanarak IG gösterilecektir Wikimedia Commons a: fireboat ve Dev 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

Görüntüleri sınıflandırma

Bu görüntüleri sınıflandırarak ve en emin 3 tahmini göstererek başlayalım. Aşağıda, en iyi k tahmin edilen etiketi ve olasılığı almak için bir yardımcı fonksiyon bulunmaktadır.

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%

Entegre Gradyanları Hesapla

Modeliniz Inception V1, girdi özellik alanınız, görüntü piksel değerleri ve 0 ile 1 arasındaki ImageNet sınıfı olasılık değerleri tarafından tanımlanan bir çıktı alanı arasındaki bir eşlemeyi tanımlayan öğrenilmiş bir işlevdir. modelinizin tahmin işlevi boyunca belirli bir noktada modelinizin tahminine göre hangi piksellerin en dik yerele sahip olduğunu söyleyen gradyanlar. Ancak geçişlerinin yalnızca piksel değerleri açısından modelinizin tahmini işlevinde yerel değişiklikleri açıklamak ve tam tüm model tahmin işlevi tarif yoktur. Senin modeli olarak tamamen "öğrenip" Tek bir piksele aralığında ve doğru ImageNet sınıf arasındaki ilişki, doyuracak olan bu piksel için degrade gittikçe küçülmekte anlam ve hatta sıfıra gidin. Aşağıdaki basit model işlevini göz önünde bulundurun:

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)
fig = plt.figure(figsize=(12, 5))
ax0 = fig.add_subplot(121)
ax0.plot(x, f(x), marker='o')
ax0.set_title('Gradients saturate over F(x)', fontweight='bold')
ax0.text(0.2, 0.5, 'Gradients > 0 = \n x is important')
ax0.text(0.7, 0.85, 'Gradients = 0 \n x not important')
ax0.set_yticks(tf.range(0, 1.5, 0.5))
ax0.set_xticks(tf.range(0, 1.5, 0.5))
ax0.set_ylabel('F(x) - model true class predicted probability')
ax0.set_xlabel('x - (pixel value)')

ax1 = fig.add_subplot(122)
ax1.plot(x, f(x), marker='o')
ax1.plot(x, interpolated_path(x), marker='>')
ax1.set_title('IG intuition', fontweight='bold')
ax1.text(0.25, 0.1, 'Accumulate gradients along path')
ax1.set_ylabel('F(x) - model true class predicted probability')
ax1.set_xlabel('x - (pixel value)')
ax1.set_yticks(tf.range(0, 1.5, 0.5))
ax1.set_xticks(tf.range(0, 1.5, 0.5))
ax1.annotate('Baseline', xy=(0.0, 0.0), xytext=(0.0, 0.2),
             arrowprops=dict(facecolor='black', shrink=0.1))
ax1.annotate('Input', xy=(1.0, 0.0), xytext=(0.95, 0.2),
             arrowprops=dict(facecolor='black', shrink=0.1))
plt.show();

png

  • sol: Piksel İçin modelin geçişlerini x 0.0 ile 0.8 arasında pozitif ancak 0.8 ile 1.0 arasında 0.0 gidin. Piksel x açıkça gerçek sınıfına% 80 tahmin edilen olasılık doğru modelinizi iterek üzerinde önemli bir etkisi vardır. O piksel mantıklı mı x 'in önemi, küçük veya kesintili mi?

  • Sağ: IG arkasında sezgi için birikir piksel x 'in yerel gradyanları ve modelinizin genel çıkış sınıf olasılığına karşılık ekler veya çıkarır ne kadar bir skorla olarak önemini bağlıyor. IG'yi 3 bölüme ayırabilir ve hesaplayabilirsiniz:

    1. 0 (bir taban çizgisi veya başlangıç ​​noktası) ile 1 (giriş pikselinin değeri) arasındaki özellik alanında düz bir çizgi boyunca küçük adımları enterpolasyon yapın
    2. her adıma göre modelinizin tahminleri arasındaki her adımda gradyanları hesaplayın
    3. bu yerel gradyanları biriktirerek (kümülatif ortalama) taban çizginiz ve girdiniz arasındaki integrali yaklaşık olarak hesaplayın.

Bu sezgiyi güçlendirmek için, aşağıdaki örnek "Fireboat" görüntüsüne IG uygulayarak bu 3 bölümden geçeceksiniz.

Bir temel oluşturun

Taban çizgisi, özellik önemini hesaplamak için bir başlangıç ​​noktası olarak kullanılan bir girdi görüntüsüdür. Sezgisel olarak, giriş görüntüsünde mevcut olduğunda, her pikselin "Yangın Gemisi" tahmini üzerindeki etkisiyle kontrast oluşturmak için, temelin açıklayıcı rolünü, her pikselin yokluğunun "Yangın Gemisi" tahmini üzerindeki etkisini temsil ettiğini düşünebilirsiniz. Sonuç olarak, taban çizgisinin seçimi, piksel özelliğinin önemini yorumlamada ve görselleştirmede merkezi bir rol oynar. Temel seçimle ilgili ek tartışma için bu öğreticinin altındaki "Sonraki adımlar" bölümündeki kaynaklara bakın. Burada piksel değerlerinin tamamı sıfır olan siyah bir görüntü kullanacaksınız.

Eğer deneme olabilir Diğer seçenekler tüm beyaz bir görüntü ya da birlikte oluşturabilir rasgele resim, bir de 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

Formülleri kodda açın

Entegre Gradyanlar için formül aşağıdaki gibidir:

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

nerede:

\(_{i}\) = özelliği
\(x\) = giriş
\(x'\) = bazal
\(\alpha\) = karıştırmayı özelliklere interpolasyon sabiti tarafından

Pratikte, belirli bir integrali hesaplamak her zaman sayısal olarak mümkün değildir ve hesaplama açısından maliyetli olabilir, bu nedenle aşağıdaki sayısal yaklaşımı hesaplarsınız:

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

nerede:

\(_{i}\) = özelliği (tek tek piksel)
\(x\) = girişi (Resim tensör)
\(x'\) = taban (görüntü tensör)
\(k\) = ölçekli özelliği pertürbasyon sabiti
\(m\) integral Riemann toplamı yaklaşımında = adım sayısı
\((x_{i}-x'_{i})\) taban hattından bir fark için bir terim =. Bu, entegre gradyanları ölçeklendirmek ve orijinal görüntü açısından tutmak için gereklidir. Temel görüntüden girişe giden yol piksel uzayındadır. IG ile ilgili olarak ara değerli görüntü fonksiyonun türevi integral terimine kabaca eşdeğer kadar bir düz çizgi (lineer transformasyon) içerisinde bu uçlara entegre olduğundan \(\alpha\) yeterli adımlarla. İntegral, her pikselin gradyanının yol boyunca pikseldeki değişikliğin toplamını alır. Bu yerine bir görüntüden diğerine üniform adımlarda, bu bütünleşmeyi uygulamak basittir \(x := (x' + \alpha(x-x'))\). Yani değişkenlerin değişim verir \(dx = (x-x')d\alpha\). \((x-x')\) terimi sabittir ve integral üzerinden etki eder.

Görüntüleri enterpolasyonla

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

Önce, bir üretecektir lineer interpolasyon başlangıca ve orijinal görüntü arasındaki. Sen temsil referans aralığı ve girdi arasındaki özellik uzayda küçük adımlar olarak interpolated görüntülerin düşünebiliriz \(\alpha\) orijinal denklemde.

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

Siyah temel görüntü ile örnek "Fireboat" görüntüsü arasında alfa aralıklarında doğrusal bir yol boyunca enterpolasyonlu görüntüler oluşturmak için yukarıdaki işlevi kullanalım.

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

Şimdi enterpolasyonlu görüntüleri görselleştirelim. Not: düşünmenin başka bir yolu \(\alpha\) sabiti sürekli her interpole resmin yoğunluğunu artırmak olmasıdır.

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

Hesaplama gradyanları

Şimdi, bir özellikteki değişiklikler ile modelin tahminlerindeki değişiklikler arasındaki ilişkiyi ölçmek için gradyanların nasıl hesaplanacağına bir göz atalım. Görüntüler söz konusu olduğunda, gradyan bize modellerin tahmin edilen sınıf olasılıkları üzerinde hangi piksellerin en güçlü etkiye sahip olduğunu söyler.

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

nerede:
\(F()\) modelinizin tahmin işlevi =
\(\frac{\partial{F} }{\partial{x_i} }\) = gradyan: (kısmi türevlerinin vektör \(\partial\)her özellik için model F'nin kestirim işlevi nisbetle) \(x_i\)

TensorFlow bir kolay sizin için renk geçişlerini hesaplama yapar 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)

Doğru çıktıya göre enterpolasyon yolu boyunca her görüntü için gradyanları hesaplayalım. Hatırlama modeliniz döndürdüğünü bir (1, 1001) şeklindeki Tensor her sınıf için ön görülen olasılıklar dönüştürmek olduğunu logits ile. Sen doğru ImageNet hedef sınıf indeksi geçmesi gerekiyor compute_gradients Resminiz için işlevi.

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

Çıkış şekli dikkat (n_interpolated_images, img_height, img_width, RGB) bize interpolasyon yolu boyunca her görüntünün her bir piksel için değeri verir. Bu gradyanları, özellik alanındaki her küçük adım için modelinizin tahminlerindeki değişikliği ölçmek olarak düşünebilirsiniz.

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

Gradyan doygunluğunu görselleştirme

Sadece yukarıda hesaplanan geçişlerini "Fireboat" tutarındaki modelin tahmin olasılığına yerel değişiklikleri açıklamak ve doyurabilecek ki hatırlayın.

Bu kavramlar, yukarıda hesapladığınız gradyanlar kullanılarak aşağıdaki 2 grafikte görselleştirilmiştir.

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

plt.figure(figsize=(10, 4))
ax1 = plt.subplot(1, 2, 1)
ax1.plot(alphas, pred_proba)
ax1.set_title('Target class predicted probability over alpha')
ax1.set_ylabel('model p(target class)')
ax1.set_xlabel('alpha')
ax1.set_ylim([0, 1])

ax2 = plt.subplot(1, 2, 2)
# Average across interpolation steps
average_grads = tf.reduce_mean(path_gradients, axis=[1, 2, 3])
# Normalize gradients to 0 to 1 scale. E.g. (x - min(x))/(max(x)-min(x))
average_grads_norm = (average_grads-tf.math.reduce_min(average_grads))/(tf.math.reduce_max(average_grads)-tf.reduce_min(average_grads))
ax2.plot(alphas, average_grads_norm)
ax2.set_title('Average pixel gradients (normalized) over alpha')
ax2.set_ylabel('Average pixel gradients')
ax2.set_xlabel('alpha')
ax2.set_ylim([0, 1]);

png

  • sol: "Fireboat" sınıfında modelinizin güven alfalar göre nasıl farklılaştığını Bu arsa gösterir. Eğimlerin veya çizginin eğiminin, yaklaşık %40'lık nihai "Yangın Gemisi" tahmini olasılığına yerleşmeden önce 0,6 ile 1,0 arasında nasıl büyük ölçüde düzleştiğine veya doyduğuna dikkat edin.

  • Sağ: Sağ arsa gösterileri daha doğrudan alfa üzerinde ortalama geçişlerini büyüklükleri. Değerlerin nasıl keskin bir şekilde yaklaştığını ve hatta kısaca sıfırın altına düştüğünü not edin. Aslında, modeliniz doygunluktan önce daha düşük alfa değerlerindeki gradyanlardan en çok "öğrenir". Sezgisel olarak, bunu modeliniz pikselleri öğrendiği için düşünebilirsiniz, örneğin doğru tahmini yapmak için su topları, bu piksel gradyanlarını sıfıra gönderir, ancak yine de oldukça belirsizdir ve alfa değerleri yaklaştıkça sahte köprü veya su jeti piksellerine odaklanır. orijinal giriş görüntüsü.

Bu önemli su topu piksellerinin "Yangın Gemisi" tahmini için önemli olarak yansıtıldığından emin olmak için, her pikselin "Yangın Gemisi" tahmini olasılığınızı nasıl etkilediğini doğru bir şekilde yaklaşık olarak tahmin etmek için bu gradyanları nasıl biriktireceğinizi öğrenmek için aşağıda devam edeceksiniz.

Gradyanları biriktirin (tümleşik yaklaşım)

Farklı işlevler arasında doğruluk ve yakınsama açısından farklı ödünleşimlerle IG için bir integralin sayısal yaklaşımını hesaplamak için izleyebileceğiniz birçok farklı yol vardır. Yöntemlerin bir popüler sınıfı denir Riemann toplamları . Burada, Yamuk kuralını kullanacaksınız (bu öğreticinin sonunda farklı yaklaşım yöntemlerini keşfetmek için ek kod bulabilirsiniz).

$ IntegratedGrads ^ {yaklaşık} {ı} (x) :: = (x {i} -x {ı}) \ günlerin \ overbrace {\ toplamı {k = 1} ^ {m}} ^ \ metni {Miktar m yerel gradyanlar} \text{gradients(enterpolasyonlu görüntüler)} \times \overbrace{\frac{1}{m} }^\text{m adıma bölün}$

Denkleminin itibaren, baştan toplayarak edilir görebilirsiniz m geçişlerini ve bölerek m adımlar. Sen yerel gradyanlar ortalama olarak parçası 3 için bir araya iki işlemleri uygulayabilirsiniz m interpolated tahminler ve giriş görüntüleri.

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 fonksiyonu başlangıca ve orijinal görüntü arasındaki ara değerli görüntülere göre hedef sınıfın tahmin olasılık geçişlerini sürer.

ig = integral_approximation(
    gradients=path_gradients)

Sen oranında eğimlere genelinde ortalamasını teyit edebilir m entegre geçişlerini orijinal "Dev Panda" görüntü olarak aynı şekle sahip tensör interpolated görüntüleri getiri.

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

Hepsini bir araya koy

Artık bir bir araya 3 önceki genel parçaları birleştirecek IntegratedGradients fonksiyonu ve bir kullanan @ tf.function yüksek performanslı çağrılabilir TensorFlow grafiğini içine derlemek dekoratör. Bu, aşağıda 5 küçük adım olarak uygulanmaktadır:

\(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. Alfalar üret \(\alpha\)

  2. İnterpolated görüntüler = üret \((x' + \frac{k}{m}\times(x - x'))\)

  3. Model arasında hesaplayın gradyanlar \(F\) girişi ile ilgili çıkış tahminler bulunmaktadır = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)

  4. Ortalama gradyanlarından integral yaklaşım = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)

  5. Orijinal görüntü = göre entegre gradyanlar ölçekleme \((x_{i}-x'_{i}) \times \text{integrated gradients}\). Bu adımın gerekli olmasının nedeni, birden çok enterpolasyonlu görüntü arasında biriken öznitelik değerlerinin aynı birimlerde olduğundan ve orijinal görüntüdeki piksel önemlerini aslına uygun olarak temsil ettiğinden emin olmaktır.

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

  # Initialize TensorArray outside loop to collect gradients.    
  gradient_batches = tf.TensorArray(tf.float32, size=m_steps+1)

  # 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]

    # 2. Generate interpolated inputs between baseline and input.
    interpolated_path_input_batch = interpolate_images(baseline=baseline,
                                                       image=image,
                                                       alphas=alpha_batch)

    # 3. Compute gradients between model outputs and interpolated inputs.
    gradient_batch = compute_gradients(images=interpolated_path_input_batch,
                                       target_class_idx=target_class_idx)

    # Write batch indices and gradients to extend TensorArray.
    gradient_batches = gradient_batches.scatter(tf.range(from_, to), gradient_batch)    

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

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

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

  return integrated_gradients
ig_attributions = integrated_gradients(baseline=baseline,
                                       image=img_name_tensors['Fireboat'],
                                       target_class_idx=555,
                                       m_steps=240)

Yine, IG özellik niteliklerinin giriş "Fireboat" görüntüsüyle aynı şekle sahip olduğunu kontrol edebilirsiniz.

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

Kağıt, örneğe bağlı olarak 20 ila 300 arasında değişen adım sayısını önerir (ancak pratikte bu, integrali doğru bir şekilde yaklaşık olarak tahmin etmek için 1000'lerde daha yüksek olabilir). Bu öğreticinin sonundaki "Sonraki adımlar" kaynaklarında uygun sayıda adım olup olmadığını kontrol etmek için ek kod bulabilirsiniz.

Nitelikleri görselleştirin

Nitelikleri görselleştirmeye ve orijinal görüntünün üzerine yerleştirmeye hazırsınız. Aşağıdaki kod, bir nitelik maskesi oluşturmak için renk kanallarındaki entegre degradelerin mutlak değerlerini toplar. Bu çizim yöntemi, piksellerin modelin tahminleri üzerindeki göreli etkisini yakalar.

def plot_img_attributions(baseline,
                          image,
                          target_class_idx,
                          m_steps=50,
                          cmap=None,
                          overlay_alpha=0.4):

  attributions = integrated_gradients(baseline=baseline,
                                      image=image,
                                      target_class_idx=target_class_idx,
                                      m_steps=m_steps)

  # Sum of the attributions across color channels for visualization.
  # The attribution mask shape is a grayscale image with height and width
  # equal to the original image.
  attribution_mask = tf.reduce_sum(tf.math.abs(attributions), axis=-1)

  fig, axs = plt.subplots(nrows=2, ncols=2, squeeze=False, figsize=(8, 8))

  axs[0, 0].set_title('Baseline image')
  axs[0, 0].imshow(baseline)
  axs[0, 0].axis('off')

  axs[0, 1].set_title('Original image')
  axs[0, 1].imshow(image)
  axs[0, 1].axis('off')

  axs[1, 0].set_title('Attribution mask')
  axs[1, 0].imshow(attribution_mask, cmap=cmap)
  axs[1, 0].axis('off')

  axs[1, 1].set_title('Overlay')
  axs[1, 1].imshow(attribution_mask, cmap=cmap)
  axs[1, 1].imshow(image, alpha=overlay_alpha)
  axs[1, 1].axis('off')

  plt.tight_layout()
  return fig

"İtfaiye Teknesi" resmindeki niteliklere bakıldığında, modelin tazyikli su tabancalarını ve musluğu doğru tahminine katkıda bulunduğunu tespit ettiğini görebilirsiniz.

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

"Dev Panda" resminde, nitelikler Panda'nın yüzünün dokusunu, burnunu ve kürkünü vurgular.

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

Kullanımlar ve sınırlamalar

Kullanım durumları

  • Modelinizi dağıtmadan önce Integrated Gradients gibi teknikleri kullanmak, nasıl ve neden çalıştığına dair sezgi geliştirmenize yardımcı olabilir. Bu teknikle vurgulanan özellikler sezgilerinizle uyuşuyor mu? Değilse, bu, modelinizdeki veya veri kümenizdeki bir hatanın veya fazla uyumun göstergesi olabilir.

sınırlamalar

  • Entegre Gradyanlar, tek tek örneklerde özellik önemleri sağlar, ancak tüm veri kümesinde genel özellik önemleri sağlamaz.

  • Entegre Gradyanlar, bireysel özellik önemleri sağlar, ancak özellik etkileşimlerini ve kombinasyonlarını açıklamaz.

Sonraki adımlar

Bu öğretici, Integrated Gradients'ın temel bir uygulamasını sundu. Bir sonraki adım olarak, bu tekniği farklı model ve resimlerle kendiniz denemek için bu not defterini kullanabilirsiniz.

İlgi duyan okuyucular için bulabilirsiniz (ayrılmaz yaklaşımları hesaplamak için, ve adımların yeterli sayıda belirlemek için, farklı taban için kod içerir) bu yazının daha uzun sürecek bir sürümü var burada .

, İyi anlamanızı kağıdı kontrol etmek Derin Ağları için Aksiyomatik Atıf ve Github depo TensorFlow bir önceki sürümünde uygulamasını içeren,. Ayrıca özellik atıf ve farklı taban etkisini keşfedebilirsiniz distill.pub .

Özellik önemleri, model hatası analizi ve veri eğriliği izleme için üretim makine öğrenimi iş akışlarınıza IG'yi dahil etmekle ilgileniyor musunuz? Google Cloud'un göz atın açıklanabilir AI IG atıfları desteklediği ürünü. Google AI EŞLE araştırma grubu da açık kaynaklı Ne-eğer aracı IG özelliği atıfları görselleştirme dahil, model hata ayıklama için kullanılabilir.