요약
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의 분류). 그 다음, $A^k$은 각 Feature Map을 의미한다. Feature Map은 이미지가 CNN을 통과한 결과를 의미한다. $k$가 붙는 이유는 CNN을 통과하고나서 CNN의 필터의 개수(k)만큼 반환되는 값(feature map)의 k채널이 생기기 때문이다. 일종의 채널과 같다.
마지막으로 $a_{k}^{c}$은 $A^{k}$의 필터맵이 이미지와 유사한데, 이 필터맵의 각 픽셀들이 분류에 어느정도 기여했는지를 의미한다. 아래의 그림(Figure 1)을 보자. Feature maps이 4개가 있으니 $k=4$인 예시이다. 녹색의 feature maps을 보면, 5x5로 이미지가 이루어져 있는데, 각 $i, j$에 해당하는 픽셀이 $y^{c}$에 어느정도 기여했는지를 구한 것이다.
즉, Grad-CAM은 각 feature Map이 어느정도 모델의 결과값($y$)에 기여했는지($A^{k}$)와 각 픽셀이 모델의 결과값에 어느정도 기여했는지($a_{k}^{c}$)을 곱하는 것이다. 결국, 각 픽셀이 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 |