Class Activation Mapping (CAM)과 Grad-CAM

2024. 8. 29. 18:26·딥러닝 (Deep Learning)/[06] - 평가 및 결과 분석
728x90
반응형

Class Activation Mapping (CAM)과 Gradient-weighted Class Activation Mapping (Grad-CAM)은 딥러닝 모델,
특히 CNN(Convolutional Neural Network)의 예측 과정을 시각화하는 강력한 도구들입니다.
이 방법들은 모델이 이미지의 어느 부분을 보고 특정 클래스를 예측했는지 시각적으로 이해할 수 있게 도와줍니다.

1. Class Activation Mapping (CAM)

CAM은 특정 클래스에 대한 예측에 기여하는 이미지의 영역을 시각화하는 방법입니다.
이 방법은 일반적으로 모델의 마지막 컨볼루션 레이어와 완전 연결(FC) 레이어 사이에서 이루어집니다.
CAM의 기본 아이디어는 각 클래스에 대해, 모델이 어느 영역에 주목했는지를 확인하는 것입니다.

CAM의 작동 방식

  • 모델 구조 변경
    CAM을 사용하려면 모델 구조를 약간 변경해야 합니다. 특히, 전통적인 완전 연결 레이어를
    글로벌 평균 풀링(Global Average Pooling, GAP) 레이어로 대체합니다.

  • Class Activation Map 생성:
    GAP 레이어와 그 뒤에 이어진 FC 레이어의 가중치로부터 각 클래스에 대한 활성화 맵을 생성합니다.
    이 맵은 이미지의 특정 부분이 모델의 예측에 얼마나 기여했는지를 나타냅니다.

CAM의 한계

  • CAM은 모델 구조를 수정해야 하며, 기존의 잘 학습된 모델에는 적용하기 어렵습니다.
  • 또한, 마지막 컨볼루션 레이어와 FC 레이어 사이의 정보만을 시각화할 수 있기 때문에,
    보다 세밀한 시각화에는 적합하지 않을 수 있습니다.

2. Gradient-weighted Class Activation Mapping (Grad-CAM)

Grad-CAM은 CAM의 확장된 버전으로, 모델 구조를 변경하지 않고도 활성화 맵을 생성할 수 있는 방법입니다.
Grad-CAM은 이미지에서 특정 클래스에 대한 활성화 맵을 계산할 때, 해당 클래스의 그라디언트(gradient)를 이용합니다. 이 방법은 기존에 학습된 모델에도 적용할 수 있으며, 더 많은 유연성을 제공합니다.

Grad-CAM의 작동 방식:

  • 모델의 마지막 컨볼루션 레이어 선택
    Grad-CAM은 모델의 마지막 컨볼루션 레이어를 사용하여, 그 레이어의 출력을 기반으로 활성화 맵을 생성합니다.

  • Gradient 계산
     특정 클래스에 대한 출력의 그라디언트를 계산하여, 각 특징 맵의 중요도를 측정합니다.

  • 가중치 합산 
    각 특징 맵을 그 중요도에 따라 가중치합을 수행하여 최종 Class Activation Map을 생성합니다.
  • ReLU 적용 
    음수의 기여도를 제거하기 위해 ReLU 함수를 적용하여 최종적으로 양수의 영역만 강조합니다.

 


3. Grad-CAM 적용 코드

import torch
import torch.nn.functional as F
from torchvision import models, transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
from torchvision.models import VGG16_Weights
import os

# 사전 학습된 모델(VGG16)을 로드하고 평가 모드로 설정
model = models.vgg16(weights=VGG16_Weights.IMAGENET1K_V1)
model.eval()

# 이미지를 전처리하는 함수
preprocess = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.Lambda(lambda img: img.convert("RGB")),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# 이미지를 로드하고 전처리
img = Image.open('./tiger.jpg')
input_tensor = preprocess(img)
input_batch = input_tensor.unsqueeze(0)  # 배치 차원을 추가


# Grad-CAM을 계산하기 위해 마지막 컨볼루션 레이어의 출력을 추출
def get_activation(model, input_batch):
    activation = None

    def hook(model, input, output):
        nonlocal activation
        activation = output
        activation.retain_grad()  # 이 위치에서 retain_grad() 호출
    layer = model.features[-1]  # VGG16의 마지막 컨볼루션 레이어
    hook_handle = layer.register_forward_hook(hook)
    output = model(input_batch)
    hook_handle.remove()
    return activation, output


# 그라디언트를 추출하고 Grad-CAM 맵을 생성
def compute_gradcam(activation, model_output, target_class):
    model_output[:, target_class].backward(retain_graph=True)  # 타겟 클래스에 대한 그라디언트 계산
    gradients = activation.grad  # 그라디언트 추출
    pooled_gradients = torch.mean(gradients, dim=[0, 2, 3])  # 채널별로 평균
    for i in range(activation.shape[1]):
        activation[:, i, :, :] *= pooled_gradients[i]  # 가중 합산
    gradcam = torch.mean(activation, dim=1).squeeze()  # 채널 평균
    gradcam = F.relu(gradcam)  # ReLU 적용
    return gradcam


# 모델의 출력을 계산하고 타겟 클래스를 설정
activation, output = get_activation(model, input_batch)
target_class = output.argmax(dim=1).item()

# Grad-CAM 맵 계산
gradcam = compute_gradcam(activation, output, target_class)

# Grad-CAM 맵을 시각화
gradcam = gradcam.detach().numpy()
gradcam = np.maximum(gradcam, 0)  # ReLU를 다시 적용 (혹시 모를 음수 제거)
gradcam = gradcam / gradcam.max()  # 정규화

# 원본 이미지와 Grad-CAM을 오버레이하여 시각화
gradcam = Image.fromarray(np.uint8(gradcam * 255), 'L')
gradcam = gradcam.resize((img.size), Image.Resampling.LANCZOS)
gradcam = np.array(gradcam)

plt.imshow(img)
plt.imshow(gradcam, alpha=0.5, cmap='jet')
plt.axis('off')
plt.show()

 

 

결과

 

빨간색 영역 
모델이 가장 주목한 부분입니다. 이 영역이 예측에 가장 큰 영향을 미쳤으며, 모델이 이 부분을 통해 클래스를 결정했다고 볼 수 있습니다.

 

노란색과 녹색 영역
이 부분도 예측에 기여했지만, 빨간색 영역보다는 덜 중요하게 작용했습니다.

 

파란색 영역
모델이 상대적으로 덜 주목하거나 거의 주목하지 않은 부분입니다.

 

 

 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'딥러닝 (Deep Learning) > [06] - 평가 및 결과 분석' 카테고리의 다른 글

Ensemble 종류와 특징  (3) 2024.11.16
Object Detection 정의와 Evaluation metric (평가지표)  (4) 2024.10.02
ZFNet 딥러닝 모델 시각화와 데이터 증강(Augumentation) 이해  (3) 2024.08.29
'딥러닝 (Deep Learning)/[06] - 평가 및 결과 분석' 카테고리의 다른 글
  • Ensemble 종류와 특징
  • Object Detection 정의와 Evaluation metric (평가지표)
  • ZFNet 딥러닝 모델 시각화와 데이터 증강(Augumentation) 이해
AI-BT
AI-BT
인공지능 (AI)과 블록체인에 관심있는 블로그
  • AI-BT
    AI-BLACK-TIGER
    AI-BT
  • 전체
    오늘
    어제
    • 분류 전체보기 (133)
      • 딥러닝 (Deep Learning) (81)
        • [01] - 딥러닝 이란? (5)
        • [02] - 데이터 (4)
        • [03] - 모델 (17)
        • [04] - 학습 및 최적화 (14)
        • [05] - 논문 리뷰 (17)
        • [06] - 평가 및 결과 분석 (4)
        • [07] - Serving (6)
        • [08] - 프로젝트 (14)
      • 머신러닝 & 딥러닝 개념 (0)
        • 머신러닝 (0)
        • 딥러닝 (0)
      • Quant 투자 (12)
        • 경제 (9)
        • 퀀트 알고리즘 & 전략 개요 (3)
      • 딥러닝 Math (4)
      • AI Naver boost camp (22)
        • 회고 (19)
        • CV 프로젝트 가이드 (3)
      • Python (1)
      • 개발 및 IT 용어 (6)
        • IT 용어 (2)
        • VS Code (1)
      • 코인 정보 (7)
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
AI-BT
Class Activation Mapping (CAM)과 Grad-CAM
상단으로

티스토리툴바