모션 키포인트 검출 AI 경진대회

파이토치를 이용한 ResNet101과 Keypoint R-CNN 학습과 시각화

2021.02.10 21:06 11,517 조회 language

안녕하세요. 키포인트 시각화부터 파이토치 torchvision의 Keypoint R-CNN 학습까지 정말 간단한 코드입니다.

*업데이트
1. torchvision에서 제공하는 모형은 Resize와 Normalize 부분이 필요없습니다. 해당 라인을 삭제했습니다.
2. 다른 백본으로 교체할 수 있도록 코드를 업데이트했습니다. 
3. torchvision 최신 버전을 사용하시는 분들은 아래 Domin님 댓글을 참고하세요.

1. 키포인트 연결부분 시각화를 위해서는 각 랜드마크 연결을 미리 정의해야 합니다. 나중에 업데이트하겠습니다.
2. 미리 학습된 torchvision의 Keypoint R-CNN으로 키포인트 추론은 매우 매우 잘 되지만, 본 대회 데이터셋을 그대로 적용안됩니다.
3. 스크립트에서 노트북으로 복사/붙여넣기했습니다. 정상작동이 안될수도 있습니다.

참고: 코딩 스타일은 을 지킵니다. 파이썬 인덴트는 공백 4칸인데, 데이콘에 노트북 업로드 시 공백이 2칸으로 변경되네요. 4칸으로 수정해서 사용하시기 바랍니다.

코드
로그인이 필요합니다
0 / 1000
Mather
2021.02.10 22:18

새해 복 많이 받으세요~

우주대마왕
2021.02.11 22:14

새해 복 많이 받으세요~

DACONIO
2021.02.15 10:50

코드 공유 감사합니다!! 

2B데이터마스터
2021.02.17 16:20

코드공유 감사합니다.

yolo
2021.02.21 21:27

코드 공유 감사합니다!!

나는닉네임
2021.02.22 23:36

코드 공유 감사합니다.

tinaandmk
2021.02.25 22:46

코드 공유 감사합니다.

kitsunetic
2021.02.26 18:06

코드 공유 감사합니다
공유해주신 코드 그대로 실행할 시 train() 에서

/usr/local/lib/python3.7/dist-packages/torchvision/models/detection/anchor_utils.py in grid_anchors(self, grid_sizes, strides)
    101         cell_anchors = self.cell_anchors
    102         assert cell_anchors is not None
--> 103         assert len(grid_sizes) == len(strides) == len(cell_anchors)
    104 
    105         for size, stride, base_anchors in zip(

AssertionError: 

이런 오류가 있는데 확인 가능할까요?

우주대마왕
2021.02.27 13:41

anchor 생성하는 구간에서 에러가 발생한건데 get_model() 그대로해서 모형을 만드신거면 파라미터로 변경되는 부분이 없어서 저기서 에러가 발생하지 않을 것 같습니다. 

anchor는 RPN 내부에서 작동합니다. RPN은 백본을 지난 특징 맵과 원본 이미지를 인자로 받습니다. 기본 파라미터는  
anchor_sizes = ((32,), (64,), (128,), (256,), (512,))
aspect_ratios = ((0.5, 1.0, 2.0),) * len(anchor_sizes)

이라 정상작동되는 부분이고 백본을 거친 특징 맵에서 문제가 발생한 것 같은데, 백본을 다른 걸로 바꾸신건지?

kitsunetic
2021.03.02 11:22

답글 늦어서 죄송합니다.
백본이나 수정한 부분은 없고 업로드하신 코드 그대로에 파일 경로 정도만 바꿨습니다.

우주대마왕
2021.03.03 00:33

혹시 토치랑 토치비전 버전이 몇인가요?

몽실이
2021.02.28 22:52

올려주신 코드 그대로 실행할 시 윗분처럼 에러가 나네요..

우주대마왕
2021.03.03 00:33

혹시 토치랑 토치비전 버전이 몇인가요?

몽실이
2021.03.04 00:20

둘다 최신버전 사용하고 있습니다!

우주대마왕
2021.03.04 10:01

이 코드는 torchvision==0.7이라 0.8 이상은 아래 Domin님 코드로 하시면 되겠습니다~

등장음
2021.03.03 23:41

감사합니다!

Domin
2021.03.04 02:17

AssertionError:  
(https://pytorch.org/docs/stable/_modules/torchvision/models/detection/keypoint_rcnn.html#keypointrcnn_resnet50_fpn)

공식홈페이지 보면 keypointrcnn 모델 파라미터로 rpn_anchor_generator이 필요해서 이부분만 아래와 같이 추가해서 해결했어요

from torchvision.models.detection.anchor_utils import AnchorGenerator

 anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),
                                   aspect_ratios=((0.5, 1.0, 2.0),))


    model = KeypointRCNN(
        backbone, 
        num_classes=2,
        num_keypoints=24,
        box_roi_pool=roi_pooler,
        keypoint_roi_pool=keypoint_roi_pooler,rpn_anchor_generator=anchor_generator
    )

우주대마왕
2021.03.04 10:02

감사합니다~ Domin님, 
torchvision==0.8 이신 분들은 Domin님처럼 AnchorGenerator 임포트해서 해주시면 되겠습니다. 
0.7은 해당 모듈이 임포트 되지 않습니다!

몽실이
2021.03.04 10:58

버전 차이가 있었군요.. 모바일넷의 경우는 domin 님 코드대로, 그 외 다른 백본은  aspect_ratios에 size length를 곱해주셔야 합니다!

kitsunetic
2021.03.06 09:34

감사합니다

등장음
2021.03.04 23:44

삭제된 댓글입니다

songbae
2021.03.05 11:31

중간에 학습한 train된 모델을 best_model.pth  라는 형태로 저장을 했다면 이모델을 불러와서 새로운 testset에 적용하려면 어떤식으로 불러와야할까요?

Domin
2021.03.05 14:34

model = get_model().to(device)
d = torch.load("./best_model.pth")
model.load_state_dict(d)

하르딘
2021.03.06 21:27

코드 공유 감사합니다. 많은 공부되었습니다.

추가로 궁금한 부분이 있어 질문 드립니다.
keypointrcnn_resnet50_fpn을 이용하여  추론 했을 경우 이미지 하나를 넣었는데
각 결과(boxes, labels 등)의 torch.size 중 0축이 모두 8인 것을 확인했습니다.

공식문서에는 해당 위치를 N이라고 표시하고 있어 
저는 Batch size로 생각하고 이미지 하나를 넣었으니 1이 나오는 것이 맞다고 생각했었는데

왜 8이 나오는지 이해가 잘 안됩니다.
ex. boxes의 shape: torch.Size([8, 4]), keypoints의 shape: torch.Size([8, 17, 3])

한 수 가르쳐 주시면 감사하겠습니다 ㅠ

우주대마왕
2021.03.07 12:57

바운딩 박스 FloatTensor[N, 4], 키포인트 FloatTensor[N, K 3]에서의 N은 한 이미지 포함된 객체들의 개수입니다. 해당 대회의 데이터셋 이미지 당 객체는 다 하나씩이라 키포인트는 FloatTensor[1, 24, 3]이 됩니다.
torch에서 N은 배치사이즈가 아닙니다. 토치 문서를 잘 살펴보시면 배치는 B로 표현합니다. 그래서 Conv2d를 보면 [B, C, H, W] 배치사이즈, 채널 수, 높이, 너비입니다. 

비전 모형 대부분은 다음과 같이 작동합니다. Object Detection으로 설명을 하자면, 내가 테스트할 사진에는 객체가 하나밖에 없으니 하나의 결과값이 리턴되어야 하지 않냐? 라고 말할 수 있고 그게 맞지만, 사실 지정된 매개변수에 따라, 모형의 학습 정도에 따라 조절됩니다. 예를 들면 SSD 모형의 경우 미리 설정한 디폴트 박스 개수만큼 뿌려줍니다. 보통 약 8,000개 정도 예측됩니다. Keypoint RCNN은 테스트 시 1,000개를 예측합니다. 이 8,000개 중에서 matching 전략, confidence score 또는 objectness라 불리는 값에 임계값과 NMS 등 다양한 방법으로 후처리해서 테스트할 사진에 있는 객체의 수 만큼 보여주는 거죠.

따라서 사용한 모형의 특징에 따라, 모형의 학습 정도에 따라, 후처리에 사용한 매개변수 값에 따라 예측값은 원하는 개수가 될 수도 있고 아닐 수도 있습니다. 여기서 모형의 특징이라고 하면 YOLOv1 베이스 모형의 경우, 모형에서 예측된 객체의 개수는 최대 98개입니다. 왜냐면 베이스의 경우, 7x7 그리드에서 바운딩 박스를 두 개씩 만 생성하기 때문입니다. 따라서 내가 테스트할 이미지에 사람이 200명이 있다면 YOLOv1 베이스에서는 200명을 전부 예측하지 못합니다.

하르딘
2021.03.07 19:34

아! N에 어떤 값이 들어가게 되는 것인지 이해가 되었습니다
친절한 설명 감사드립니다! ㅎㅎ