파이토치 제공 Mask-RCNN의 Feature Map을 가져오기 위한 Hook 구동 관련하여 질문 있습니다.

안녕하세요. 지난번 질문올렸던 파이토치 어린이 입니다. 지난번 질문에 ChatGPT 답변으로도 해결이 안되어 포기하고 다른 방법을 강구했는데도 해결이 안되어 다시 한번 질문 남깁니다ㅠㅠ

파이토치에서 제공한 Mask-RCNN 활용 중이고, 학습 완료 후 입력 이미지들의 중간 Layer의 Feature Map들을 가져오려고 합니다. 허나 입력 이미지를 다르게 주어도 출력되는 Feature Map 이 똑같이 나와버립니다. 제 생각엔 다음 순서의 이미지에 대한 FM이 출력안되고 첫번째 이미지에 대한 FM이 계속해서 나오는 것 같은데 제 코드의 문제와 어떠한 점을 놓쳤는지 잘 모르겠습니다ㅠㅠ
도와주시면 정말로 감사드리겠습니다.

학습 완료 후 작성한 코드는 다음과 같습니다.

Hook 함수

def get_activation(name):
  def hook(models, input, output):
     activation[name] = output
  return hook

입력 이미지별 F.M 저장 위한 코드

activation = {}
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
models.to(device)

for i in range(1, 5):
  test_img = Image.open("입력 이미지 루프").convert('RGB')
  test_img = test_img.resize((800, 800))
  test_img = tr.functional.to_tensor(test_img)
  test_img = test_img.reshape(1, 3, 800, 800)

  with torch.no_grad():
     models.eval()
     models.backbone.fpn.extra_blocks.register_forward_hook(get_activation("fm{}".format(i)))
     test_img = test_img.to(device)
     models(test_img)

출력 결과

activation["fm1"] 부터 ["fm4"] 까지 동일한 값이 들어가 있음

  • 아래 답변은 OpenAI의 ChatGPT로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요. Mask-RCNN 모델의 feature map을 가져오고자 하는데, 입력 이미지를 다르게 하여도 똑같은 feature map이 나오는 문제가 발생하고 있다는 것으로 이해하겠습니다.

해당 문제는 register_forward_hook 함수에서 hook 함수를 잘못 작성하여 발생할 수 있습니다. 현재 작성하신 get_activation 함수는 해당 layer의 output feature map을 activation이라는 dictionary에 저장하는 기능을 하도록 정의되어 있는데, 이 dictionary가 global로 정의되어 있어서 모든 입력 이미지에 대해 같은 dictionary가 사용되기 때문입니다. 따라서 global dictionary 대신 입력 이미지별로 dictionary를 생성해야 합니다.

다음은 해당 문제를 해결하기 위한 예시 코드입니다.

def get_activation(name, activation):
    def hook(model, input, output):
        activation[name] = output
    return hook

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

for i in range(1, 5):
    test_img = Image.open(입력 이미지 루프).convert('RGB')
    test_img = test_img.resize((800, 800))
    test_img = tr.functional.to_tensor(test_img)
    test_img = test_img.to(device)
    activation = {}
    hook_fn = get_activation('fm{}'.format(i), activation)
    handle = model.backbone.fpn.extra_blocks[i-1].register_forward_hook(hook_fn)
    with torch.no_grad():
        model.eval()
        model(test_img)
    handle.remove()
    print(activation['fm{}'.format(i)])

위 코드에서는 각 입력 이미지에 대해 새로운 activation dictionary를 생성하고, get_activation 함수 내부에서 해당 dictionary를 이용하도록 변경하였습니다. 또한, register_forward_hook 함수를 사용할 때 각 layer의 순서가 무엇인지 확인하여 올바른 layer에 hook 함수를 등록하도록 수정하였습니다.

코드에서 handle.remove()을 사용하면 해당 hook 함수를 삭제할 수 있습니다. 따라서 이 코드가 단 한 번 실행되고 나면 해당 hook 함수는 삭제되기 때문에 다음 이미지에서는 올바른 hook 함수가 등록됩니다.

만약 위 방법이 문제를 해결하지 못한다면, 다른 부분을 찾아봐야 할 수도 있습니다. 이 경우 코드의 전체 내용을 공유해 주시면 더 자세한 도움을 드릴 수 있을 것입니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주세요!