TensorFlow.org पर देखें | Google Colab में चलाएं | गिटहब पर देखें | नोटबुक डाउनलोड करें | टीएफ हब मॉडल देखें |
यह ट्यूटोरियल दर्शाता है कि इंटीग्रेटेड ग्रेडिएंट्स (IG) को कैसे लागू किया जाए, जो कि डीप नेटवर्क्स के लिए एक्सियोमैटिक एट्रिब्यूशन पेपर में पेश की गई एक व्याख्यात्मक एआई तकनीक है। IG का उद्देश्य मॉडल की भविष्यवाणियों के बीच संबंधों को उसकी विशेषताओं के संदर्भ में समझाना है। इसमें कई उपयोग के मामले हैं जिनमें फीचर महत्व को समझना, डेटा तिरछा की पहचान करना और मॉडल के प्रदर्शन को डीबग करना शामिल है।
IG किसी भी भिन्न मॉडल (जैसे चित्र, पाठ, संरचित डेटा), कार्यान्वयन में आसानी, सैद्धांतिक औचित्य, और वैकल्पिक दृष्टिकोणों के सापेक्ष कम्प्यूटेशनल दक्षता के लिए व्यापक प्रयोज्यता के कारण एक लोकप्रिय व्याख्यात्मक तकनीक बन गया है जो इसे बड़े नेटवर्क और सुविधा के पैमाने पर अनुमति देता है। छवियों जैसे रिक्त स्थान।
इस ट्यूटोरियल में, आप इमेज क्लासिफायरियर के पिक्सेल फीचर महत्व को समझने के लिए IG के चरण-दर-चरण कार्यान्वयन के माध्यम से चलेंगे। एक उदाहरण के रूप में, पानी के जेट स्प्रेइंग फायरबोट की इस छवि पर विचार करें। आप इस छवि को एक फायरबोट के रूप में वर्गीकृत करेंगे और आपके निर्णय के लिए महत्वपूर्ण होने के नाते नाव और पानी के तोपों को बनाने वाले पिक्सेल को हाइलाइट कर सकते हैं। आपका मॉडल बाद में इस ट्यूटोरियल में इस छवि को फायरबोट के रूप में वर्गीकृत करेगा; हालांकि, क्या यह अपने निर्णय की व्याख्या करते समय समान पिक्सेल को महत्वपूर्ण के रूप में उजागर करता है?
"आईजी एट्रिब्यूशन मास्क" और "ओरिजिनल + आईजी मास्क ओवरले" शीर्षक से नीचे की छवियों में आप देख सकते हैं कि आपका मॉडल इसके बजाय (बैंगनी रंग में) नाव के पानी के तोपों और पानी के जेट वाले पिक्सल को नाव से अधिक महत्वपूर्ण होने के रूप में हाइलाइट करता है। उसका निर्णय। आपका मॉडल नई फ़ायरबोट्स के लिए सामान्यीकरण कैसे करेगा? पानी के जेट के बिना फायरबोट्स के बारे में क्या? इस बारे में अधिक जानने के लिए पढ़ें कि IG कैसे काम करता है और IG को अपने मॉडलों पर कैसे लागू किया जाए ताकि उनकी भविष्यवाणियों और अंतर्निहित विशेषताओं के बीच संबंधों को बेहतर ढंग से समझा जा सके।
सेट अप
import matplotlib.pylab as plt
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub
TF-Hub से एक पूर्व-प्रशिक्षित छवि क्लासिफायरियर डाउनलोड करें
IG को किसी भी भिन्न मॉडल पर लागू किया जा सकता है। मूल पेपर की भावना में, आप उसी मॉडल, इंसेप्शन V1 के पूर्व-प्रशिक्षित संस्करण का उपयोग करेंगे, जिसे आप TensorFlow हब से डाउनलोड करेंगे।
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 _________________________________________________________________
मॉड्यूल पेज से, आपको इंसेप्शन V1 के बारे में निम्नलिखित बातों को ध्यान में रखना होगा:
इनपुट : मॉडल के लिए अपेक्षित इनपुट आकार (None, 224, 224, 3)
है। यह dtype float32 और आकार (batch_size, height, width, RGB channels)
का एक घना 4D टेंसर है, जिसके तत्व [0, 1] की सीमा के लिए सामान्यीकृत पिक्सेल के RGB रंग मान हैं। पहला तत्व None
है यह इंगित करने के लिए कि मॉडल कोई पूर्णांक बैच आकार ले सकता है।
आउटपुट : (batch_size, 1001)
के आकार में लॉग का एक tf.Tensor
। प्रत्येक पंक्ति इमेजनेट से 1,001 वर्गों में से प्रत्येक के लिए मॉडल के अनुमानित स्कोर का प्रतिनिधित्व करती है। मॉडल के शीर्ष पूर्वानुमानित वर्ग अनुक्रमणिका के लिए आप 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)
35 एल10एन-प्लेसहोल्डरimagenet_labels = load_imagenet_labels('https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')
tf.image
के साथ छवियों को लोड और प्रीप्रोसेस करें
आप विकिमीडिया कॉमन्स से दो छवियों का उपयोग करके IG का वर्णन करेंगे: एक फायरबोट और एक विशालकाय पांडा ।
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()
छवियों को वर्गीकृत करें
आइए इन छवियों को वर्गीकृत करके और शीर्ष 3 सबसे भरोसेमंद भविष्यवाणियों को प्रदर्शित करके शुरू करें। शीर्ष k अनुमानित लेबल और संभावनाओं को पुनः प्राप्त करने के लिए एक उपयोगिता फ़ंक्शन निम्नलिखित है।
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%}')
fireboat: 32.6% pier: 12.7% suspension bridge: 5.7%
giant panda: 89.4% teddy: 0.3% gibbon: 0.3%
एकीकृत ग्रेडिएंट की गणना करें
आपका मॉडल, इंसेप्शन V1, एक सीखा हुआ फ़ंक्शन है जो आपके इनपुट फीचर स्पेस, इमेज पिक्सेल वैल्यू और इमेजनेट क्लास प्रायिकता मानों द्वारा परिभाषित आउटपुट स्पेस के बीच मैपिंग का वर्णन करता है। ग्रेडिएंट, जो आपको बताते हैं कि आपके मॉडल के पूर्वानुमान फ़ंक्शन के साथ दिए गए बिंदु पर आपके मॉडल की भविष्यवाणी के सापेक्ष कौन से पिक्सेल का सबसे अधिक स्थानीय सापेक्ष है। हालांकि, ग्रेडिएंट केवल पिक्सेल मानों के संबंध में आपके मॉडल के पूर्वानुमान फ़ंक्शन में स्थानीय परिवर्तनों का वर्णन करते हैं और आपके संपूर्ण मॉडल पूर्वानुमान फ़ंक्शन का पूरी तरह से वर्णन नहीं करते हैं। जैसे ही आपका मॉडल एक व्यक्तिगत पिक्सेल की सीमा और सही इमेजनेट वर्ग के बीच संबंध को पूरी तरह से "सीखता" है, इस पिक्सेल के लिए ढाल संतृप्त हो जाएगा, जिसका अर्थ तेजी से छोटा हो जाएगा और यहां तक कि शून्य हो जाएगा। नीचे दिए गए सरल मॉडल फ़ंक्शन पर विचार करें:
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();
बाएं : पिक्सेल
x
के लिए आपके मॉडल के ग्रेडिएंट 0.0 और 0.8 के बीच सकारात्मक हैं लेकिन 0.8 और 1.0 के बीच 0.0 पर जाएं। पिक्सेलx
स्पष्ट रूप से आपके मॉडल को वास्तविक वर्ग पर 80% अनुमानित संभावना की ओर धकेलने पर महत्वपूर्ण प्रभाव डालता है। क्या यह समझ में आता है कि पिक्सेलx
का महत्व छोटा या असंतत है?दाएं : IG के पीछे का अंतर्ज्ञान पिक्सेल
x
के स्थानीय ग्रेडिएंट्स को जमा करना है और इसके महत्व को एक स्कोर के रूप में बताता है कि यह आपके मॉडल के समग्र आउटपुट क्लास प्रायिकता में कितना जोड़ता या घटाता है। आप IG को 3 भागों में विभाजित और गणना कर सकते हैं:- 0 (बेसलाइन या शुरुआती बिंदु) और 1 (इनपुट पिक्सेल का मान) के बीच फ़ीचर स्पेस में एक सीधी रेखा के साथ छोटे चरणों को प्रक्षेपित करें
- प्रत्येक चरण के संबंध में अपने मॉडल की भविष्यवाणियों के बीच प्रत्येक चरण पर ग्रेडिएंट की गणना करें
- इन स्थानीय ग्रेडिएंट्स को जमा करके (संचयी औसत) अपने बेसलाइन और इनपुट के बीच इंटीग्रल का अनुमान लगाएं।
इस अंतर्ज्ञान को सुदृढ़ करने के लिए, आप नीचे दिए गए उदाहरण "फायरबोट" छवि में IG को लागू करके इन 3 भागों से गुजरेंगे।
आधार रेखा स्थापित करें
बेसलाइन एक इनपुट इमेज है जिसका उपयोग फीचर महत्व की गणना के लिए शुरुआती बिंदु के रूप में किया जाता है। सहज रूप से, आप बेसलाइन की व्याख्यात्मक भूमिका के बारे में सोच सकते हैं कि "फायरबोट" भविष्यवाणी पर प्रत्येक पिक्सेल की अनुपस्थिति के प्रभाव का प्रतिनिधित्व करने के लिए इनपुट छवि में मौजूद होने पर "फायरबोट" भविष्यवाणी पर प्रत्येक पिक्सेल के प्रभाव के विपरीत। नतीजतन, बेसलाइन का चुनाव पिक्सेल फीचर महत्व की व्याख्या और कल्पना करने में एक केंद्रीय भूमिका निभाता है। आधारभूत चयन की अतिरिक्त चर्चा के लिए, इस ट्यूटोरियल के निचले भाग में "अगले चरण" अनुभाग में संसाधन देखें। यहां, आप एक काली छवि का उपयोग करेंगे जिसका पिक्सेल मान सभी शून्य है।
अन्य विकल्प जिनके साथ आप प्रयोग कर सकते हैं उनमें एक पूरी सफेद छवि, या एक यादृच्छिक छवि शामिल है, जिसे आप 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()
फ़ार्मुलों को कोड में अनपैक करें
एकीकृत ग्रेडिएंट का सूत्र इस प्रकार है:
\(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}\) 2 = फीचर
\(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'\) 9 = बेसलाइन (छवि टेंसर)
\(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();
गणना ग्रेडिएंट
अब आइए एक नज़र डालते हैं कि किसी फीचर में बदलाव और मॉडल की भविष्यवाणियों में बदलाव के बीच संबंध को मापने के लिए ग्रेडिएंट की गणना कैसे करें। छवियों के मामले में, ग्रेडिएंट हमें बताता है कि किस पिक्सेल का मॉडल की अनुमानित वर्ग संभावनाओं पर सबसे अधिक प्रभाव पड़ता है।
\(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)
आइए सही आउटपुट के संबंध में प्रक्षेप पथ के साथ प्रत्येक छवि के लिए ग्रेडिएंट की गणना करें। याद रखें कि आपका मॉडल लॉग के साथ एक (1, 1001)
आकार का Tensor
लौटाता है जिसे आप प्रत्येक वर्ग के लिए अनुमानित संभावनाओं में परिवर्तित करते हैं। आपको अपनी इमेज के लिए सही इमेजनेट टारगेट क्लास इंडेक्स को 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]
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]);
बायां : यह प्लॉट दिखाता है कि "फ़ायरबोट" वर्ग में आपके मॉडल का विश्वास कैसे भिन्न होता है। ध्यान दें कि अंतिम "फायरबोट" में लगभग 40% की अनुमानित संभावना पर बसने से पहले ग्रेडिएंट, या लाइन का ढलान, मोटे तौर पर 0.6 और 1.0 के बीच कैसे चपटा या संतृप्त होता है।
दाएं : दायां प्लॉट अल्फा पर औसत ग्रेडियेंट परिमाण को अधिक सीधे दिखाता है। ध्यान दें कि कैसे मूल्य तेजी से पहुंचते हैं और यहां तक कि संक्षेप में शून्य से नीचे गिर जाते हैं। वास्तव में, आपका मॉडल संतृप्त होने से पहले अल्फा के निचले मूल्यों पर ग्रेडियेंट से सबसे ज्यादा "सीखता है"। सहज रूप से, आप इसके बारे में सोच सकते हैं क्योंकि आपके मॉडल ने पिक्सेल सीखे हैं, उदाहरण के लिए पानी के तोपों ने सही भविष्यवाणी करने के लिए, इन पिक्सेल ग्रेडिएंट्स को शून्य पर भेज दिया है, लेकिन अभी भी काफी अनिश्चित है और नकली ब्रिज या वॉटर जेट पिक्सल पर केंद्रित है क्योंकि अल्फा मान निकट आते हैं। मूल इनपुट छवि।
यह सुनिश्चित करने के लिए कि ये महत्वपूर्ण वाटर कैनन पिक्सल "फायरबोट" भविष्यवाणी के लिए महत्वपूर्ण के रूप में परिलक्षित होते हैं, आप नीचे यह सीखना जारी रखेंगे कि इन ग्रेडिएंट्स को कैसे सटीक रूप से अनुमानित किया जाए कि प्रत्येक पिक्सेल आपकी "फायरबोट" की भविष्यवाणी की संभावना को कैसे प्रभावित करता है।
संचित ग्रेडिएंट्स (अभिन्न सन्निकटन)
आईजी के लिए एक इंटीग्रल के संख्यात्मक सन्निकटन की गणना के बारे में कई अलग-अलग तरीके हैं, अलग-अलग कार्यों में सटीकता और अभिसरण में विभिन्न ट्रेडऑफ के साथ। विधियों के एक लोकप्रिय वर्ग को रीमैन सम्स कहा जाता है। यहां, आप समलम्बाकार नियम का उपयोग करेंगे (आप इस ट्यूटोरियल के अंत में विभिन्न सन्निकटन विधियों का पता लगाने के लिए अतिरिक्त कोड पा सकते हैं)।
$IntegratedGrads^{लगभग} {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{divid by m steps}$
समीकरण से, आप देख सकते हैं कि आप m
ग्रेडिएंट को जोड़ रहे हैं और m
चरणों से विभाजित कर रहे हैं। आप m
इंटरपोलेटेड भविष्यवाणियों और इनपुट छवियों के स्थानीय ग्रेडिएंट्स के औसत के रूप में भाग 3 के लिए दो ऑपरेशनों को एक साथ लागू कर सकते हैं।
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
ग्रेडिएंट फ़ंक्शन में जोड़ देंगे और एक उच्च प्रदर्शन कॉल करने योग्य TensorFlow ग्राफ़ में संकलित करने के लिए @tf.function डेकोरेटर का उपयोग करेंगे। इसे नीचे 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.}\)
अल्फ़ाज़ उत्पन्न करें \(\alpha\)
प्रक्षेपित चित्र उत्पन्न करें = \((x' + \frac{k}{m}\times(x - x'))\)
इनपुट सुविधाओं के संबंध में मॉडल \(F\) आउटपुट पूर्वानुमानों के बीच ग्रेडिएंट की गणना करें = \(\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i} }\)
औसत ग्रेडिएंट्स के माध्यम से इंटीग्रल सन्निकटन = \(\sum_{k=1}^m \text{gradients} \times \frac{1}{m}\)
मूल छवि = \((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 फीचर एट्रिब्यूशन का आकार इनपुट "Fireboat" इमेज के समान है।
print(ig_attributions.shape)
(224, 224, 3)
पेपर उदाहरण के आधार पर 20 से 300 के बीच के चरणों की संख्या का सुझाव देता है (हालांकि व्यवहार में यह इंटीग्रल को सटीक रूप से अनुमानित करने के लिए 1,000 में अधिक हो सकता है)। आप इस ट्यूटोरियल के अंत में "अगले चरण" संसाधनों में उचित संख्या में चरणों की जांच करने के लिए अतिरिक्त कोड पा सकते हैं।
गुणों की कल्पना करें
आप एट्रिब्यूशन की कल्पना करने और उन्हें मूल छवि पर ओवरले करने के लिए तैयार हैं। नीचे दिया गया कोड एट्रिब्यूशन मास्क बनाने के लिए सभी रंग चैनलों में एकीकृत ग्रेडिएंट के निरपेक्ष मानों का योग करता है। यह प्लॉटिंग विधि मॉडल की भविष्यवाणियों पर पिक्सेल के सापेक्ष प्रभाव को पकड़ती है।
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
"फ़ायरबोट" छवि पर एट्रिब्यूशन को देखते हुए, आप देख सकते हैं कि मॉडल पानी के तोपों और टोंटी की सही भविष्यवाणी में योगदान के रूप में पहचान करता है।
_ = 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)
"विशालकाय पांडा" छवि पर, विशेषताएँ पांडा के चेहरे की बनावट, नाक और फर को उजागर करती हैं।
_ = 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)
उपयोग और सीमाएं
बक्सों का इस्तेमाल करें
- अपने मॉडल को लागू करने से पहले एकीकृत ग्रेडिएंट जैसी तकनीकों को नियोजित करने से आपको यह समझने में मदद मिल सकती है कि यह कैसे और क्यों काम करता है। क्या इस तकनीक द्वारा हाइलाइट की गई विशेषताएं आपके अंतर्ज्ञान से मेल खाती हैं? यदि नहीं, तो यह आपके मॉडल या डेटासेट में बग या ओवरफिटिंग का संकेत हो सकता है।
सीमाओं
एकीकृत ग्रेडियेंट व्यक्तिगत उदाहरणों पर फीचर महत्व प्रदान करता है, हालांकि, यह संपूर्ण डेटासेट में वैश्विक फीचर महत्व प्रदान नहीं करता है।
एकीकृत ग्रेडियेंट व्यक्तिगत विशेषता महत्व प्रदान करता है, लेकिन यह फीचर इंटरैक्शन और संयोजनों की व्याख्या नहीं करता है।
अगले कदम
इस ट्यूटोरियल ने इंटीग्रेटेड ग्रैडिएंट्स का एक बुनियादी कार्यान्वयन प्रस्तुत किया। अगले चरण के रूप में, आप इस तकनीक को विभिन्न मॉडलों और छवियों के साथ स्वयं आज़माने के लिए इस नोटबुक का उपयोग कर सकते हैं।
इच्छुक पाठकों के लिए, इस ट्यूटोरियल का एक लंबा संस्करण है (जिसमें विभिन्न बेसलाइन के लिए कोड शामिल है, अभिन्न अनुमानों की गणना करने के लिए, और पर्याप्त संख्या में चरणों को निर्धारित करने के लिए) जो आप यहां पा सकते हैं।
अपनी समझ को गहरा करने के लिए, डीप नेटवर्क्स और जीथब रिपॉजिटरी के लिए एक्सियोमैटिक एट्रिब्यूशन पेपर देखें, जिसमें टेंसरफ्लो के पिछले संस्करण में कार्यान्वयन शामिल है। आप distill.pub पर फीचर एट्रिब्यूशन और विभिन्न बेसलाइन के प्रभाव का भी पता लगा सकते हैं।
फीचर महत्व, मॉडल त्रुटि विश्लेषण, और डेटा तिरछा निगरानी के लिए अपने उत्पादन मशीन सीखने के वर्कफ़्लो में IG को शामिल करने के इच्छुक हैं? IG एट्रिब्यूशन का समर्थन करने वाले Google क्लाउड के स्पष्टीकरण योग्य AI उत्पाद देखें। Google AI PAIR अनुसंधान समूह ने व्हाट-इफ टूल को भी ओपन-सोर्स किया है जिसका उपयोग मॉडल डिबगिंग के लिए किया जा सकता है, जिसमें IG फीचर एट्रिब्यूशन की कल्पना करना शामिल है।