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, Derin Ağlar için Axiomatic Attribution makalesinde tanıtılan Açıklanabilir bir AI tekniği olan Integrated Gradients'ın (IG) nasıl uygulanacağını gösterir. 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. Örnek olarak, su püskürten bir itfaiye gemisinin bu görüntüsünü düşünün. 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.
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 makalenin ruhuna uygun olarak, TensorFlow Hub'dan indireceğiniz aynı model Inception V1'in önceden eğitilmiş bir sürümünü kullanacaksınız.
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()
tutucu33 l10n-yerModel: "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:
Girdiler : Model için beklenen girdi şekli (None, 224, 224, 3)
şeklindedir. Bu, elemanları [0, 1] aralığına normalize edilmiş piksellerin RGB renk değerleri olan float32 ve şeklin (batch_size, height, width, RGB channels)
yoğun bir 4D tensörüdür. İlk öğe, modelin herhangi bir tamsayı parti boyutunu alabileceğini belirtmek için None
.
Çıktılar : ( tf.Tensor
(batch_size, 1001)
şeklinde bir logit tf.Tensor. Her satır, ImageNet'ten her 1,001 sınıfın her biri için modelin tahmin edilen puanını temsil eder. Modelin en yüksek tahmin edilen sınıf indeksi için tf.argmax(predictions, axis=-1)
kullanabilirsiniz. Ayrıca, modelin belirsizliğini ölçmek ve hata ayıklama için benzer tahmini sınıfları keşfetmek için tf.nn.softmax(predictions, axis=-1)
kullanarak modelin logit çıktısını tüm sınıflarda tahmin edilen olasılıklara dönüştürebilirsiniz.
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)
tutucu35 l10n-yerimagenet_labels = load_imagenet_labels('https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
Görüntüleri tf.image ile yükleyin ve tf.image
IG'yi Wikimedia Commons'tan iki resim kullanarak göstereceksiniz: bir Fireboat ve bir 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()}
yer tutucu38 l10n-yerDownloading 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()
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]
tutucu41 l10n-yerfor (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%}')
fireboat: 32.6% pier: 12.7% suspension bridge: 5.7%
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. Bununla birlikte, degradeler, piksel değerlerine göre modelinizin tahmin işlevindeki yalnızca yerel değişiklikleri tanımlar ve model tahmin işlevinizin tamamını tam olarak açıklamaz. Modeliniz, tek bir pikselin aralığı ile doğru ImageNet sınıfı arasındaki ilişkiyi tamamen "öğrendiğinde", bu pikselin gradyanı doygun hale gelir, yani giderek küçülür ve hatta sıfıra gider. 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();
left : Modelinizin
x
pikseli için gradyanları 0,0 ile 0,8 arasında pozitiftir, ancak 0,8 ile 1,0 arasında 0,0'a gider. Pixelx
, modelinizi gerçek sınıfta tahmin edilen %80 olasılığa doğru itmede belirgin bir etkisi vardır. Pikselx
öneminin küçük veya süreksiz olması mantıklı mı?sağ : IG'nin ardındaki sezgi, piksel
x
yerel gradyanlarını biriktirmek ve önemini, modelinizin genel çıktı sınıfı olasılığına ne kadar eklediği veya çıkardığıyla ilgili bir puan olarak atfetmektir. IG'yi 3 bölüme ayırabilir ve hesaplayabilirsiniz:- 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
- her adıma göre modelinizin tahminleri arasındaki her adımda gradyanları hesaplayın
- 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.
Deneyebileceğiniz diğer seçenekler arasında tamamen beyaz bir görüntü veya tf.random.uniform(shape=(224,224,3), minval=0.0, maxval=1.0)
ile oluşturabileceğiniz rastgele bir görüntü yer alır.
baseline = tf.zeros(shape=(224,224,3))
tutucu47 l10n-yerplt.imshow(baseline)
plt.title("Baseline")
plt.axis('off')
plt.show()
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}\) = özellik
\(x\) = giriş
\(x'\) = temel
\(\alpha\) = özellikleri bozmak için enterpolasyon sabiti
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}\) = özellik (bireysel piksel)
\(x\) = giriş (görüntü tensörü)
\(x'\) = taban çizgisi (görüntü tensörü)
\(k\) = ölçeklenmiş özellik bozulma sabiti
\(m\) = integralin Riemann toplamı yaklaşımındaki adım sayısı
\((x_{i}-x'_{i})\) = taban çizgisinden 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 düz bir çizgide (doğrusal dönüşüm) entegre ettiğiniz için bu, yeterli adımlarla \(\alpha\) göre enterpolasyonlu görüntü fonksiyonunun türevinin integral terimine kabaca eşdeğer olur. İntegral, her pikselin gradyanının yol boyunca pikseldeki değişikliğin toplamını alır. \(x := (x' + \alpha(x-x'))\)yerine bu entegrasyonu bir görüntüden diğerine tek tip adımlar olarak uygulamak daha kolaydır. Yani değişkenlerin değişimi \(dx = (x-x')d\alpha\)değerini verir. \((x-x')\) terimi sabittir ve integralin dışında tutulur.
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}\)
İlk olarak, taban çizgisi ile orijinal görüntü arasında doğrusal bir enterpolasyon oluşturacaksınız. Enterpolasyonlu görüntüleri, orijinal denklemde \(\alpha\) temsil edilen, taban çizginiz ve girdiniz arasındaki özellik alanındaki küçük adımlar olarak düşünebilirsiniz.
m_steps=50
alphas = tf.linspace(start=0.0, stop=1.0, num=m_steps+1) # Generate m_steps intervals for integral_approximation() below.
tutucu49 l10n-yerdef 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: \(\alpha\) sabiti hakkında düşünmenin başka bir yolu, interpolasyonlu her görüntünün yoğunluğunu sürekli olarak arttırması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();
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} }\) = F modelinizin her bir özelliğe göre tahmin fonksiyonunun gradyanı (kısmi türevlerin vektörü \(\partial\)) \(x_i\)
TensorFlow, bir tf.GradientTape
ile gradyan hesaplamayı sizin için kolaylaştırır.
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. Modelinizin, her sınıf için tahmin edilen olasılıklara dönüştürdüğünüz logitlerle (1, 1001)
şekilli bir Tensor
döndürdüğünü hatırlayın. Görüntünüz için doğru compute_gradients
hedef sınıf dizinini hesaplama_gradients işlevine iletmeniz gerekir.
path_gradients = compute_gradients(
images=interpolated_images,
target_class_idx=555)
(n_interpolated_images, img_height, img_width, RGB)
çıktı şekline dikkat edin, bu bize enterpolasyon yolu boyunca her görüntünün her pikseli için gradyanı 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)
tutucu55 l10n-yer(51, 224, 224, 3)
Gradyan doygunluğunu görselleştirme
Yukarıda hesapladığınız gradyanların, modelinizin tahmin edilen " Fireboat " olasılığındaki yerel değişiklikleri tanımladığını ve .
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]);
left : Bu grafik, modelinizin "Fireboat" sınıfına olan güveninin alfalar arasında nasıl değiştiğini 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ğdaki grafik, alfa üzerindeki ortalama gradyan büyüklüklerini daha doğrudan gösterir. 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. Popüler bir yöntem sınıfına Riemann toplamları denir. 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} {i}(x)::=(x {i}-x' {i})\times \overbrace{\sum {k=1}^{m} }^\text{Toplam m yerel gradyanlar} \text{gradients(enterpolasyonlu görüntüler)} \times \overbrace{\frac{1}{m} }^\text{m adıma bölün}$
Denklemden, m
gradyan üzerinde topladığınızı ve m
adıma böldüğünüzü görebilirsiniz. m
enterpolasyonlu tahminlerin ve girdi görüntülerinin yerel gradyanlarının ortalaması olarak 3. kısım için iki işlemi birlikte uygulayabilirsiniz .
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
işlevi, taban çizgisi ve orijinal görüntü arasındaki enterpolasyonlu görüntülere göre hedef sınıfın tahmin edilen olasılığının gradyanlarını alır.
ig = integral_approximation(
gradients=path_gradients)
m
enterpolasyonlu görüntünün gradyanları arasında ortalama almanın, orijinal "Dev Panda" görüntüsüyle aynı şekle sahip entegre bir gradyan tensörü döndürdüğünü onaylayabilirsiniz.
print(ig.shape)
tutucu61 l10n-yer(224, 224, 3)
Hepsini bir araya koy
Şimdi önceki 3 genel parçayı bir IntegratedGradients
işlevinde birleştirecek ve onu yüksek performanslı çağrılabilir bir TensorFlow grafiğinde derlemek için bir @tf.function dekoratörü kullanacaksınız. 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.}\)
Alfalar oluştur \(\alpha\)
Enterpolasyonlu görüntüler oluştur = \((x' + \frac{k}{m}\times(x - x'))\)
Girdi özelliklerine göre \(F\) model çıktı tahminleri arasındaki gradyanları hesaplayın = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)
Ortalama gradyanlar aracılığıyla integral yaklaşım = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)
Orijinal görüntüye göre entegre gradyanları ölçeklendir = \((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.
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
-yer tutucu64 l10n-yerig_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)
tutucu66 l10n-yer(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)
"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)
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.
İlgilenen okuyucular için, burada bulabileceğiniz bu öğreticinin daha uzun bir sürümü vardır (farklı taban çizgileri, integral yaklaşımları hesaplamak ve yeterli sayıda adım belirlemek için kod içerir).
Anlayışınızı derinleştirmek için, TensorFlow'un önceki bir sürümünde bir uygulama içeren Derin Ağlar ve Github deposu için Axiomatic Attribution belgesine göz atın. Distile.pub'da özellik ilişkilendirmesini ve farklı temellerin etkisini de keşfedebilirsiniz.
Ö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 IG özniteliklerini destekleyen Açıklanabilir AI ürününe göz atın. Google AI PAIR araştırma grubu ayrıca, IG özellik niteliklerini görselleştirmek de dahil olmak üzere model hata ayıklaması için kullanılabilen What-if aracını açık kaynaklı hale getirdi.