Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/ko/tutorials/interpretability/integrated_gradients.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ๋”ฅ ๋„คํŠธ์›Œํฌ์— ๋Œ€ํ•œ ๊ณต๋ฆฌ์  ์†์„ฑ ๋…ผ๋ฌธ์— ์†Œ๊ฐœ๋œ Explainable AI ๊ธฐ์ˆ ์ธ **ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ(IG)**๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. IG๋Š” ํ•ด๋‹น ํŠน์„ฑ์˜ ๊ด€์ ์—์„œ ๋ชจ๋ธ ์˜ˆ์ธก ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฐ ๋ชฉ์ ์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน์„ฑ์˜ ์ค‘์š”์„ฑ ์ดํ•ด, ๋ฐ์ดํ„ฐ ๊ธฐ์šธ์ž„ ์‹๋ณ„ ๋ฐ ๋ชจ๋ธ ์„ฑ๋Šฅ ๋””๋ฒ„๊น…์„ ํฌํ•จํ•œ ๋งŽ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

IG๋Š” ๋‹ค์–‘ํ•œ ๋ชจ๋ธ(์˜ˆ: ์ด๋ฏธ์ง€, ํ…์ŠคํŠธ, ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ)์— ๋Œ€ํ•œ ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ, ๊ตฌํ˜„์˜ ์šฉ์ด์„ฑ, ์ด๋ก ์  ๊ทผ๊ฑฐ ๋ฐ ๋Œ€๊ทœ๋ชจ ๋„คํŠธ์›Œํฌ์™€ ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ์š”์†Œ ๊ณต๊ฐ„์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ฒด ์ ‘๊ทผ ๋ฐฉ์‹์— ์ƒ๋Œ€์ ์ธ ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์— ํž˜์ž…์–ด ๋„๋ฆฌ ํ†ต์šฉ๋˜๋Š” ํ•ด์„ ๊ธฐ์ˆ ๋กœ ์ž๋ฆฌ ์žก์•˜์Šต๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” IG์˜ ๋‹จ๊ณ„๋ณ„ ๊ตฌํ˜„์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜์ž์˜ ํ”ฝ์…€ ์š”์†Œ๊ฐ€ ๊ฐ–๋Š” ์ค‘์š”๋„๋ฅผ ์ดํ•ดํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฌผ์„ ๋ถ„์‚ฌํ•˜๋Š” ์†Œ๋ฐฉ์„ ์„ ๋‚˜ํƒ€๋‚ธ ์ด ์ด๋ฏธ์ง€๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”. ์ด ์ด๋ฏธ์ง€๋Š” ์†Œ๋ฐฉ์„ ์œผ๋กœ ๋ถ„๋ฅ˜๋  ๊ฒƒ์ด๊ณ  ์ด๋Ÿฌํ•œ ๊ฒฐ์ •์„ ๋‚ด๋ฆฐ ๋ฐ๋Š” ๋ณดํŠธ์™€ ๋ฌผ ๋Œ€ํฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ”ฝ์…€์ด ์ค‘์š”ํ•˜๊ฒŒ ์ž‘์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•Œ์•„๋ณผ ๋ชจ๋ธ๋„ ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋’ท๋ถ€๋ถ„์—์„œ ์ด ์ด๋ฏธ์ง€๋ฅผ ์†Œ๋ฐฉ์„ ์œผ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฒฐ์ •์„ ์„ค๋ช…ํ•  ๋•Œ ์ค‘์š”ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ”ฝ์…€์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๊นŒ?

"IG Attribution Mask" ๋ฐ "Original + IG Mask Overlay" ์ œ๋ชฉ์˜ ์•„๋ž˜ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋ธ์€ ์ด ๊ฒฐ์ •์„ ๋‚ด๋ฆด ๋•Œ ๋ณดํŠธ์˜ ๋ฌผ ๋Œ€ํฌ์™€ ๋ฌผ ์ œํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํ”ฝ์…€์„ ๋ณดํŠธ ์ž์ฒด๋ณด๋‹ค ๋” ์ค‘์š”ํ•˜๊ฒŒ ๊ฐ•์กฐ(๋ณด๋ผ์ƒ‰)ํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์ด ์ƒˆ๋กœ์šด ์†Œ๋ฐฉ์„ ์œผ๋กœ ์ผ๋ฐ˜ํ™”ํ•˜๋Š” ๋ฐฉ์‹์€ ๋ฌด์—‡์ผ๊นŒ์š”? ๋ฌผ ์ œํŠธ๊ฐ€ ์—†๋Š” ์†Œ๋ฐฉ์„ ์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ๊ณ„์†ํ•ด์„œ IG์˜ ์ž‘๋™ ๋ฐฉ์‹๊ณผ ๋ชจ๋ธ์— IG๋ฅผ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ณ  ์˜ˆ์ธก๊ณผ ๊ธฐ๋ณธ ํŠน์„ฑ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Output Image 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()

๋ชจ๋“ˆ ํŽ˜์ด์ง€์—์„œ Inception V1์— ๊ด€ํ•œ ๋‹ค์Œ ์‚ฌํ•ญ์„ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ž…๋ ฅ: ๋ชจ๋ธ์˜ ์˜ˆ์ƒ ์ž…๋ ฅ ํ˜•์ƒ์€ (None, 224, 244, 3,)์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํ˜•์‹์ด float32์ด๊ณ  ํ˜•์ƒ์ด (batch_size, height, width, RGB channels)(ํ•ด๋‹น ์š”์†Œ๋Š” [0, 1] ๋ฒ”์œ„๋กœ ์ •๊ทœํ™”๋œ ํ”ฝ์…€์˜ RGB ์ƒ‰์ƒ ๊ฐ’์ž„)์ธ ๋ฐ€๋„๊ฐ€ ๋†’์€ 4D ํ…์„œ์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋Š” ๋ชจ๋ธ์ด ์ž„์˜์˜ ์ •์ˆ˜ ๋ฐฐ์น˜ ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” None์ž…๋‹ˆ๋‹ค.

์ถœ๋ ฅ : (batch_size, 1001) ๋ชจ์–‘์˜ tf.Tensor ์˜ tf.Tensor. ๊ฐ ํ–‰์€ ImageNet์˜ ๊ฐ 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)
imagenet_labels = load_imagenet_labels('https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt')

tf.image๋กœ ์ด๋ฏธ์ง€ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ

Wikimedia Commons์˜ ๋‘ ์ด๋ฏธ์ง€์ธ Fireboat์™€ Giant Panda๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 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()}
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%}')

ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ ๊ณ„์‚ฐํ•˜๊ธฐ

๋ชจ๋ธ Inception V1์€ ์ž…๋ ฅ ํŠน์„ฑ ๊ณต๊ฐ„, ์ด๋ฏธ์ง€ ํ”ฝ์…€ ๊ฐ’ ๋ฐ 0๊ณผ 1 ์‚ฌ์ด์˜ ImageNet ํด๋ž˜์Šค ํ™•๋ฅ  ๊ฐ’์œผ๋กœ ์ •์˜๋œ ์ถœ๋ ฅ ๊ณต๊ฐ„ ์‚ฌ์ด์˜ ๋งคํ•‘์„ ์„ค๋ช…ํ•˜๋Š” ํ•™์Šต๋œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์‹ ๊ฒฝ๋ง์— ๋Œ€ํ•œ ์ดˆ๊ธฐ ํ•ด์„ ๊ฐ€๋Šฅ์„ฑ ๋ฉ”์„œ๋“œ๋Š” ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์„ฑ์— ์ค‘์š”๋„ ์ ์ˆ˜๋ฅผ ๋ฐฐ์ •ํ–ˆ์œผ๋ฉฐ, ์ด๋Š” ๋ชจ๋ธ์˜ ์˜ˆ์ธก ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋ผ ์ฃผ์–ด์ง„ ์ง€์ ์—์„œ ๋ชจ๋ธ ์˜ˆ์ธก์— ์ƒ๋Œ€์ ์œผ๋กœ ๊ฐ€์žฅ ๊ฐ€ํŒŒ๋ฅธ ๋กœ์ปฌ์„ ๊ฐ–๋Š” ํ”ฝ์…€์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋ž˜๋””์–ธํŠธ๋Š” ํ”ฝ์…€ ๊ฐ’๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋ชจ๋ธ ์˜ˆ์ธก ํ•จ์ˆ˜์—์„œ ๋กœ์ปฌ ๋ณ€ํ™”๋งŒ์„ ์„ค๋ช…ํ•˜๊ณ  ์ „์ฒด ๋ชจ๋ธ ์˜ˆ์ธก ํ•จ์ˆ˜๋ฅผ ์™„์ „ํžˆ ์„ค๋ช…ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์ด ๊ฐœ๋ณ„ ํ”ฝ์…€์˜ ๋ฒ”์œ„์™€ ์˜ฌ๋ฐ”๋ฅธ ImageNet ํด๋ž˜์Šค ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์™„์ „ํžˆ "ํ•™์Šต"ํ•จ์— ๋”ฐ๋ผ ์ด ํ”ฝ์…€์˜ ๊ทธ๋ž˜๋””์–ธํŠธ๊ฐ€ ํฌํ™”๋˜์–ด ์ ์  ์ž‘์•„์ง€๊ณ  ๊ฒฐ๊ตญ 0์ด ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๊ฐ„๋‹จํ•œ ๋ชจ๋ธ ํ•จ์ˆ˜๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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)
#@title 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๋ฅผ ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„์–ด ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. ํŠน์„ฑ ๊ณต๊ฐ„์—์„œ 0(๊ธฐ์ค€์„  ๋˜๋Š” ์‹œ์ž‘์ )๊ณผ 1(์ž…๋ ฅ ํ”ฝ์…€ ๊ฐ’) ์‚ฌ์ด์˜ ์ง์„ ์„ ๋”ฐ๋ผ ์ž‘์€ ๋‹จ๊ณ„๋ฅผ ๋ณด๊ฐ„ํ•ฉ๋‹ˆ๋‹ค.

    2. ๊ฐ ๋‹จ๊ณ„์™€ ๊ด€๋ จํ•ด ๋ชจ๋ธ ์˜ˆ์ธก ์‚ฌ์ด์˜ ๊ฐ ๋‹จ๊ณ„์—์„œ ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

    3. ์ด๋Ÿฌํ•œ ๋กœ์ปฌ ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ๋ˆ„์ (๋ˆ„์  ํ‰๊ท )ํ•˜์—ฌ ๊ธฐ์ค€์„ ๊ณผ ์ž…๋ ฅ ์‚ฌ์ด์˜ ์ ๋ถ„ ๊ทผ์‚ฌ๊ฐ’์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋…ผ๋ฆฌ๋ฅผ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ "Fireboat" ์ด๋ฏธ์ง€ ์˜ˆ์— IG๋ฅผ ์ ์šฉํ•˜์—ฌ ์ด ์„ธ ๋ถ€๋ถ„์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ์ค€์„  ์ˆ˜๋ฆฝํ•˜๊ธฐ

๊ธฐ์ค€์„ ์€ ํŠน์„ฑ ์ค‘์š”๋„๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ์‹œ์ž‘์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ž…๋ ฅ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. ์ง๊ด€์ ์œผ๋กœ, ๊ธฐ์ค€์„ ์˜ ์„ค๋ช…์  ์—ญํ• ์„ ์ž…๋ ฅ ์ด๋ฏธ์ง€์— ์žˆ์„ ๋•Œ "Fireboat" ์˜ˆ์ธก์— ๋ฏธ์น˜๋Š” ๊ฐ ํ”ฝ์…€์˜ ์˜ํ–ฅ๊ณผ ๋Œ€๋น„์‹œ์ผœ ๊ฐ ํ”ฝ์…€์ด ์—†์„ ๋•Œ "Fireboat" ์˜ˆ์ธก์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ๊ธฐ์ค€์„ ์˜ ์„ ํƒ์€ ํ”ฝ์…€ ํŠน์„ฑ์˜ ์ค‘์š”์„ฑ์„ ํ•ด์„ํ•˜๊ณ  ์‹œ๊ฐํ™”ํ•˜๋Š” ๋ฐ ์ค‘์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์ค€์„  ์„ ํƒ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ํŠœํ† ๋ฆฌ์–ผ ํ•˜๋‹จ์˜ "๋‹ค์Œ ๋‹จ๊ณ„" ์„น์…˜์— ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ์—ฌ๊ธฐ์„œ๋Š” ํ”ฝ์…€ ๊ฐ’์ด ๋ชจ๋‘ 0์ธ ๊ฒ€์ •์ƒ‰ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์‹คํ—˜ํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์„ ํƒ์œผ๋กœ ์ „์ฒด ํฐ์ƒ‰ ์ด๋ฏธ์ง€ ๋˜๋Š” 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()

์ˆ˜์‹์„ ์ฝ”๋“œ๋กœ ์••์ถ• ํ•ด์ œํ•˜๊ธฐ

ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ์˜ ์ˆ˜์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

IntegratedGradientsi(x)::=(xiโˆ’xโ€ฒโˆ—i)ร—โˆซโˆ—ฮฑ=01โˆ‚F(xโ€ฒ+ฮฑร—(xโˆ’xโ€ฒ))โˆ‚xidฮฑ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_{i} = ํŠน์„ฑ
xx = ์ž…๋ ฅ
xโ€ฒx' = ๊ธฐ์ค€์„ 
ฮฑ\alpha = ํŠน์„ฑ์„ ๊ต๋ž€์‹œํ‚ค๋Š” ๋ณด๊ฐ„ ์ƒ์ˆ˜

์‹ค์ œ๋กœ, ์ •์ ๋ถ„์„ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด ์ˆ˜์น˜์ ์œผ๋กœ ํ•ญ์ƒ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ ๊ณ„์‚ฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆ˜์น˜์  ๊ทผ์‚ฌ๊ฐ’์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

IntegratedGradsapproxโˆ—i(x)::=(xโˆ—iโˆ’xโ€ฒโˆ—i)ร—โˆ‘โˆ—k=1mโˆ‚F(xโ€ฒ+kmร—(xโˆ’xโ€ฒ))โˆ‚xiร—1mIntegratedGrads^{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*{i} = ํŠน์„ฑ(๊ฐœ๋ณ„ ํ”ฝ์…€)
xx = ์ž…๋ ฅ(์ด๋ฏธ์ง€ ํ…์„œ)
xโ€ฒx' = ๊ธฐ์ค€์„ (์ด๋ฏธ์ง€ ํ…์„œ)
kk = ๋ฐฐ์œจ ์กฐ์ •๋œ ํŠน์„ฑ ์„ญ๋™ ์ƒ์ˆ˜
mm = ์ ๋ถ„์˜ ๋ฆฌ๋งŒ ํ•ฉ ๊ทผ์‚ฌ์˜ ๋‹จ๊ณ„ ์ˆ˜
(xโˆ—iโˆ’xiโ€ฒ)(x*{i}-x'_{i}) = ๊ธฐ์ค€์„ ๊ณผ์˜ ์ฐจ์ด์— ๋Œ€ํ•œ ํ•ญ. ์ด๊ฒƒ์€ ์ ๋ถ„๋œ ๊ทธ๋ž˜๋””์–ธํŠธ์˜ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•˜๊ณ  ์›๋ณธ ์ด๋ฏธ์ง€์˜ ๊ด€์ ์—์„œ ์ด๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์ค€์„  ์ด๋ฏธ์ง€์—์„œ ์ž…๋ ฅ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋Š” ํ”ฝ์…€ ๊ณต๊ฐ„์— ์žˆ์Šต๋‹ˆ๋‹ค. IG๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ง์„ ์œผ๋กœ ํ†ตํ•ฉ(์„ ํ˜• ๋ณ€ํ™˜)ํ•˜๋ฏ€๋กœ ์ถฉ๋ถ„ํ•œ ๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด ฮฑ\alpha์™€ ๊ด€๋ จํ•ด ๋ณด๊ฐ„๋œ ์ด๋ฏธ์ง€ ํ•จ์ˆ˜์˜ ๋„ํ•จ์ˆ˜์˜ ์ ๋ถ„ ํ•ญ๊ณผ ๋Œ€๋žต ๋™์ผํ•ด์ง‘๋‹ˆ๋‹ค. ์ ๋ถ„์€ ๊ฐ ํ”ฝ์…€์˜ ๊ทธ๋ž˜๋””์–ธํŠธ์— ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ฅธ ํ”ฝ์…€์˜ ๋ณ€ํ™”๋ฅผ ๊ณฑํ•œ ๊ฐ’์„ ํ•ฉ์‚ฐํ•ฉ๋‹ˆ๋‹ค. x:=(xโ€ฒ+ฮฑ(xโˆ’xโ€ฒ))x := (x' + \alpha(x-x'))๋ฅผ ๋Œ€์ฒดํ•˜์—ฌ ํ•œ ์ด๋ฏธ์ง€์—์„œ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€๋กœ์˜ ๊ท ์ผํ•œ ๋‹จ๊ณ„๋กœ ์ด ์ ๋ถ„์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด dx=(xโˆ’xโ€ฒ)dฮฑdx = (x-x')d\alpha๊ฐ€ ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. (xโˆ’xโ€ฒ)(x-x') ํ•ญ์€ ์ƒ์ˆ˜์ด๋ฉฐ ์ ๋ถ„์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ๋ณด๊ฐ„ํ•˜๊ธฐ

IntegratedGradsapproxโˆ—i(x)::=(xโˆ—iโˆ’xโ€ฒโˆ—i)ร—โˆ‘โˆ—k=1mโˆ‚F(xโ€ฒ+kmร—(xโˆ’xโ€ฒ)โžinterpolateย mย imagesย atย kย intervals)โˆ‚xiร—1mIntegratedGrads^{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

์œ„ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ •์ƒ‰ ๊ธฐ์ค€์„  ์ด๋ฏธ์ง€์™€ ์˜ˆ์ œ "Fireboat" ์ด๋ฏธ์ง€ ์‚ฌ์ด์˜ ์•ŒํŒŒ ๊ฐ„๊ฒฉ์œผ๋กœ ์„ ํ˜• ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ๋ณด๊ฐ„๋œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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();

๊ทธ๋ž˜๋””์–ธํŠธ ๊ณ„์‚ฐํ•˜๊ธฐ

์ด์ œ ํŠน์„ฑ ๋ณ€๊ฒฝ๊ณผ ๋ชจ๋ธ ์˜ˆ์ธก ๋ณ€๊ฒฝ ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€์˜ ๊ฒฝ์šฐ, ๊ทธ๋ž˜๋””์–ธํŠธ๋Š” ๋ชจ๋ธ์˜ ์˜ˆ์ธก ํด๋ž˜์Šค ํ™•๋ฅ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์ด ๊ฐ€์žฅ ํฐ ํ”ฝ์…€์ด ๋ฌด์—‡์ธ์ง€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

IntegratedGradsapproxโˆ—i(x)::=(xโˆ—iโˆ’xโ€ฒโˆ—i)ร—โˆ‘โˆ—k=1mโˆ‚F(interpolatedย images)โžcomputeย gradientsโˆ‚xiร—1mIntegratedGrads^{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()F() = ๋ชจ๋ธ์˜ ์˜ˆ์ธก ํ•จ์ˆ˜
โˆ‚Fโˆ‚xi\frac{\partial{F}} {\partial{x_i}} = ๊ฐ ํŠน์„ฑ xix_i์— ์ƒ๋Œ€์ ์ธ ๋ชจ๋ธ F์˜ ์˜ˆ์ธก ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ทธ๋ž˜๋””์–ธํŠธ(๋ถ€๋ถ„ ๋„ํ•จ์ˆ˜ โˆ‚\partial์˜ ๋ฒกํ„ฐ)

์šฉ์ดํ•œ ๊ทธ๋ž˜๋””์–ธํŠธ ๊ณ„์‚ฐ์„ ์œ„ํ•ด 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๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์ ์„ ์ƒ๊ธฐํ•˜์„ธ์š”. ์˜ฌ๋ฐ”๋ฅธ 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)

๊ทธ๋ž˜๋””์–ธํŠธ ํฌํ™” ์‹œ๊ฐํ™”ํ•˜๊ธฐ

์œ„์—์„œ ๊ณ„์‚ฐํ•œ ๊ทธ๋ž˜๋””์–ธํŠธ๋Š” ๋ชจ๋ธ์˜ ์˜ˆ์ธก๋œ "Fireboat" ํ™•๋ฅ ์— ๋Œ€ํ•œ ๋กœ์ปฌ ๋ณ€๊ฒฝํ™”๋ฅผ ์„ค๋ช…ํ•˜๋ฉฐ ํฌํ™”๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ฐœ๋…์€ ์•„๋ž˜ 2๊ฐœ์˜ ํ”Œ๋กฏ์—์„œ ์œ„์—์„œ ๊ณ„์‚ฐํ•œ ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ๊ฐํ™”๋ฉ๋‹ˆ๋‹ค.

pred = model(interpolated_images) pred_proba = tf.nn.softmax(pred, axis=-1)[:, 555]
#@title 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]);
  • ์™ผ์ชฝ: ์ด ํ”Œ๋กฏ์€ "Fireboat" ํด๋ž˜์Šค์— ๋Œ€ํ•œ ๋ชจ๋ธ์˜ ์‹ ๋ขฐ๋„๊ฐ€ ์ „์ฒด ์•ŒํŒŒ์— ๊ฑธ์ณ ์–ด๋–ป๊ฒŒ ๋‹ฌ๋ผ์ง€๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์•ฝ 40%์˜ ์ตœ์ข… "Fireboat" ์˜ˆ์ƒ ํ™•๋ฅ ์—์„œ ์•ˆ์ •ํ™”๋˜๊ธฐ ์ „์— ๊ทธ๋ž˜๋””์–ธํŠธ ๋˜๋Š” ๋ผ์ธ์˜ ๊ธฐ์šธ๊ธฐ๊ฐ€ 0.6๊ณผ 1.0 ์‚ฌ์ด์—์„œ ํฌ๊ฒŒ ํ‰ํ‰ํ•ด์ง€๊ฑฐ๋‚˜ ํฌํ™”๋˜๋Š” ๊ฒƒ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.

  • ์˜ค๋ฅธ์ชฝ: ์˜ค๋ฅธ์ชฝ ํ”Œ๋กฏ์€ ์ „์ฒด ์•ŒํŒŒ์— ๊ฑธ์ณ ํ‰๊ท  ๊ทธ๋ž˜๋””์–ธํŠธ ํฌ๊ธฐ๋ฅผ ๋” ์ง์ ‘์ ์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๊ฐ’์ด 0์œผ๋กœ ๊ธ‰๊ฒฉํ•˜๊ฒŒ ์ ‘๊ทผํ•˜๊ณ  ์‹ฌ์ง€์–ด ์ž ๊น ๋™์•ˆ 0 ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋Š” ๋ชจ์Šต์— ์ฃผ๋ชฉํ•˜์„ธ์š”. ์‚ฌ์‹ค, ๋ชจ๋ธ์€ ๋‚ฎ์€ ์•ŒํŒŒ ๊ฐ’์˜ ๊ทธ๋ž˜๋””์–ธํŠธ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด "ํ•™์Šต"ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์ง๊ด€์ ์œผ๋กœ ๋ณด๋ฉด, ๋ชจ๋ธ์ด ์ •ํ™•ํ•œ ์˜ˆ์ธก์„ ์œ„ํ•ด ํ”ฝ์…€, ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฌผ๋Œ€ํฌ๋ฅผ ํ•™์Šตํ•˜๊ณ  ์ด๋Ÿฌํ•œ ํ”ฝ์…€ ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ 0์œผ๋กœ ๋ณด๋‚ด์ง€๋งŒ ์—ฌ์ „ํžˆ ์ƒ๋‹นํžˆ ๋ถˆํ™•์‹คํ•˜๊ณ  ์•ŒํŒŒ ๊ฐ’์ด ์›๋ž˜ ์ž…๋ ฅ ์ด๋ฏธ์ง€์— ์ ‘๊ทผํ•จ์— ๋”ฐ๋ผ ๋‹ค๋ฆฌ ๋˜๋Š” ๋ฌผ ์ œํŠธ ํ”ฝ์…€์— ์ค‘์ ์„ ๋‘๋Š” ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ค‘์š”ํ•œ ๋ฌผ๋Œ€ํฌ ํ”ฝ์…€์ด "Fireboat" ์˜ˆ์ธก์— ์ค‘์š”ํ•˜๊ฒŒ ๋ฐ˜์˜๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์—์„œ ๊ณ„์†ํ•ด์„œ ๊ฐ ํ”ฝ์…€์ด "Fireboat" ์˜ˆ์ธก ํ™•๋ฅ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์ •ํ™•ํ•˜๊ฒŒ ๊ทผ์‚ฌ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ๋ˆ„์ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋””์–ธํŠธ ๋ˆ„์ ํ•˜๊ธฐ(์ ๋ถ„ ๊ทผ์‚ฌ๊ฐ’ ๊ณ„์‚ฐ)

IG์— ๋Œ€ํ•œ ์ ๋ถ„์˜ ์ˆ˜์น˜์  ๊ทผ์‚ฌ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์œผ๋ฉฐ, ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์— ๊ฑธ์ณ ์ •ํ™•๋„์™€ ์ˆ˜๋ ด์—์„œ ๋“์‹ค ๊ด€๊ณ„๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ ํด๋ž˜์Šค๋Š” ๋ฆฌ๋งŒ ํ•ฉ(Riemann sums)์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์‚ฌ๋‹ค๋ฆฌ๊ผด ๊ทœ์น™์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์ด ํŠœํ† ๋ฆฌ์–ผ ๋งˆ์ง€๋ง‰์— ๋‹ค๋ฅธ ๊ทผ์‚ฌ ๊ณ„์‚ฐ์„ ์‚ดํŽด๋ณด๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ์ฝ”๋“œ๊ฐ€ ๋‚˜์™€ ์žˆ์Œ).

IntegratedGradsapproxโˆ—i(x)::=(xโˆ—iโˆ’xโ€ฒโˆ—i)ร—โˆ‘โˆ—k=1mโžSumย mย localย gradientsgradients(interpolatedย images)ร—1mโžDivideย byย mย stepsIntegratedGrads^{approx}*{i}(x)::=(x*{i}-x'*{i})\times \overbrace{\sum*{k=1}^{m}}^\text{Sum m local gradients} \text{gradients(interpolated images)} \times \overbrace{\frac{1}{m}}^\text{Divide 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 ์ด๋ฏธ์ง€์˜ ๊ทธ๋ž˜๋””์–ธํŠธ ์ „์ฒด์—์„œ ํ‰๊ท ์„ ๊ตฌํ•˜๋ฉด ์›๋ž˜ "Giant Panda" ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ํ˜•์ƒ์˜ ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ ํ…์„œ๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

print(ig.shape)

๋ชจ๋‘ ํ•จ๊ป˜ ์‹คํ–‰ํ•˜๊ธฐ

์ด์ œ ์•ž์„œ ์•Œ์•„๋ณธ 3๊ฐœ์˜ ์ผ๋ฐ˜ ํŒŒํŠธ๋ฅผ IntegratedGradients ํ•จ์ˆ˜๋กœ ๊ฒฐํ•ฉํ•˜๊ณ  @ tf.function ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์„ฑ๋Šฅ ํ˜ธ์ถœ ๊ฐ€๋Šฅ Tensorflow ๊ทธ๋ž˜ํ”„๋กœ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์•„๋ž˜ 5 ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

IntegratedGradsapproxโˆ—i(x)::=(xโˆ—iโˆ’xโ€ฒโˆ—i)โž5.ร—โˆ‘โˆ—k=1mโž4.โˆ‚F(xโ€ฒ+kmโž1.ร—(xโˆ’xโ€ฒ))โž2.โž3.โˆ‚xiร—1mโž4.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โ€ฒ+kmร—(xโˆ’xโ€ฒ))(x' + \frac{k}{m}\times(x - x')) ์ƒ์„ฑ

  3. ์ž…๋ ฅ ํŠน์„ฑ = โˆ‚F(interpolatedย pathย inputs)โˆ‚xi\frac{\partial F(\text{interpolated path inputs})}{\partial x_{i}}์™€ ๊ด€๋ จํ•˜์—ฌ ๋ชจ๋ธ FF ์ถœ๋ ฅ ์˜ˆ์ธก ์‚ฌ์ด์˜ ๊ทธ๋ž˜๋””์–ธํŠธ ๊ณ„์‚ฐ

  4. ํ‰๊ท  ๊ทธ๋ž˜๋””์–ธํŠธ๋ฅผ ํ†ตํ•œ ์ ๋ถ„ ๊ทผ์‚ฌ = โˆ‘k=1mgradientsร—1m\sum_{k=1}^m \text{gradients} \times \frac{1}{m}

  5. ์›๋ณธ ์ด๋ฏธ์ง€ = = (xiโˆ’xiโ€ฒ)ร—integratedย gradients(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) # Concatenate path gradients together row-wise into single tensor. total_gradients = tf.concat(gradient_batches, axis=0) # 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)

์ด ๋ฌธ์„œ์—์„œ๋Š” ์˜ˆ์ œ์— ๋”ฐ๋ผ 20์—์„œ 300 ์‚ฌ์ด์˜ ๋‹จ๊ณ„ ์ˆ˜๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค(์‹ค์ œ๋กœ ์ ๋ถ„์„ ์ •ํ™•ํ•˜๊ฒŒ ๊ทผ์‚ฌ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ˆ˜์ฒœ ๋‹จ๊ณ„๊นŒ์ง€๋„ ์ด์šฉํ•จ). ์ด ํŠœํ† ๋ฆฌ์–ผ ๋งˆ์ง€๋ง‰์˜ "๋‹ค์Œ ๋‹จ๊ณ„" ๋ฆฌ์†Œ์Šค์—์„œ ์ ์ ˆํ•œ ๋‹จ๊ณ„ ์ˆ˜๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์†์„ฑ ์‹œ๊ฐํ™”ํ•˜๊ธฐ

์ด์ œ ์†์„ฑ์„ ์‹œ๊ฐํ™”ํ•˜๊ณ  ์›๋ณธ ์ด๋ฏธ์ง€์— ์˜ค๋ฒ„๋ ˆ์ดํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ƒ‰์ƒ ์ฑ„๋„์—์„œ ์ ๋ถ„๋œ ๊ทธ๋ž˜๋””์–ธํŠธ์˜ ์ ˆ๋Œ€๊ฐ’์„ ํ•ฉ์‚ฐํ•˜์—ฌ ์†์„ฑ ๋งˆ์Šคํฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”Œ๋กฏ ๋ฉ”์„œ๋“œ๋Š” ๋ชจ๋ธ ์˜ˆ์ธก์— ๋ฏธ์น˜๋Š” ํ”ฝ์…€์˜ ์ƒ๋Œ€์  ์˜ํ–ฅ์„ ํฌ์ฐฉํ•ฉ๋‹ˆ๋‹ค.

#@title 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

"Fireboat" ์ด๋ฏธ์ง€์˜ ์†์„ฑ์„ ์‚ดํŽด๋ณด๋ฉด ๋ชจ๋ธ์ด ๋ฌผ ๋Œ€ํฌ์™€ ์ฃผ๋‘ฅ์ด๊ฐ€ ์ •ํ™•ํ•œ ์˜ˆ์ธก์— ๊ธฐ์—ฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์‹๋ณ„ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์šฉ๋„ ๋ฐ ์ œํ•œ

์‚ฌ์šฉ ์‚ฌ๋ก€

  • ๋ชจ๋ธ์„ ๋ฐฐํฌํ•˜๊ธฐ ์ „์— ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ์™€ ๊ฐ™์€ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์ž‘๋™ ๋ฐฉ์‹ ๋ฐ ๊ทธ ์ด์œ ์— ๋Œ€ํ•œ ์ง๊ด€์„ ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋ฒ•์œผ๋กœ ๊ฐ•์กฐ๋œ ํŠน์„ฑ์ด ์ง๊ด€๊ณผ ์ผ์น˜ํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด๋Š” ๋ชจ๋ธ ๋˜๋Š” ๋ฐ์ดํ„ฐ์„ธํŠธ์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๊ฑฐ๋‚˜ ๊ณผ์ ํ•ฉ์ž„์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๊ณ„

  • ํ†ตํ•ฉ ๊ทธ๋ž˜๋””์–ธํŠธ๋Š” ๊ฐœ๋ณ„ ์˜ˆ์ œ์—์„œ ํŠน์„ฑ์˜ ์ค‘์š”๋„๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ์ „์ฒด ๋ฐ์ดํ„ฐ ์„ธํŠธ์— ๊ฑธ์ณ ์ „์ฒด ํŠน์„ฑ์˜ ์ค‘์š”๋„๋ฅผ ์ œ๊ณตํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ ๋ถ„ ๊ทธ๋ž˜๋””์–ธํŠธ๋Š” ๊ฐœ๋ณ„ ํŠน์„ฑ์˜ ์ค‘์š”๋„๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ํŠน์„ฑ ์ƒํ˜ธ ์ž‘์šฉ ๋ฐ ์กฐํ•ฉ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์ ๋ถ„ ๊ทธ๋ž˜๋””์–ธํŠธ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ๋Š” ์ด ๋…ธํŠธ๋ถ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ชจ๋ธ๊ณผ ์ด๋ฏธ์ง€๋กœ ์ด ๊ธฐ๋ฒ•์„ ์‹œํ—˜ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ด€์‹ฌ์ด ์žˆ๋Š” ๋…์ž๋ฅผ ์œ„ํ•ด ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ์ƒ์„ธ ๋ฒ„์ „(์—ฌ๋Ÿฌ ๊ธฐ์ค€์„ ์— ๋Œ€ํ•œ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์ ๋ถ„ ๊ทผ์‚ฌ์น˜ ๊ณ„์‚ฐ ๋ฐ ์ถฉ๋ถ„ํ•œ ์ˆ˜์˜ ๋‹จ๊ณ„๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ ํฌํ•จ)์„ ์—ฌ๊ธฐ์„œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดํ•ด๋„๋ฅผ ๋†’์ด๋ ค๋ฉด ์ด์ „ TensorFlow ๋ฒ„์ „์—์„œ์˜ ๊ตฌํ˜„์„ ํฌํ•จํ•œ Axiomatic Attribution for Deep Networks ๋ฐ Github ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. distill.pub์—์„œ ํŠน์„ฑ ์†์„ฑ ๋ฐ ์—ฌ๋Ÿฌ ๊ธฐ์ค€์„ ์˜ ์˜ํ–ฅ์— ๋Œ€ํ•ด์„œ๋„ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์„ฑ ์ค‘์š”๋„, ๋ชจ๋ธ ์˜ค๋ฅ˜ ๋ถ„์„ ๋ฐ ๋ฐ์ดํ„ฐ ์ ๋ฆผ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์œ„ํ•œ ์‹ค๋ฌด ๋จธ์‹ ๋Ÿฌ๋‹ ์›Œํฌํ”Œ๋กœ์— IG๋ฅผ ํ†ตํ•ฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๊นŒ? IG ์†์„ฑ์„ ์ง€์›ํ•˜๋Š” Google Cloud์˜ Explainable AI ์ œํ’ˆ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”. Google AI PAIR ๋ฆฌ์„œ์น˜ ๊ทธ๋ฃน์€ IG ํŠน์„ฑ ์†์„ฑ ์‹œ๊ฐํ™”๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ชจ๋ธ ๋””๋ฒ„๊น…์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” What-if ๋„๊ตฌ๋ฅผ ์˜คํ”ˆ์†Œ์Šค๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.