
요약
Grad-CAM은 CNN 기반의 모델을 해석할 때 사용되는 방법이다. 인공지능의 해석방법(XAI)에서는 Grad-CAM은 흔히 Post-hoc으로 분류되고(일단, 모델의 결과(Y)가 나오고 나서 다시 분석사는 방법)으로 취급된다. 또한, 딱 CNN에서만 사용되기 때문에 Model-specific 방법이다. 이 Grad-CAM의 가장 큰 쉬운 마지막 CNN이 나오고 나서 반환되는 Feature Map(본문에서:A)이 평균적으로 Y의 분류에 어느정도 되는지를 계산하고, 각 픽셀별로 이를 선형으로 곱하는 방법이다.
상세 내용
Grad-CAM은 아래와 같이 계산할 수 있다.

각, 기호에 대한 설명은 아래와 같다. y은 모델이 내뱉는 확률이며, c는 특정 라벨을 의미한다. 개 vs 고양이의 분류기이면 c의 최대값은 2이 된다(=1, 2의 분류). 그 다음, Ak은 각 Feature Map을 의미한다. Feature Map은 이미지가 CNN을 통과한 결과를 의미한다. k가 붙는 이유는 CNN을 통과하고나서 CNN의 필터의 개수(k)만큼 반환되는 값(feature map)의 k채널이 생기기 때문이다. 일종의 채널과 같다.

마지막으로 ack은 Ak의 필터맵이 이미지와 유사한데, 이 필터맵의 각 픽셀들이 분류에 어느정도 기여했는지를 의미한다. 아래의 그림(Figure 1)을 보자. Feature maps이 4개가 있으니 k=4인 예시이다. 녹색의 feature maps을 보면, 5x5로 이미지가 이루어져 있는데, 각 i,j에 해당하는 픽셀이 yc에 어느정도 기여했는지를 구한 것이다.

즉, Grad-CAM은 각 feature Map이 어느정도 모델의 결과값(y)에 기여했는지(Ak)와 각 픽셀이 모델의 결과값에 어느정도 기여했는지(ack)을 곱하는 것이다. 결국, 각 픽셀이 feature maps을 고려하였을 때(가중하였을 때) 결과값에 어느정도 영향을 미쳤는지를 계산할 수 있다.
구현:
torch에서는 register_foward_hook과 register_backward_hook을 이용하여 grad cam을 계산할 수 있습니다. register_forward_hook과 register_backward_hook은 PyTorch에서 모델의 레이어에 대한 forward pass와 backward pass 중간에 호출되는 함수를 등록하는 메서드입니다. 이를 통해 레이어의 활성화 맵이나 그래디언트를 추출하거나 조작할 수 있습니다.
register_forward_hook:
이 메서드는 모델의 레이어에 대해 forward pass가 수행될 때 호출되는 함수를 등록합니다. 등록된 함수는 해당 레이어의 출력을 인자로 받아 다양한 작업을 수행할 수 있습니다. 주로 활성화 맵 등 중간 결과를 추출하거나 조작하는 데 사용됩니다.
def forward_hook(module, input, output):
# module: 레이어 인스턴스
# input: forward pass의 입력
# output: forward pass의 출력
pass
target_layer.register_forward_hook(forward_hook)
register_backward_hook:
이 메서드는 모델의 레이어에 대해 backward pass가 수행될 때 호출되는 함수를 등록합니다. 등록된 함수는 해당 레이어의 그래디언트를 인자로 받아 다양한 작업을 수행할 수 있습니다. 주로 그래디언트를 조작하거나 특정 그래디언트 정보를 추출하는 데 사용됩니다.
def backward_hook(module, grad_input, grad_output):
# module: 레이어 인스턴스
# grad_input: 입력 그래디언트
# grad_output: 출력 그래디언트
pass
target_layer.register_backward_hook(backward_hook)
위의 두 함수를 이용하여 아래와 같이 구현할 수 있습니다.
def grad_cam(
model: torch.nn.Module,
image: np.ndarray,
target_layer: torch.nn.Module,
) -> np.ndarray:
"""
Args:
model (torch.nn.Module): Grad-CAM을 적용할 딥러닝 모델.
image (np.ndarray): Grad-CAM을 계산할 입력 이미지.
target_layer (Type[torch.nn.Module]): Grad-CAM을 계산할 대상 레이어.
Returns:
np.ndarray: Grad-CAM 시각화 결과.
"""
def forward_hook(module, input, output):
grad_cam_data["feature_map"] = output
def backward_hook(module, grad_input, grad_output):
grad_cam_data["grad_output"] = grad_output[0]
grad_cam_data = {}
target_layer.register_forward_hook(forward_hook)
target_layer.register_backward_hook(backward_hook)
output = model(image) # 모델의 출력값을 계산합니다. y_c에 해당
model.zero_grad()
# 가장 예측값이 높은 그레디언트를 계산합니다. output[0,]은 차원을 하나 제거
output[0, output.argmax()].backward()
feature_map = grad_cam_data["feature_map"]
grad_output = grad_cam_data["grad_output"]
weights = grad_output.mean(dim=(2, 3), keepdim=True)
cam = (weights * feature_map).sum(1, keepdim=True).squeeze()
cam = cam.detach().cpu().numpy()
return cam
'Data science > Computer Vision' 카테고리의 다른 글
이미지분할 Grabcut 사용법 (0) | 2023.04.26 |
---|---|
NMS(Non maximal supression) 계산하기, 파이썬 (0) | 2023.03.18 |
5분컷이해 Morphological transformation (형태변형) 설명 (0) | 2022.09.18 |
python CV2, Image, Numpy 의 이미지 처리축 (0) | 2021.12.18 |
SSIM (Structural Similarity Index) 구하기 (0) | 2021.06.02 |