제목대로 torch_lightning으로 구현된 모델을 grad_cam으로 설명하고 싶은데
output이 다르고 모델 레이어에 접근하는 방식도 좀 다르더라고요
grad_cam 라이브러리를 사용해서 해석하는건 불가능하겠죠..??
gpt랑 이것저것 보면서 만든건데 아무래도 이상한거 같아서요..
LivenessClassifier의 가정된 구조에 기반한 예시
import torch
import cv2
import numpy as np
import matplotlib.pyplot as plt
from torchvision import transforms
from PIL import Image
LivenessClassifier 임포트
from main import LivenessClassifier
target_layer를 지정할 때, 문자열로 경로를 지정하여 레이어에 접근합니다.
경로는 ['net', 'auxcfer', 'resnet18', 'layer4', '1', 'conv2']와 같은 형태일 수 있습니다.
def grad_cam(model, input_image, target_layer, target_class=1):
# 모델을 평가 모드로 전환
model.eval()
# 모델에 입력
outputs = model(input_image)
# 모델의 출력이 튜플인지 확인
if isinstance(outputs, tuple):
# 주 출력 텐서 선택 (일반적으로 마지막 요소)
outputs = outputs[-1]
# 클래스 스코어 선택 (이진 분류일 경우 0 또는 1 선택)
class_score = outputs[:, target_class]
# backward 수행
class_score.backward()
# target_layer 경로에 따라 레이어에 접근
target_module = model
for layer in target_layer:
if hasattr(target_module, layer):
target_module = getattr(target_module, layer)
else:
raise AttributeError(f"{layer}가 존재하지 않습니다.")
# target_layer에서 그래디언트와 활성화 맵을 얻기
gradients = target_module.weight.grad
activations = target_module.weight.detach()
# 그래디언트의 평균을 통해 가중치 계산
pooled_gradients = torch.mean(gradients, dim=[0, 2, 3])
# 활성화 맵에 가중치 부여
for i in range(activations.shape[1]):
activations[:, i, :, :] *= pooled_gradients[i]
# 최종 heatmap 생성
heatmap = torch.mean(activations, dim=1).squeeze()
heatmap = torch.relu(heatmap)
heatmap /= torch.max(heatmap)
return heatmap
Grad-CAM 시각화 함수
def visualize_grad_cam(input_image, heatmap):
heatmap_np = heatmap.cpu().numpy()
heatmap_resized = cv2.resize(heatmap_np, (input_image.shape[2], input_image.shape[3]))
heatmap_jet = cv2.applyColorMap(np.uint8(255 * heatmap_resized), cv2.COLORMAP_JET)
superimposed_img = heatmap_jet * 0.4 + (input_image.squeeze(0).permute(1, 2, 0).numpy() * 255)
superimposed_img = np.uint8(superimposed_img)
plt.imshow(superimposed_img)
plt.axis('off')
plt.show()
실행 예시
if name == 'main':
# LivenessClassifier 인스턴스화 및 평가 모드 전환
model = LivenessClassifier.load_from_checkpoint('./lightning_logs/version_14/checkpoints/epoch=39-step=39.ckpt') # LivenessClassifier 클래스 사용
model.eval()
print(type(model))
print(model._modules['net']._modules['auxcfer']._modules['resnet18']._modules['layer4']._modules['1']._modules['conv2'])
print('-'*100)
# 이미지 로드 및 전처리
image_path = '001.jpg'
image = Image.open(image_path)
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
])
image_tensor = transform(image).unsqueeze(0) # 배치 차원 추가
# Grad-CAM 실행 및 시각화
target_layer = ['net', 'auxcfer', 'resnet18', 'layer4', '1', 'conv2']
heatmap = grad_cam(model, image_tensor, target_layer, target_class=1) # 적절한 레이어 이름 사용
visualize_grad_cam(image_tensor, heatmap) # Grad-CAM을 시각화