XAI
- Integrated Gradients(IG)
목차
- 학습 목표
- IG 개요
- IG 원리 간단 복습
- 실습 예제 개요
- 실습: 파이썬 코드로 보는 Integrated Gradients
- 5.1 라이브러리 및 데이터 불러오기
- 5.2 모델 정의 및 훈련
- 5.3 Integrated Gradients 계산 구현
- 5.4 시각화 및 해석
- 추가 실습 아이디어
- 정리 및 결론
- 참고 자료
1. 학습 목표
- Integrated Gradients(IG)의 이론적 개념 및 원리를 이해한다.
- Baseline의 중요성을 인식하고 적절한 baseline 설정 방안을 고민해본다.
- 파이썬 코드 실습을 통해 딥러닝 모델에 IG를 직접 적용해본다.
- IG 결과를 시각화하고 특징 중요도를 해석하는 방법을 학습한다.
- 비즈니스 또는 실무 현장에서 IG가 갖는 의미를 살펴보고, 어떻게 활용할 수 있는지 고민한다.
2. IG 개요
Integrated Gradients는 2017년 Sundararajan 등이 제안한 설명 가능한 AI(XAI) 기법의 한 종류입니다. 딥러닝 모델의 예측(출력)에 대해 각 특징(입력 변수)이 얼마나 기여하는지 정량적으로 계산하고, 이를 통해 모델의 의사결정 근거를 시각화합니다.
- Baseline(특징이 ‘없는’ 상태)에서 시작해 실제 입력값까지 조금씩 이동하면서 그때그때 기울기(gradient)를 적분하여 각 특징의 중요도를 산출한다.
- 이 기법은 민감도(sensitivity), 구현불변성(implementation invariance), 완전성(completeness) 등 여러 유용한 이론적 속성을 만족한다.
- 실제로 이미지 분류, 텍스트 분석, 의료 영상 진단, 금융 신용평가 등 다양한 분야에서 활용되고 있다.
3. IG 원리 간단 복습
IG를 정의하는 핵심 수식은 다음과 같습니다. IGi(x) = (xi−xi′)×∫α=01∂F(x′+α(x−x′))∂xi dαIG_i(x) ;=; (x_i - x’i) \times \int{\alpha=0}^{1} \frac{\partial F\bigl(x’ + \alpha (x - x’)\bigr)}{\partial x_i} , d\alpha
- xx: 실제 입력 벡터(예: 이미지, 특성 벡터 등)
- x′x’: baseline 벡터(‘특징이 없는’ 상태를 나타내는 입력)
- α\alpha: 0에서 1까지 이동하며, baseline에서 실제 입력까지 선형 보간(interpolation)을 진행
- ∂F∂xi\frac{\partial F}{\partial x_i}: 모델 의 출력값을 입력 에 대해 편미분한 값(기울기) FF xx
- 최종적으로, baseline에서 실제 입력까지 이동하면서 기울기를 적분한 결과를 로 스케일링한다. (xi−xi′)(x_i - x’_i)
4. 실습 예제 개요
- 데이터셋: 예시로 MNIST(손글씨 숫자) 또는 Fashion-MNIST를 사용합니다. (이미지 데이터이기 때문에 시각화가 비교적 직관적입니다.)
- 모델: 간단한 합성곱 신경망(CNN)
- 목표: CNN으로 MNIST 데이터를 분류한 뒤, 특정 샘플 이미지를 대상으로 IG를 적용하여 어떤 픽셀들이 예측에 영향을 주었는지를 확인한다.
- Baseline: 모든 픽셀이 0(검정색)인 이미지를 사용할 예정이다. (이미지에서 ‘아무 정보도 없는’ 상태로 취급)
5. 실습: 파이썬 코드로 보는 Integrated Gradients
5.1 라이브러리 및 데이터 불러오기
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import numpy as np
- torch: PyTorch
- torchvision: 이미지 데이터 전처리 및 로드
- matplotlib, numpy: 시각화 및 수치 계산용
데이터셋 준비
# MNIST 데이터셋 다운로드 및 로드
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)) # MNIST 평균, 표준편차로 정규화
])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)
5.2 모델 정의 및 훈련
간단한 CNN 모델 정의
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.fc1 = nn.Linear(64*7*7, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = F.relu(self.conv1(x)) # (batch, 32, 28, 28)
x = F.max_pool2d(x, 2) # (batch, 32, 14, 14)
x = F.relu(self.conv2(x)) # (batch, 64, 14, 14)
x = F.max_pool2d(x, 2) # (batch, 64, 7, 7)
x = x.view(x.size(0), -1) # (batch, 64*7*7)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = SimpleCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
모델 훈련 루프
num_epochs = 1 # 예시로 1 epoch만 학습
model.train()
for epoch in range(num_epochs):
total_loss = 0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss/len(train_loader):.4f}")
실제 학습 환경에서는 5~10 Epoch 정도 수행하면 정확도가 97% 이상까지 상승합니다. (학습 속도 및 성능은 GPU 환경, epoch 수 등에 따라 달라질 수 있습니다.)
5.3 Integrated Gradients 계산 구현
Integrated Gradients를 직접 구현하는 핵심 절차는 다음과 같습니다.
- baseline(여기서는 0으로만 이루어진 이미지) 설정
- baseline에서 실제 이미지까지 를 0~1로 나누어 선형 보간 α\alpha
- 각 에 대해 모델의 gradient를 계산 α\alpha
- 각 gradient를 적분(혹은 수치적으로 합산)하여 최종 IG를 구함
5.3.1 하나의 샘플 이미지 선택
model.eval()
# 테스트 셋에서 임의의 샘플 하나 추출
test_iter = iter(test_loader)
images, labels = next(test_iter)
sample_img = images[0].unsqueeze(0).to(device) # shape: (1, 1, 28, 28)
sample_label = labels[0].item()
print("실제 라벨: ", sample_label)
# 모델 예측 확인
with torch.no_grad():
pred = model(sample_img)
pred_label = torch.argmax(pred, dim=1).item()
print("예측 라벨: ", pred_label)
5.3.2 IG 함수 정의 (선형 경로 적분)
def integrated_gradients(model, input_img, baseline, target_label_idx, steps=50):
"""
model: 학습된 PyTorch 모델
input_img: (1, channel, height, width) 형태의 텐서
baseline: input_img와 동일한 shape, 특징이 없는 상태의 텐서
target_label_idx: 예측하고자 하는 클래스 라벨 인덱스
steps: 선형 보간을 몇 단계로 수행할 것인가 (기본 50)
"""
# input_img, baseline 모두 gradient 계산을 위해 requires_grad=True 설정
input_img.requires_grad = True
baseline.requires_grad = True
# (input_img - baseline)을 steps만큼 나누어 선형 보간
scaled_inputs = [
baseline + float(i)/steps * (input_img - baseline)
for i in range(steps+1)
]
# gradients를 누적할 리스트
all_gradients = []
for scaled_input in scaled_inputs:
# forward
output = model(scaled_input)
# 해당 클래스의 스칼라값만 추출
# output은 shape (1, num_classes)이므로 target_label_idx에 해당하는 값만 선택
target_score = output[0, target_label_idx]
# backward를 통해 gradient 계산
model.zero_grad()
target_score.backward(retain_graph=True)
# scaled_input의 gradient 획득
all_gradients.append(scaled_input.grad.data.cpu().numpy().copy())
# gradient 누적 후 0으로 재설정 (다음 루프에 영향 없도록)
scaled_input.grad.zero_()
# 평균 gradient 계산 (수치 적분)
avg_gradients = np.mean(all_gradients, axis=0)
# IG = (input_img - baseline) * 평균 gradient (element-wise 곱)
ig = (input_img.detach().cpu().numpy() - baseline.detach().cpu().numpy()) * avg_gradients
return ig
유의사항: 위 코드는 가장 직관적인 방식으로 IG를 구현하여 설명에 초점을 맞췄습니다. 실제로는 tensor 연산을 최적화하거나, 한 번에 batch로 계산하는 기법 등을 사용할 수 있습니다.
5.3.3 IG 계산 실행
# baseline: 0으로만 구성된 이미지 (MNIST shape 동일)
baseline_img = torch.zeros_like(sample_img).to(device)
# sample_label에 해당하는 클래스에 대해 IG 계산
ig_result = integrated_gradients(
model, sample_img.clone(), baseline_img.clone(),
target_label_idx=sample_label, steps=25 # steps=25로 축소
)
print("IG shape:", ig_result.shape)
5.4 시각화 및 해석
5.4.1 원본 이미지와 IG 시각화
# 원본 이미지
original_img = sample_img.detach().cpu().numpy()[0,0,:,:] # shape: (28,28)
# IG 결과 (pixel-wise 기여도)
ig_attributions = ig_result[0,0,:,:]
# 양수/음수 기여 등 시각화를 위해 일부 처리를 수행
ig_abs = np.abs(ig_attributions)
ig_normalized = ig_abs / (ig_abs.max() + 1e-8) # [0,1]로 정규화
fig, axs = plt.subplots(1, 3, figsize=(10, 3))
axs[0].imshow(original_img, cmap='gray')
axs[0].set_title("Original Image")
axs[1].imshow(ig_attributions, cmap='seismic')
axs[1].set_title("IG Raw Attributions")
axs[2].imshow(original_img, cmap='gray', alpha=0.5)
axs[2].imshow(ig_normalized, cmap='hot', alpha=0.5)
axs[2].set_title("Overlayed IG")
for ax in axs:
ax.axis('off')
plt.tight_layout()
plt.show()
- IG Raw Attributions: 각 픽셀이 해당 클래스 예측에 기여한 정도를 양/음으로 표시
- Overlayed IG: 원본 이미지 위에 기여도가 큰 부분을 붉은색으로 덧씌워서 시각화
- 이 시각화로, 모델이 숫자를 인식할 때 주목한 픽셀들을 직관적으로 확인 가능
해석 팁:
6. 추가 실습 아이디어
- 다른 모델 구조 실험: CNN 대신 MLP(Multi-Layer Perceptron) 또는 ResNet 등을 사용해 성능 및 IG 결과를 비교해본다.
- 다른 baseline 시도: 0 대신 평균 이미지, 노이즈 이미지 등을 baseline으로 설정하여 IG 결과가 어떻게 달라지는지 관찰한다.
- 다른 데이터셋 활용: 이미지가 아닌 탭уляр(tabular) 데이터(예: UCI의 Iris나 Adult 등)에 적용해보면, IG가 개별 특징(column)에 부여하는 기여도를 표 형태로 확인할 수 있다.
- 다른 XAI 기법과 비교: LIME, SHAP, Grad-CAM 등과의 결과를 비교하며 IG만의 장단점을 체감해본다.
- 계산 효율 개선: 위 예제 코드처럼 step-by-step으로 계산하는 대신, 한꺼번에 batch 연산을 수행하여 계산 시간을 줄이는 방법도 고민해본다.
7. 정리 및 결론
- Integrated Gradients는 딥러닝 모델이 특정 예측을 내릴 때, 각 특징(픽셀, 변수)이 얼마나 기여하는지 산출하는 효과적인 XAI 기법입니다.
- Baseline을 기준으로 실제 입력까지 선형 보간하며, 각 지점에서 gradient를 구해 적분하는 방식으로 기여도를 계산합니다.
- IG는 이론적으로 민감도, 구현불변성, 완전성 등의 공리를 만족하며, 딥러닝 구조 수정 없이 모델의 gradient만 활용하기 때문에 적용이 쉽습니다.
- 다만, baseline 설정에 따라 결과가 크게 달라질 수 있으므로, 도메인에 맞게 baseline을 선정하고 IG 결과를 해석할 때 주의를 기울여야 합니다.
- 비즈니스 관점에서는 AI 모델에 투명성과 신뢰성을 부여하는 수단으로 IG가 큰 의미를 가지며, 특히 금융, 의료, 공공 정책 등에서 모델 설명 및 규제 준수를 위해 적극 도입되고 있습니다.
8. 참고 자료
- Sundararajan, Mukund, et al. “Axiomatic Attribution for Deep Networks.” ICML, 2017.
- Smilkov, Daniel, et al. “SmoothGrad: removing noise by adding noise.” arXiv preprint arXiv:1706.03825 (2017).
- Ancona, Marco, et al. “Towards better understanding of gradient-based attribution methods for Deep Neural Networks.” ICLR, 2018.
- Lundberg, Scott M., and Su-In Lee. “A unified approach to interpreting model predictions.” NIPS, 2017.
- Montavon, Grégoire, Wojciech Samek, and Klaus-Robert Müller. “Methods for interpreting and understanding deep neural networks.” Digital signal processing 73 (2018): 1-15.
마무리
위 교육 콘텐츠는 Integrated Gradients의 개념 설명 및 파이썬(Pytorch) 실습 코드 예시를 통해, 학습자들이 IG의 작동 원리를 직접 체험하도록 안내합니다.
- 학습자 수준: 딥러닝과 파이썬 문법에 대한 기초 지식 보유자.
- 학습 후 기대 효과: IG를 활용하여 모델의 예측 근거를 시각화하고, XAI가 비즈니스 현장에서 어떻게 가치 있게 쓰이는지 이해할 수 있음. 앞서 제시된 코드를 기반으로, 실제 프로젝트나 더 복잡한 모델에 적용하며 연습해보면 IG의 실질적 활용 가치를 체감하게 될 것입니다.
추가 팁:
이상으로 Integrated Gradients 교육 콘텐츠를 마치겠습니다. 감사합니다!