【Detection】TridentNet - Scale-Aware Trident Networks for Object Detection

  • 논문 : Scale-Aware Trident Networks for Object Detection
  • 분류 : Scale-Aware Object Detection
  • 저자 : Yanghao Li, Yuntao Chen, Naiyan Wang, Zhaoxiang Zhang
  • PS
    1. COCO에서 Small, Medium, Large의 기준이 무엇인가? 참고 Page, (핵심 복붙 : In COCO, there are more small objects than large objects. Specifically: approximately 41% of objects are small (area < 322), 34% are medium (322 < area < 962), and 24% are large (area > 962). Area is measured as the number of pixels in the segmentation mask.)
    2. 전체적으로 약 파는 논문 같다. 비교도 자기의 모델(ablation) 비교가 대부분으고. 최근 기법들이랑 비교도 안하고…
    3. 파라메터 share하는 거 말고는, 앙상블이랑 뭐가 다른지. 모르겠고 왜 이게 논문이고 citation이 250이나 되는지 모르겠다. 속도보단 성능. 실용성보단 연구. 라는 느낌이 강해서 내맘에 들지 않는 논문이다.
  • 목차
    1. TridentNet Paper Review
    2. Code

TridentNet

1. Conclusion, Abstract, Introduction

  • 아래와 같은 Network를 설계하여, trident blocks 들이 다른 receptive field를 가지게 함으로써, scale-aware feature maps 을 생성한다.
    image-20210311185032430
  • our contributions 정리
    1. effect of the receptive field 에 대해서 조사해보았다.
    2. scale-specific feature maps을 생성하는 TridentNet를 소개한다.
    3. ` scale-aware training scheme` 를 사용해서 각각의 branch가 적절한 크기의 객체를 추출하는데 특화되도록 만든다.
    4. TridentNet Fast 를 소개한다.
    5. a parallel multi-branch architecture : 각 branch 들이 자신들의 transformation parameter를 공유하지만(trident-block 들이 서로의 weight를 sharing), 서로 다른 receptive fields를 가지도록 한다.
    6. mAP of 48.4 using a single model with ResNet-101 backbone

3. Investigation of Receptive Field

  • Architecture의 디자인 요소 중, Receptive feild에 대한 영향력 조사에 대한 논문은 없었다. 따라서 우리가 다른 Dilation rate를 사용함으로써 receptive field 에 대한 영향력을 조사해보았다.
  • dilation rate (d_s) 를 사용하면, network의 receptive field를 증가시키는 장점을 얻을 수 있다.
  • 아래와 같이 실험을 했고, 오른쪽 표가 실험의 결과이다.
  • 이를 통해서, receptive field가 객체 크기에 따른 검출 성능에 영향을 준다는 것을 파악했다.
  • 특히! 큰 객체에 대해서 더 검출을 잘하는 것을 파악할 수 있다. (이 논문 전체를 보면 small object의 성능 검출 보다는 보통 large object에 따른 성능 증가가 많은 편이었다.)
  • ResNet101을 사용했을 때 조차도, receptive field를 넓혀줬을 때, 성능이 향상되었다. 이론적인 receptive field 보다, [practical하고 실험적이고 effective한] receptive field는 더 작다는 것을 증명하는 사례이다.

image-20210311223956455


4. Trident Network

4.1. Network Structure

  • Multi-branch Block
    1. single scale input이 들어가고, 평행하게 각 branch가 scale-specific feature map을 만들어 낸다.
    2. TridentNets은 임이의 Network의 Conv연산을 trident blocks으로 바꿔서 만들어 낸다.
    3. (실제 이 논문의 목표는 어떤 전체 Architecture를 만든게 아니다. Faster-RCNN 그리고 RPN 혹은 ResNet backbone의 특정부분의 Conv연산을 trident block으로 대체하여 사용한게 전부이다. 어떻게 어느 부분을 바꾸었는지는 구체적으로 나와있지 않다.)
    4. Typically, we replace the blocks in the last stage of the backbone network with trident blocks / since larger strides lead to a larger difference in receptive fields as needed. 즉, ResNet 중에서도 Deep한 부분부터 trident block을 삽입해 사용했다고 한다. 뒤의 실험에서도 나오겠지만, Deep 한 곳에 적용해야 효과가 좋다. 왜냐하면, Deep한 곳의 각각의 Featrue Pixel들은 이미 큰 Receptive field를 가지는데, 거기다가 Trident Block을 적용해서 더! 큰 Receptive Field를 가지게 만드는 것이다.
    5. (이것을 코드로 구현하는 것은 어렵지 않을 것 같다. 일단 Faster-RCNN코드를 하나 가져온다. 그리고 그 코드에 있는 일부 nn.conv2d 에 Dilation rate를 추가해준다. 그럼 그게 하나의 branch이다. 그렇게 각각의 net=build_module()을 3개 만든다. net1, net2, net3. 그리고 이것들을 가지고 NMS해주면 끝. (NMS가 그냥 앙상블 수준이다.))
      image-20210311225603287
  • Weight sharing among branches
    1. 모든 Branch는 RPN and R-CNN heads의 일부 conv를 Trident Block으로 대체하여 사용한다.. 그리고 (서로 dilation rate만 다른) 각각의 Branch에 대해서, the same parameters를 공유한다.
    2. 그렇기 때문에 추가적인 파라미터가 필요하지 않다. (물론 연산은 3배로 해야하는 것은 맞다.)
    3. 학습 중에서도 파라메터가 공유되어 학습된다.
  • Scale-aware Training Scheme
    1. 위의 표를 보면 Small object에 대해서는 Large Receptive Field를 가지는 branch에서는 오히려 낮은 성능이 나오는 것을 확인할 수 있다.
    2. 이것을 objects of different scales, on different branches 즉 mismatched branches 라고 표현할 수 있다.
    3. 따라서 이러한 문제를 피하고자, 각각의 branch가 the scale awareness를 가지게 하도록 하는 a scale-aware training scheme을 수행했다.
    4. 어려운게 아니라, 각 Branch마다 담당하는 객체의 크기가 다르다. 위의 (1) 식과 같이 l_i와 u_i를 설정한다. 그리고 ROI 즉 이미지의 위에서 객체의 크기를 w, h 라고 했을 때, 일정 범위의 객체일 때만, 각 Branch가 Predict 해야하는 GT로 사용하도록 만든다.
  • Inference and Approximation
    1. 각각의 Branch에서 Detect 결과를 받아서 NMS 혹은 NMS를 사용해서 최종 결과로써 반환한다.
  • Fast Inference Approximation
    1. 연산을 3배로 해야하기 떄문에 속도가 매우 느리다. 그래서 inference하는 동안 좀더 좋은 속도를 얻고 싶다면, 중간 branch 만을 사용한다. (dilation rate = 2 )
    2. (아니 특별한 것도 아니고 겨우 이게 Fast inference 기법이란다. 무슨 약 파는 것도 아니고 어이가 없는 논문이다.)
    3. 확실히 performance drop 이 발생하지만, weight-sharing strategy을 사용하기 때문에 중간 성능에서는 좋은 성능을 보인다. (Figure2 확인)

5. Experiments

  • Table4 는 ResNet에서 trident blocks을 어디다 놓을지 정하는 실험이다. conv2,3,4가 의미하는 곳이 어딘지 모르겠으나, (논문에 안 나와 있음. ResNet논문 혹은 코드를 봐야함) conv4에서 사용하는게 좋다고 한다. 위에서 말했듯이 더 deep한 곳에서 사용해야 더 확실하게 receptive field를 크게 하는것에 도움을 받는다고 한다.

image-20210311230859944

【In-Segmen】BlendMask - Top-Down Meets Bottom-Up w/ my advice

  • 논문 : BlendMask: Top-Down Meets Bottom-Up for Instance Segmentation
  • 분류 : Real Time Instance Segmentation
  • 저자 : Hao Chen, Kunyang Sun, Zhi Tian, Chunhua Shen
  • 느낀점 :
    • 논문 필기 본은 C:\Users\sb020\OneDrive\21.1학기\논문읽기_21.1 참조하기.
    • 내 생각이 옳다고 200프로 생각하지 말자. 다른 사람의 말과 논리가 맞을 수 있다. 내 논리를 100프로 버리고 상대의 의견과 논리를 들어보자. 인간은 절대 정확할 수 없다. 상대방의 말을 들을 때는, 단어 하나를 곱 씹고 이해하려고 노력하자.
    • 확실히 Method를 보고 Conclusion, Abstract, Introduction 를 보면 이해가 훨씬 잘되고, 단어가 바뀌거나, 표현이 바뀌어도 확 이해가 된다. 따라서 제발 Method 부터 읽자. 괜히 깝치지 말고 Method부터 읽자. 왜 같은 실수를 계속 반복하는가? 초반 Conclusion, Abstract, Introduction에서 5분 이상 허비하지 말자.
  • 읽어야 하는 논문
    • FCIS [18]
  • 목차
    1. BlendMask Paper Review
    2. Code

BlendMask

1. Conclusion, Abstract, Introduction

  • 성능 : Mask R-CNN 보다 20% faster. BlendMask-RealTime achieves 34.2% mAP at 25 FPS evaluated on a single 1080Ti GPU
  • (뭔소리지?) effectively instancelevel information 와 semantic information 를 결합해서 사용했다. top-down과 bottom-up 방법을 아주 적절히 혼합해 사용했다. (hybridizing top-down and bottom-up approaches, FCIS [18] and YOLACT [3] )
  • BlendMask는 1번의 conv로 attention map을 학습하고, 이를 이용해 K=4개의 channel만으로 Instance segmentation 예측을 수행한다.
  • top-down approach 의 단점 (sementic -> instance) (일단 그래도 복붙. 논문 안 읽어서 뭔소린지 모름)
    1. DeepMask [23]
    2. local-coherence between features and masks is lost
    3. the feature representation is redundant because a mask is repeatedly encoded at each foreground feature
    4. position information is degraded after downsampling with strided convolutions
  • bottom-up approach의 단점 (box -> segmentation)
    1. heavy reliance on the dense prediction quality (ROI 결과에 너무 많이 의존된다.)
    2. 많은 수의 class가 담긴 복잡한 장면을 이해하는 능력의 일반화에 제한이 있다. (panoptic segmentation 힘듬)
    3. 복잡한 post-processing 절체가 필요하다.
  • 우리 모듈의 핵심 Blender module : BlendMask에서는 얕지만 디테일한 정보깊지만 의미론적인 정보를 융합해사용한다.
    1. 얕지만 디테일한 정보 : better location information, finer details, accurate dense pixel features. (Bottom Module)
    2. 깊지만 의미론적인 정보 : larger receptive field, rich instance-level information (Tower = Top layer)
    3. mask combination! = blender
  • FCOS에 simple framework 만 추가해서 BlendMask를 만들었다.

3. Our BlendMask

  • the decoder(Backbone) of DeepLabV3+ 을 사용했다.
  • 아래 그림과 필기 먼저 보기
  • M은 Mask prediction (R) 보다 작다. 왜냐면 attention에 대한 rough estimate 만을 모델에게 물어보는것 이기 떄문이다.
  • 저 과정을 통해, 어떤 Attention이 이뤄졌다는지 모르겠다. 아! “H_l x W_l 내부의 하나하나의 픽셀들이, R x R에 대해 어떻게 attention 할 필요가 있는가?” 라고 생각하면 되겠다!

SmartSelect_20210311-125649_Noteshelf.jpg

  • 수정본 (그림 중간에 MxM 에 엑스(X)가 처진것은, MxM ==> RxR 로 Interpolate가 되는 것을 의미한다.)

SmartSelect_20210311-143514_Noteshelf.jpg

  • 3.4 Semantics encoded in learned bases and attentions
    image-20210311170839067

4. Ablation Experiments

  • 많은 실험을 통해서, 어떤 알고리즘을 사용할지 선택한다.
    image-20210311171245648
  • 특히 Other improvements
    1. YOLACT에서 사용한, auxiliary semantic segmentation supervision 방법을 활용하여 성능향상을 많이 얻었다.
    2. 그 외는 필요하면 논문 참조
  • Fast NMS 을 사용해서 속도 향상을 했지만, 성능감소가 커서 Batched NMS in Detectron2 를 사용했다.
    image-20210311171300645

  • 잘못 필기한 그림 (혹시나 필요하면 참고하기)
    SmartSelect_20210311-125616_Noteshelf.jpg

w

【In-Segmen】Mask Scoring R-CNN & YOLACT++

  • 논문1 : Mask Scoring R-CNN
  • 논문2 : YOLACT++
  • 분류 : Real Time Instance Segmentation
  • 저자 : Zhaojin Huang, Lichao Huang / Daniel Bolya, Chong Zhou
  • 느낀점 :
    • 핵심만 캐치하고 넘어가자. 필요하면 그때, 다시 보자.
    • (PS) 논문 필기 본은 C:\Users\sb020\OneDrive\21.1학기\논문읽기_21.1 참조하기. 그리고 논문 필기 본을 보면 X 친 부분이 많듯이, 논문을 거의 안 읽었다. 핵심만 파악했다.
  • 목차
    1. Mask Scoring R-CNN Paper Review
    2. YOLACT++ Paper Review
    3. Code

A. Mask Scoring R-CNN

  • 그리고 논문의 영어문장 난이도도 높은 편이다. 모든 세세한 내용들이 다 적혀있는 게 아니므로, 코드를 찾아보고 확실히 알아보는 시간도 나중에 필요할 듯하다.

1. Conclusion, Abstract, Introduction

  • 현재 instance segmentation 의 score 문제점을 파악하고, 이를 해결하는 방법으로 Mask Scoring을 제안했다.
  • (마스크 예측을 얼마나 잘했는지) the quality of the predicted instance masks를 체크하는 MaskIOU head를 추가했다.
  • mask quality 와 mask score 를 명확하게 규정하고 정의하여, evaluation하는 동안에 더 정확한 Mask를 Prioritizing (우선 순위 지정)을 통해서 전체 성능을 향상시킨다.
  • 현재 Mask RCNN의 문제점을 파악해 보자.
    image-20210309134653066
  • very simple and effective (하지만, 논문의 결과들을 보면 MaskIOU head를 추가해서 속도와 파라메터의 증가가 얼마나 일어났는지는 나와있지 않다.)

2. Method

  • 3.1. Motivation
    image-20210309134918464
  • 3.2. Mask scoring in Mask R-CNN
    • Mask scoring = S_mask
      1. S_mask는 Mask head에서 binary segmenation을 얼마나 잘했는지 평가하는 수치이다. (내 생각으로, 이 값이 Final (class&mask) Confidence 인 듯하다. 이 S_mask를 구체적으로 어떻게 사용했는지는 코드를 통해서 확인해야 할 듯 하다. 논문 자체에서도 매우 애매하게 나와있다.)
      2. classification과 mask segmentation 모두에 도움이 될 수 있도록, S_mask = S_cls x S_iou 으로 정의해 사용했다. 여기서 S_cls는 Classification head에서 나온 classification score를 사용하고, S_iou는 MaskIoU head에서 나온 값을 사용한다.
      3. 이상적으로는 GT와 같은 Class의 Mask에 대해서 만 Positive value S_mask가 나와야 하고, 나머지 Mask의 S_mask는 0이 나와야 한다.
    • MaskIoU head
      image-20210309140843950
      1. 논문을 읽으면서 위와같이 필기했지만, 애매한 부분이 너무 많다. “Training 혹은 Inference 과정에서는 각각 어떻게 행동하는지?, GT는 무엇이고?, 전체를 사용하는지 해당 Class 값만 사용하는지?” 이런 나의 궁금증들은 논문으로 해결할 수 없었다. 코드를 봐야한다.
      2. 하지만 전체적인 그림과 핵심 파악은 위의 그림만으로도 파악이 가능하다.
      3. 위의 Max pooling은 kernel size of 2 and stride of 2 를 사용한다.
    • Training
      1. (Mask R-CNN 과정과 같이) GT BB와 Predicted BB의 IOU가 0.5이상을 가지는 것만 Training에 사용한다.
      2. (위 그림의 숫자 2번과정) target class 에 대해서만 channel을 뽑아오고, 0.5 thresholding을 통해서 binary predicted mask 결과를 찾아낸다.
      3. binary predicted mask 과 GT mask결과를 비교해서 MaskIoU를 계산한다. 이것을 GT MaskIoU로써 Mask Head의 최종값이 나와야 한다. 이때 Mask head의 최종결과 값 predicted MaskIOU값이 잘 나오도록 학습시키기 위해서, L_2 loss를 사용했다. (구체적 수식 없음)
    • Inference
      1. 지금까지 학습된 모델을 가지고, 이미지를 foward하여, Class confidence, box 좌표, binary mask, Predicted MaskIOU를 얻는다.
      2. Class confidence, box 좌표만을 가지고, SoftNMS를 사용해서 top-k (100)개의 BB를 추출한다.
      3. 이 100개의 BB를 MaskIOU head에 넣어준다. 그러면 100개에 대한 predicted MaskIOU를 얻을 수 있다.
      4. predicted MaskIOU x Class confidence 를 해서 Final Confidence를 획득한다.
      5. Final Confidence에서 다시 Thresholding을 거치면 정말 적절한 Box, Mask 결과 몇개만 추출 된다.

3. Experiments and Results

  • Experiments
    • resized to have 600px along the short axis and a maximum of 1000px along the long axis for training and testing
    • 18 epochs
    • (초기 learning rate는 안나와있다. 0.1 이겠지뭐..) decreasing the learning rate by a factor of 0.1 (10분의 1) after 14 epochs and 17 epochs
    • SGD with momentum 0.9
    • SoftNMS
  • Quantitative Results And Ablation Study
    image-20210309142550139

B. YOLACT++

image-20210309163534601

  • 위의 그림과 같이 그냥 YOLACT과 다른 점은 크게 3가지이다.
    1. efficient and fast mask rescoring network : mask quality를 고려해서, mask predictions에 대한 re-ranking을 한다.
    2. backbone network : deformable convolutions를 사용해서, instances검출을 위한 더 나은 feature sampling을 수행한다.
    3. anchors 종류를 새롭게 하였다.
  • Fast Mask Re-Scoring Network
    1. Mask Scoring RCNN의 방법을 채용했다.
    2. (Bounding box 영역 이외는 zero) crop이 된 이후를 input (YOLACT’s cropped mask prediction (before thresholding))으로 받은 FCN 을 통과해서, 마지막에 MaskIOU를 추론하는 모듈을 추가했다.
    3. 전체 모듈의 Architecture는 위와 같다. a 6-layer FCN with ReLU + final global pooling layer.
    4. 이 과정을 통해서 our ResNet-101 model에서, fps from 34.4 to 33 이 된다.
    5. 만약에 그냥 Mask Scoring RCNN의 방법을 그대로 사용하면, fps from 34.4 to 17.5이 된다.
    6. 여기선는 ROI align과 fc layers를 사용하지 않았기 때문에, efficient and fast 하다고 한다.
  • Deformable Convolution with Intervals
    1. Deformable Convolutional Networks : (1) 블로그 설명, (2) 동영상 설명
    2. Deformable Convolution Networks (DCNs)는 free-form sampling을 수행하며, 정말 필요한 Feature에만 집중해 sampling이 수행된다.
    3. a speed overhead of 8 ms 만으로 +1.8 mask mAP 성능향상을 이뤘다. 성능 향상의 이유를 추론해보면 다음과 같다.
      1. DCN는 different scales, rotations, and aspect ratios 의 객체를 다루는데 강할 만큼, 정말 Instance가 있는 부분을 sampling하는 능력을 가지고 있다.
      2. 2 stage detector는 RPN과 같은 proposal network가 없다. (does not have a re-sampling process = ROI pooling?) 따라서 처음부터 sampling을 잘하는게 필요한다. DCN이 이것을 도와준다.
    4. 하지만 이 DCN 과정 자체가 parameter를 더 많이 사용해야하기 때문에, DCN을 전체 신경망에 사용하기에는 속도 감소의 단점이 있다. 따라서 일정 layer 부분에만 DCN을 사용해야했고, 어느 부분에 사용하는게 가장 적절한 성능향상과 속도감소를 가져와 주었는지 아래와 같이 테스트 해보았다.
    5. 아래의 Table 7 을 참조해보자.
      • just DCN : 30 layers with deformable convolutions when using ResNet-101
      • speed up을 위해서 몇가지 실험을 해보았다. 여기서 가장 좋은 Trade-off 결과를 가져다 준 모델은 w/ DCN (interval=3) 이었다.
      • 아래의 각각의 method가 무엇인지 글로 설명이 되어 있지만, 정확한 이해는 힘들었다. 코드를 봐야한다. (내용 복붙 : (1) in the last 10 ResNet blocks, (2) in the last 13 ResNet blocks, (3) in the last 3 ResNet stages with an interval of 3 (i.e., skipping two ResNet blocks in between; total 11 deformable layers), and (4) in the last 3 ResNet stages with an interval of 4 (total 8 deformable layers). )
  • Optimized Prediction Head
    • 아래의 Table 3 참조.
    • 아무래도 YOLACT은 anchor-based 이다. 따라서 적절한 Anchor를 선택하는 것은 매우 중요했고, 몇가지 실험을 통해서 성능향상을 가장 많이 가져다 준 방법을 찾아 보았다.
    • 비율을 다르게 하거나 vs Anchor scale 을 다르게 하거나. 둘 다 실험해 본 결과, 후자가 더 좋은 성능 향상을 가져다 주었다고 한다.

image-20210309170334063

【In-Segmen】CenterMask - Real-Time Anchor-Free Instance Segmentation

CenterMask

1. Conclusion, Abstract, Introduction

  1. Real-time anchor-free one-stage
  2. VoVNetV2 backbone : (1) residual connection (2) effective Squeeze-Excitation (eSE, Squeeze and Excitation Block (M2Det, MobileNetV3, EfficientDet 참조))
  3. Spatial attention guided mask (=SAG-Mask) : Segmentation Mask를 예측한다. spatial attention을 사용함으로써 집중해야할 Informative Pixel에 집중하고, Noise를 Suppress한다.
  4. ResNet-101-FPN backbone / 35fps on Titan Xp
  5. (PS) Introduction은 읽을 필요 없는 것 같고, Relative Work는 아에 없다. Introduction에 Relative Work의 내용들이 가득해서 그런 것 같다.

2. CenterMask architecture

image-20210308210529882

  • 논문의 그림에서 P7~P3의 그림이 이상해서 내가 다시 표시했다. 내가 수정한게 더 맞는 것 같다.

2.3. Adaptive RoI Assignment Function

  1. 위 필기 갈색5번을 참조하면 ROI는 구했고, 그 ROI를 가져올 때, 어떤 Feature Level을 사용해야하는가?

    image-20210308212753869

  2. 위 Equation1 은 Mask rcnn에서 사용하던 방식이다. 하지만 이것을 그대로 사용하기에는 문제가 있다. 첫째로, 이 방식은 feature levels of P2 (stride of 2^2) to P5를 사용하는 2 stage detector에 더 적합하다. 우리는, P3 (2^3) to P7 (2^7)를 사용하는 one stage detector를 개발해야한다.

  3. 게다가 위의 224는 ImageNet Image size이다. 이것은 굉장히 Heuristic한 설정이고, 이와 같은 설정을 유지해서 계산을 해보면, 특정 wh에 따라 선택된 k 값은 상대적으로 작은 값이다. 다시 말해, 좀 더 큰 resolution의 Feature map에서 ROI feature를 가져와야 하는데, 작은 Resolution의 Feature map에서 ROI feature를 가져오므로 작은 객체 탐지를 어렵게 만든다.

  4. 따라서 우리는 Equation2를 새로운 Feature Level 설정 방법으로 사용한다. 몇가지 경우와 수를 고려해보면, Image area의 절반이상의 ROI area를 가지는 객체는 무조건 P7에서 Feature를 가져오고, 상대적으로 Equation 1보다 작은 k값의, P_k에서 feature를 가져와 small object detection에 도움을 준다.

  5. ablation study를 통해서 k_max to P5 and k_min to P3 를 사용하는게 가장 좋은 결과를 가져다 주었다고 한다.


2.4. Spatial Attention-Guided Mask

  1. 최근 attention methods은 Detector가 중요한 Feature에 집중하는데 도움을 준다. ‘what’을 강조해주는 channel attention과 ‘where’을 강조해주는 spaital attention이 있다. CBAM이 위의 2가지 방법을 적절히 잘 섞은 방법이다.
  2. 이 논문에서는 spaital attention를 사용해서, Mask head가 정말 의미있는 Pixel에 집중하고, 무의미한 Pixel은 억압되도록 만들었다.
  3. 그것이 SAG-Mask (a spatial attention-guided mask) 부분이고 위의 Architecture 그림에 잘 그려져 있다.
    image-20210308214326422

2.5. VoVNetV2 backbone

  1. VoVNet는 ‘computation + energy’ efficient backbone network 이다. 이 네트워크는 효율적으로 다양한 feature representation(map)들을 보존한다. VoVNetV1 또한 이 논문 저자가 발표한 논문의 방법이다.
  2. 이번 VoVNetV2에서는 특별하게 effective SE 모듈을 추가했다. effective SE 모듈은 기존의 SE 이 2번의 fc layer를 통과시키면서, dimension reduction 과정을 거치고 이 과정에서 정보의 손실이 생긴다고 주장한다. 따라서 1번의 fc layer만 통과시키는 effective SE 모듈를 주장한다.
  3. Architecture의 모습은 아래와 같다.
    image-20210308214521758

2.6. Implementation details

  1. mask scoring [15] 를 사용했다. 예측한 mask의 quality (e.g., mask IoU)를 고려하여, classification score를 재조정하는 방법이다. (이 방법을 어떻게 사용했는지 구체적인 방법에 대해서는 안 나와 있다. mask scoring [15] 논문을 봤다는 전제를 하는 것 같으므로 나중에 mask scoring [15] 논문을 꼭 읽어봐야겠다.)
  2. CenterMask-Lite : backbone, box head, and mask head 에 대해서, down-sizing을 하여 성능은 조금 낮아져도, 속도가 빨라지도록 만들었다. 구체적으로 어떻게 down-sizing 했는지는 논문에 간략히 적혀있으니 필요하면 참조.
  3. Training :
    • FCOS에서 나오는 100개의 박스를 SAG-mask branch에 fed한다.
    • Mask R-CNN과 같은 mask-target을 사용했다. 이 mask-target은 Mask-IOU를 이용해 정의 된다.
    • Loss_total = L_cls + L_center + L_box + L_mask
    • input image는 가로 세로 중 짧은 쪽이 800이 되도록 resize된다. 긴쪽은 1333이 되거나 1333보다 작은 pixel크기가 된다.
    • 90K iterations (∼12 epoch) with a mini-batch of 16 images
    • SGD, weight decay of 0.0001 and a momentum of 0.9
    • initial learning rate 0.01 which is decreased by a factor of 10 at 60K and 80K iterations, respectively
    • All backbone models 은 ImageNet pre-trained weights 를 사용했다.
  4. Inference :
    • FCOS에서 나오는 50개의 박스를 SAG-mask branch에 fed한다.
    • CenterMask/CenterMask-Lite use a single scale of 800/600 pixels for the shorter side

3. Results

image-20210308220227847

【Detection】FCOS - Fully Convolutional One-Stage Object Detection

FCOS

1. Conclusion, Abstract, Introduction

  1. anchor boxes와 관련된 hyper-parameter와 학습 중 Matching 및 IOU 계산에 대한 연산들을 모두 제거했다. Hyper-parametor를 제거함으로써 heuristics한 many trick들을 모두 없앴다. 그리고 Anchor와의 관계 연산을 하지 않으므로 Faster Training이 가능하다.
  2. Sementic Segmentation 처럼. per-pixel prediction fashion 을 수행한다.
  3. 우리의 FCOS를 two-stage Detector에서 RPN으로 사용해도 좋은 결과를 가져다 준다. RPN 또한 Anchor-based 인 것을 기억하자.
  4. NMS 를 사용한 후처리 과정은 필요하다. FCOS with ResNeXt-64x4d-101에서 SOTA 성능 44.7% AP를 획득했다. 우리 모델은 simple and fast 하다!
  5. 원래 Class confidence만 예측하는 head만 있으면, low-quality predicted bounding boxes 들이 너무 많이 생긴다. 그래서 우리는 해당 1x1 pixel 점이 객체의 center와 얼마나 떨어져있냐를 수치로 가지고 있는 center-ness 값이 추출되도록 head를 추가했다.

2. Our Approach

image-20210306155338457

  • Anchor라는 개념없이, 각 Pyramid Feature Level의 한 1x1 픽셀 공간이 가지면 괜찮을 Class와, 가장 적절히 일치하는 Instance에 대한 the box offset (t, b, r, l) 을 검출한다.
  • 헷갈리면, 이전 포스트 FSAF Architecture에서 Anchor based 부분까지 완전히 제거해 버렸다고 생각하면 좋다.

3.1 Fully Convolutional One-Stage Object Detector

  • 우선 전체 architecture와 필기 꼭 참고하기. 그리고 아래의 수식들 하나하나 읽기.

image-20210306160218840


3.2. Multi-level Prediction with FPN for FCOS

  • FPN을 사용해서 Recall을 증가시키고, Overlapped bounding box의 ambiguity (다중 객체가 겹치는 해당 Feature map pixel에서 어떤 BB를 예측할 것인가?) 를 해결했다.
  • FPN으로 적용되는 stride값은 P3, P4, P5, P6 and P7 에 대해서, 각각 8, 16, 32, 64 and 128 이다. 이 값은 위의 S 로 동작한다.
  • Anchor-based detector에서 각각의 P_l 은 자신만의 Anchor size를 가짐으로써, 각 Level에서 검출하는 Instance의 크기가 서로 다른다. 여기서도 이런 개념을 추가했다. the range of bounding box regression 를 할당했다. 그 과정은 이와 같다.
    • (1) 우선 모든 Feature level에 t* ( l* , t* , r* , b* ) 를 연산해놓는다. (Image에 대응하는 (l, t, r, b)를 S로 나눠주면 된다.)
    • (2) 만약 max( l* , t* , r* , b* ) > m_i or max( l* , t* , r* , b* )< m_(i−1) 즉 일정 범위를 벗어나면 negative sample이라고 파악하고, bounding box regression 학습에 사용하지 않는다.
    • (3) 여기서 m2, m3, m4, m5, m6 and m7 는 각각 0, 64, 128, 256, 512 and ∞ 으로 설정해 사용했다.
    • 이 과정을 통해서, Inference을 하는 동안에는 각각의 Pyramid Feature level들은 자신이 예측해야하는 적절한 크기의 Instance를 우선적으로 검출한다.
  • (필기참조) 하나의 Feature level Picel이 1개 이상의 GT BB를 할당하고 있다면, 단순하게 더 작은 area를 가진 GT BB를 Ground True로 설정해 예측하도록 한다.
  • 그리고 단순하게 Shared Heads Between Feature Levels 를 사용한다. 즉 위의 보라색 head는 모두 파라메터를 공유한다. parameter-efficient (파라메터가 효율적으로 적은) 모델을 만들고 성능도 높혀준다. 하지만 이런 작업이 각 Level이 찾으려고 하는 Instance의 크기가 다른 것을 고려할 때 그리 합리적인 방법은 아닐 수 있습니다.
  • (필기참조) 그래서 우리는 그냥 exp(x)를 사용하는 것 대신에, exp(s_i * x) 를 사용했다. (s_i 는 trainable scalar) 알아서 각 Level에 필요한 s_i 값을 주어줄 것이라고 예측했다.

3.3. Center-ness for FCOS

  • (위 그림 참조) 그냥 Class Score만을 사용해서 NMS를 적용하니, a lot of low-quality predicted bounding boxes 가 추출되는 것을 확인할 수 있었다. 그래서 Center-ness를 예측하는 branch를 새롭게 만들었다.
  • 그 branch에서는 normalized distance를 의미하는“center-ness”를 예측한다.
    image-20210307163927443
  • When testing, 위의 Architecture 그림 처럼, center-ness와 classification score를 곱해서 최종 Confidence로 사용한다. 그리고 NMS를 적용한다.
  • the center-ness를 사용하는 것 대신에, central portion (FSAF에서 Efficient Region (GT instance BB의 0.2 공간))을 사용하는 방법도 있다. 하지만 이것 조차 extra hyper-parameter를 사용하는 방법이라는 것에 명심해야한다.
  • FCOS_PLUS 에서는 위의 2가지 방법을 융합해서 성능을 높혔다고 한다.

image-20210308091956833


4. Experiments

  • Training Details
    • ResNet-50
    • the same hyper-parameters with RetinaNet
    • SGD, Weight decay and momentum are set as 0.0001 and 0.9
    • initial learning rate being 0.01, batch of 16 images, 10 at iteration 60K and 80K.
    • the input images are resized being 800.
  • Inference Details
    • the same post-processing hyperparameters of RetinaNe
  • 4.1. Ablation Study
    1. (FPN) Multi-level Prediction 을 사용함으로써, ‘Best Possible Recalls 획득’ 그리고 ‘Ambiguous Samples 제거’ 를 할 수 있다.
      image-20210308092142003
    2. Best Possible Recalls 은 다음과 같이 정의할 수 있다. 위의 파란 필기도 참조. the ratio of the number of ground-truth boxes, a detector can recall at the most, divided by all ground-truth boxes.
    3. Ambiguous Samples
      • 특히 위의 사진과 같이, 객체가 overlapping 될때 Ambiguous sampling (보통 FPN에서는 ‘다중’ 예측을 통한 후 NMS를 한다. 이때 ‘특정 한번’의 예측을 할 때, 보통 ‘특정 위치’에서 1개의 객체인식만 하면 되는데, 객체가 겹치는 경우에는, 이 ‘특정 위치’에서 어떤 객체를 우선적으로 예측해야하는지 애매모호한 경우가 발생한다. 이를 Ambiguous sampling 이라고 말하는 것 같다. )이 발생한다.
      • 논문에는 정확한 정의와 계산 수식을 제시하고 있지 않다. 그저, 논문에서 말하는 몇가지 내용에 대해서 아래에 정리한다. 아래의 내용 말고 추가적인 내용은 없다. 왜 있는지? 무슨 소리를 하고 싶은건지 이해가 힘들다.
      • Table2를 보면, FPN을 사용함으로써 Ambiguous sampling이 줄어든 것을 확인할 수 있다. 이 이유는 다음과 같다. 객체가 overlapping 하게 되는 보통의 경우에는 두 객체의 크기가 상대적으로 다르다. 따라서 FPN의 다른 Level에서 객체가 각각 검출되면 되기 때문에, Ambiguous sampling 의 발생 빈도를 상당히 줄일 수 있다.
      • Moreover, 저자가 말하기로 같은 Class의 객체가 겹치면, 상대적으로 overlapping으로 인한 Ambiguous sampling은 적다고 한다.(어차피 비슷한 Feature map이 겹치므로) 반대로 겹치는 객체의 Class가 다르면, overlapping으로 인한 Ambiguous sampling이 크게 발생한다. (다른 Featere map이 서로 엃겨 섞이게 되므로. classifier는 당항할 것이다.)
  • 4.2. With or Without Center-ness / FCOS vs. Anchor-based Detectors / Comparison with State-of-the-art Detectors
    image-20210308094302495


FCOS code

  • Github link : [https://github.com/tianzhi0549/FCOS]

  • 공부순서
    1. Readmd.md 읽기
    2. 패키지 전체 흐름 파악하기
    3. 핵심 코드 살펴보기
    4. demo/fcos_demo.py
    5. python tools/test_net.py
    6. train : python -m torch.distributed.launch
  • 위의 5번까지 살짝 1시간 정도 본 결과 느낀점

    1. 아래의 기반 코드를 완전히 뜯어 부셔버리고, fcos코드를 보면 좋을 듯 하다. 하지만 시간이 없다면, 핵심 코드만 봐도 좋겠다. 우선 지금은 공부할 때가 아니다. 공부할 때 라는 생각이 들 때, 바로 공부해보자. 아래의 내용들을 참고하면 좋은 공부의 시작이 될 수 있다.
    2. 기반 코드 : https://github.com/facebookresearch/maskrcnn-benchmark
    3. 논문 내용 이해에 도움을 주는 핵심 코드 : https://github.com/tianzhi0549/FCOS/blob/master/fcos_core/modeling/rpn/inference.py
    4. 내가 만약 신경망을 처음부터 구성한다면, 심플하게 만들기 위해 도움 받을 수 있을 코드 : https://github.com/yhenon/pytorch-retinanet/tree/master/retinanet
    5. Test를 하던 Training을 하던 이것을 시작으로 Model을 만들었다.
      image-20210308160135320
      image-20210308160207919
  • 그리고 전체적으로 살펴 본 결과, 코드 제작자가 직접 손수 손본 곳은 여기가 전부 인듯 하다. (처음에는 못 찾았는데, 검색으로 centerness를 검색함으로써 찾을 수 있었다.)
    image-20210308160926494

  • 특히 /modeling/rpn/fcos/fcos.py에서 아래의 코드를 유심히 보자.

    class FCOSModule(torch.nn.Module):
        """
        Module for FCOS computation. Takes feature maps from the backbone and
        FCOS outputs and losses. Only Test on FPN now.
        """
      
        def __init__(self, cfg, in_channels):
            # /modeling/rpn/fcos/fcos.py 에 정의되어 있다. 
            head = FCOSHead(cfg, in_channels)
    		# /modeling/rpn/fcos/inference.py 에 정의되어 있다. 이 객체는 딱 Test할 때만 사용하나 보다.
            box_selector_test = make_fcos_postprocessor(cfg)
    

【In-Segmen】YOLACT - Real-time Instance Segmentation w/ my advice

  • 논문 : YOLACT
  • 분류 : Real-time Instance Segmentation
  • 저자 : Daniel Bolya Chong Zhou Fanyi Xiao Yong Jae Lee
  • 읽는 배경 : the devil boundary 의 기반이 되는 논문
  • 느낀점 :
    • 읽으면 좋을 것 같은 논문
      • FCIS[24, 2017, Fully convolutional instance-aware semantic segmentation]
    • 확실히 창의적이고 심박하다. 이러한 설계를 통해서도 원하는 결과가 추출된다는게 매우 신기하다.
    • 하지만 Transformer 도 그렇고, 아래의 ProtoNet과 Mask head의 결과를 Linear combination하는 것도 그렇고, 이런 생각이 든다.
    • “사람들은 대충 이렇게 설계하면 나의 직관적 의도대로 동작할 거 같은데?? 라는 생각으로 설계한 모델을 학습시킨다. 어찌되든 딥러닝 특성상 어떻게든 그럴듯하게 학습이 된다. 그렇다면… 나도 그냥 일반적인 설계말고, 좀더 심박하고 창의적이고 신기한 모양을 가진 Network를 설계해보면 어떨까? 마치 새로운 미로 문제를 만들어 보듯이. 심박하고 창의적이고 뒤죽박죽하게 하지만 직관적으로 생각해보면 심플하게. 하지만 이런 도전은 무조건 실패를 가져다 준다. 따라서 정말 다양한 아이디어로 실험해봐야한다. 다양한 아이디어 중 하나는 대박나지 않겠는가?”
  • 목차
    1. Paper Review
    2. Code Review

YOLACT

1,2. Abstract, Introduction

  1. fully-convolutional model for realtime instance segmentation / 29.8 mAP on MS COCO / 33.5 fps on a single Titan Xp / after training on only one GPU
  2. two parallel subtasks 이 이뤄진다.
    1. (global, holistic, non-local) generating a set of prototype masks
    2. predicting per-instance mask coefficients
  3. Fast NMS 를 적용하여 12ms faster 성능을 얻었다.
  4. Mask-RCNN 은, 객체에 따른 mask 데이터를 뽑아 내기 위해서 feature localization step (=re-pooling, ROI-Pooing, ROI-Align) 과 같은 작업이 필요했다. Instance 정보를 뽑아내는 작업이 다 완료되어야 Mask 정보를 뽑을 수 있으므로, 빠른 성능은 얻기 어렵다.
  5. FCIS[24, 2017, Fully convolutional instance-aware semantic segmentation] 논문이 One-stage methods 라고 거론되고 있지만, localization 이후에 후처리 작업이 너무 오래걸려서, 실시간성을 확보할 정도로 속도가 빠르지 않았다.
  6. 이 모델의 장점은 “빠르다. 비교적 좋은 성능이다.” 이다. ResNet101을 사용해서 30fps가 나오고, any loss of quality from repooling 가 없기 때문에 이미지 전체를 보고 좋은 instance mask 결과를 추출 할 수 있다.
  7. Related Work
    • (복붙) One-stage instance segmentation methods generate position sensitive maps that are assembled into final masks with position-sensitive pooling [6, 24] or combine semantic segmentation logits and direction prediction logits [4]. -> slow
    • (복붙 - top-down 방식의 instance segmentation) some methods first perform semantic segmentation followed by boundary detection [22], pixel clustering [3, 25], or learn an embedding to form instance masks [32, 17, 9, 13]
    • Real-time Instance Segmentation : Straight to Shapes [21] and Box2Pix [42] 와 같은 모델이 있었지만, 성능이 너무 안 좋았다.


3. YOLACT

image-20210305230246553

  1. two parallel subtasks 이 이뤄진다.
    1. first branch uses an FCN -> prototype masks - pixel 끼리는 서로서로의 소통과 관계 파악이 필요한데, global gerneralizing 을 통해 성취할 수 있다.
    2. predict a vector of “mask coefficients” , for each anchor , that encode an instance’s representation , in the prototype space.
  2. 그 이후 NMS, Linearly combining이 이뤄진다.
  3. 참고로 위의 Assembly step에서 computational overhead가 일어날 수 있는데, 아래의 수식처럼, 한번의 행렬곱으로 GPU의 장점을 살려 빠른 계산을 할 수 있게 해놨다.

image-20210305230738580


3.1 Prototype Generation (FCN)

  1. 위의 Figure 3 참조.
  2. 최종적으로 k 개의 prototype masks를 만들거고, k channels 에서 하나하나의 채널이, 하나의 prototype mask가 된다.
  3. 여기서 특이한 점은, 위 이미지에서, 138x138xk feature map에 필요한 GT는 없다. 그냥 the final mask loss after assembly 에 의해서 나오는 Loss에 의해서 supervision 될 뿐이다.
  4. 더 큰 Feature map 을 사용해서 FCN을 할 수록 작은 객체 탐지에 좋았다. 그래서 FPN의 P3 만을 사용했다.
  5. Upsample을 하는데, 원본 input 이미지 크기의 4분의 1 크기가 될 때까지 upsampling 시켜준다고 한다.
  6. 마지막으로 그림처럼, 1x1을 통과해서 channel을 k로 맞춰주고, relu를 통과시켜준다. 여기서 relu를 사용할지 안할지 고민을 했다고 한다. 왜냐면 여기서 나오는 pixel값이 +,- 양방향에서 무한하다면 더 좋은 confident pixel about obvious background 이 라고 여길 수 있기 때문이다. 하지만 Relu를 사용했다고 한다.

3.2. Mask Coefficients

  • 위의 Figure 4 참조.
  • Typical anchor-based object detectors 모델을 기반으로 한다.
  • per anchor에 따라서 4 + c + k channel을 생성한다.
  • tanh 를 수행한다. 그래야 linear combination을 적절히 수행할 수 있다고 한다.
  • (논문에 fc-mask라는 말이 있다. 그리고 Mask-head에서는 fc layer (fully connected layer)를 썼다는 듯이 이야기하고 있는데, Architecture 그림에서도, 코드에서도 Mask_branch에서 nn.linear를 만든 흔적도 없다. 내가 논문 해석을 못하는건가? 나중에 더 알아보자.) )

3.3. Mask Assembly

  • 위의 그림 중 첫번째 수식 참조.
  • sigmoid nonlinearity를 이용했고, single matrix multiplication을 사용하면 되므로 빠르게 처리할 수 있도록 했다.
  • linear combination 말고도 더 복잡한 방법을 사용할 수 있었겠지만, 속도와 단순성을 확보하기 위해서 linear combination 을 사용했다.
  • Loss : 위의 그림 중 두번째 수식 참조
    • 여기서 M은 assembled masks 이고, M_gt는 ground truth masks Mgt 이다.
    • BCE loss는 pytorch document, 블로그 에서 참조.
  • Cropping Masks
    • 위 그림에 적어 놓은 것 같이, 학습 동안에는 GT BB를 사용해서 crop 하고 (+L_mask에 GT BB의 크기(넓이)로 값을 나눠 준다. (큰 객체에 큰 loss가 커지는 문제를 막기 위해서)), Inference 하는 동안에는 Predicted BB를 사용해서 Crop한다.
    • 다음 설명에도 나오겠지만, 사실 너무 작지 않은, large+midium size의 객체는 crop을 하지 않고도 thresholding 만으로 적절한 mask 결과가 나온다고 한다.

3.4. Emergent Behavior

  • 솔직히 이 반 페이지 이해가 잘 안된다. 그래도 내가 최대한 이해한 내용을 바탕으로 정리하면 다음과 같다.
    • 우선 알아야 할 용어 : translation invariant (병진 대칭) 에 대한 정리
      1. translation invariant이란, translation invariance란 input의 위치가 달라져도 output이 동일한 값을 갖는것을 말한다. 그 반대를 논문에서는 translation equivariance이라고 표현하는 것 같다..
      2. 그냥 conv연산은 translation equivariance 하다. (input value의 위치가 변함에 따라 feature map value도 변한다) Max pooling과 Softmax는 translation invariant 하다. 전체적으로 생각하면 Classification관점에서 CNN연산은 translation invariance 하다고 할 수 있다.
    • FCN은 translation invariant 하기 때문에, instance의 특정 위치를 파악하려면 ROI-pooing이나 ROI-Align과 같은 translation variance 한 작업이 필요하다. 하지만 우리가 하는 translation variance 작업은 단순히 crop을 하는 것 뿐이다.
    • 하지만 우리의 Network는 큰 객체, 중간 크기의 객체는 crop을 하지 않더라도, Tresholding 만으로 적절한 mask를 뽑을 수 있었다. 따라서 Crop을 translation variance라고 말하기에는 무리가 있다.
    • YOLACT는 FCN을 통해서 각각의 Instance에 대한 Localization을 찾는다. 어떻게 이것이 가능할까?
    • 첫번째는 ResNet에서 충분한 translation variance 이 이뤄진다. corner, edge 등등을 이미 찾아내고, localization을 할 수 있을 정보를 FCN에게 쥐어 준다.
    • 두번째는 k = 32개의 prototypes 이, Mask head에서 나온 정보를 통해서 Linear combination을 하기 때문이다. 이 과정을 통해서 different activations in its prototypes 들은 서로서로 Comunication (Multi haed attentino module은 어떨까?) 을 하여, 최종적으로 Instance Localization을 뽑아낼 수 있는 것이라고 한다.
  • 아래의 그림은 Prototype activation map이 어떻게 동작하는지 시각화를 해 놓은 것이다. 이해가 어렵지 않으니 읽고 확인하자.
    image-20210306114716335

4. Backbone Detector

  1. good features를 뽑기 위한, backbone은 RetinaNet과 비슷한(동일한) 것을 사용했다.
  2. YOLACT Detector
    • 무조건 550 × 550 이미지가 들어간다. 일정한 fps가 나오게 하기 위해서, aspect ratio 이미지 비율은 보존하지 않았다.
    • 3 anchors [1, 1/2, 2]. P3부터 feature map pixel size를 [24, 48, 96, 192, 384]로 사용했다.
    • [smooth-L1] loss for box regressors
    • [softmax cross entropy] with c positive labels + 1 background label
    • 3:1 neg:pos ratio의 Negative mining 기법 사용.
    • Focal Loss 사용하지 않았다.

5. Other Improvements

  • Fast NMS
    1. 원래 NMS는 (이전 Post의 자료를 찾아봐도 된다) confidence score로 sort를 한 후, 높은 것과 일정 이상 IOU를 가지는 Predicted Box를 제거한다. 하지만 이 작업이 수행 속도에 방해가 된다. 그래서 이것을 수정했다.
    2. Fast NMS의 직관적인 이해는 다음과 같다. (논문 부분 그대로 해석하자면..) Predicted Box를 최종 결과로 가져갈지 혹은 버려 버릴지를 정하는 작업이 Parallel하게 수행된다. 단순하게 already-removed detections to suppress other detections (한번 아니라고 제거된 박스는 다시는 고려하지 않는다. 라고 이해하면 되려나?) 라고 표현할 수 있다. (아래의 공식으로 이게 충분히 이해되지는 않는다. 쩃든 이런거 있다 정도만 알아두자.)
    3. Fast NMS 수행방법은 다음과 같다. 첫째 class 마다 n개의 predicted box만을 선별한다. 총 c x n 개. 박스 서로에 대한 IOU를 계산한다. 행렬곱으로 처리하면 되므로 순식간이다. 그러면 c x n x n feature map이 생성된다.
    4. 그 후 대각, 하삼각행렬의 값을 0으로 바꿔버리고, column-wise max를 수행한다. 그 후 마지막 thresholding 과정을 거쳐, 최종적으로 살아남은 Predicted Box를 검출해 낸다. 아래의 그림을 보면 이해가 좀 더 쉽다. 하지만 이게 정확히 어떻게 작동되는지는, 예시를 만들어 손으로 직접해보거나, 코드를 한줄한줄 확인하면서 이해할 필요가 있다.
      image-20210306120119514
  • Semantic Segmentation Loss
    1. 전체 AP를 +0.4 를 시켜주었다. 학습과정에만 적용하고 inference에서는 사용하지 않는 방법이라 test time에는 영향이 없다.
    2. P_3 feature map에 1x1 conv를 통과시키고 c channel이 나오게 한다. 그리고 sigmoid function을 거친다. (softmax and c + 1 channel이 아니다)
    3. 이렇게 나온 H x W x C 와, Sementic Segmentation GT를 정답갑으로 하여, Loss를 주어 학습시킨다.
    4. (이 과정을 통해서 P3는 물론 FPN의 Feature map들은 Segmentation 결과를 더 잘 추출 할 수 있는 feature extractor로 변화될 것이다. 그리고 이 P3를 사용해서 FCN을 통과시켜 Prototypes를 찾아낸다.)

6. Results

image-20210306120629006



YOLACT - code

  • 지금 궁금한 코드 내용
    1. Fast NMS
    2. NMS
    3. Semantic Segmentation Loss
    4. Linear combination
    5. Mask Loss
    6. 32개의 Prototpyes 를 생성하는, ProtoNet
  • 나중에 필요할 떄 코드를 참조하자.

    • num_priors : Anchor의 갯수

    • mask_dim : k (prototypes의 갯수)

    • # yolact/yolact.py
      self.bbox_layer = nn.Conv2d(out_channels, self.num_priors * 4,                **cfg.head_layer_params)
      self.conf_layer = nn.Conv2d(out_channels, self.num_priors * self.num_classes, **cfg.head_layer_params)
      self.mask_layer = nn.Conv2d(out_channels, self.num_priors * self.mask_dim,    **cfg.head_layer_params)
                  
      # 코드볼 때, 여기서 src는 self라고 이해하면 된다.        
      bbox = src.bbox_layer(bbox_x).permute(0, 2, 3, 1).contiguous().view(x.size(0), -1, 4)
      conf = src.conf_layer(conf_x).permute(0, 2, 3, 1).contiguous().view(x.size(0), -1, self.num_classes)
      mask = src.mask_layer(mask_x).permute(0, 2, 3, 1).contiguous().view(x.size(0), -1, self.mask_dim)
      

【Transformer】Attention Is All You Need 공부 필기

  • 논문 : Attention Is All You Need
  • 이 논문은 그리 자세하지 않다.
  • 직관적인 이해를 위해서, 이곳 저곳에서 글을 찾아 읽고 공부했다.
  • 과거의 Post(Attention Mechanism Overveiw) 에서 정리한 내용에 추가적으로 공부한 내용이다.
  • ViT (16x16 Vision Transformer ) 논문에서는 Encoder만을 사용했다. 따라서 Multi Head Attention 모듈만 이해하면 됐지만, DETR에서는 Decoder까지 이해하기 때문에 Decoder까지의 완벽한 이해가 필요했다.
  • 참고 자료
    1. 과거의 Post(Attention Mechanism Overveiw)에 적혀있는 Reference
    2. Youtube1 : https://www.youtube.com/watch?v=mxGCEWOxfe8

T3.png



  • 아래 필기 공부 순서 : 맨 아래 그림 -> 보라색 -> 파랑색 -> 대문자 알파벳 매칭 하기

T3.png

T3.png

T3.png



T3.png

T5.png

T4.png

【Transformer+OD】DETR-End-to-End Object Detection with Transformers w/ my advice

  • 논문 : End-to-End Object Detection with Transformers
    필기 완료된 파일은 OneDrive\21.1학기\논문읽기 에 있다.
  • 분류 : Transformer + Object Detection
  • 저자 : Nicolas Carion, Francisco Massa, Gabriel Synnaeve
  • 읽는 배경 : Visoin Transformers 를 사용한 Object Detection
  • 느낀점 :
    • 연산이 좀 더 구체적으로 어떻게 이뤄지는 건지 궁금하면, Deformable DETR 부분의 내용정리를 참고하면 좋다
    • Conclution -> Method -> Introduction -> Abstract 순서로 논문을 공부하자!
    • 실제 공부 순서
      1. Conclusion, Abstract
      2. Introduction : Fig 1 과 Fig 1을 설명하는 논문의 부분. 1문단만 읽음
      3. Introduction : 거의 마지막 부분
      4. Related work : 큰 제목이 의미하는 것이 무엇인지만, 알아봤다.
      5. The DETR model
      6. 나머지
      7. 아직 이해가 안 되는 것 : auxiliary losses
    • 논문이 정말 깔끔하다. 이전의 ViT (16x16 vision transfomer) 논문을 보다가, 이 논문을 보니까 문장도 정말 잘 써놨고 이해도 정말 잘되게 써놨다. 일부러 어렵게 써놓지도 않아서 너무 좋다. 이렇게 아주아주 유명하고 유용한 논문도 이렇게 쉽게 써 놓을 수 있고, 쉽게 이해가 될 수 있는데…. 내가 논문을 읽으면서 “어렵고, 이해가 안되고, 논문 읽기 싫다” 라는 생각이 들때면, 이 DERT 논문을 떠올리자. 논문을 개같이 써놔서 이해가 안되고, 어려운거지, 코드를 보고 실제를 확인하면 정말 별거 없다. 내가 부족해서 어려운거 라고 생각하며 우울해하지말고, “논문을 개같이 써서 어려운거다! 이 논문만 그런거다! 또 다른 논문은 쉽게 이해되고 재미있을 수 있다!” 라고 생각하자. 왜 우울해 해. 모르면 배우면 되지. 생각하지 말고 그냥 하자.
  • 목차 :
    1. Paper Review
    2. Code
      • https://github.com/facebookresearch/detr


End-to-End Object Detection with Transformers

image-20210303203616333


1. Conclusion, Abstract, Introduction

  • 이 논문의 핵심 2가지
    1. Transformers(encoder-decoder architectures)를 기반으로 한, object detection systems.
    2. Direct set prediction (NMS 따위 안쓰고, Class, BB 한방에 예측해버림) : bipartite(Predicted BB and GT) matching을 수행하는, set-based global loss 를 정의해 사용했다.
    3. Fixed small set of learned object queries 를 사용한다 : DERT가 ‘객체와 Global Image context’ 와의 관계를 추론하여, Parallel하게 (N개의 Query에 대해서 N개의 예측 결과를 출력한다. Figure2에서 빨,초,노,파 박스) final predictions을 하게 만든다.
  • 특장점
    1. Powerful : optimized Faster R-CNN 와 유사한 성능 결과를 가진다. (하지만 Small object에 대해서는 성능이 매우 낮다)
    2. straightforward, simple :
      • detection pipeline을 간소화했다. 코드가 단순하다.
      • Task에 필요한 prior knowledge(사전적 지식 = 인간의 지식 = Heuristics Network)을 정확히 Encoding 해야하는, 많은 hand-designed components (= NMS, anchor generation) 를 제거했다.
      • any customized layers (heuristic한 접근법들) 을 사용하지 않았다.
      • 한방에 모든 객체를 예측한다. (Direct set prediction)
    3. flexible : 원래의 DERT 모델에서, simple segmentation head 를 추가함으로써, 쉽게 panoptic segmentation 구현했다.
    4. large objects : self-attention을 활용해서, global information을 이용해서, 큰 객체 아주 예측을 잘한다.
    5. 추가 특징
      • extra-long training schedule 이 필요하다.
      • auxiliary/parallel decoding losses 으로 부터 오는 이익이 있다.
  • 해결해야 할 도전과제들(challenge)
    • small objects

2. Related work

  • 2.1 Set Prediction (한방에 예측 세트를 찾아내는 것 = directly predict sets)
  • 2.2 Transformers and Parallel Decoding
  • 2.3 Object detection
    • Set-based loss
    • Recurrent detectors.

3. The DETR model

3.1 Object detection set prediction loss

  • DERT에서는 Single pass through the decoder를 통해서 N개의 고정된 크기 Predictions을 추출한다. 여기서 N은 평균 이미지 내부의 객체 수 보다 훨씬 크다.
  • (1) optimal bipartite matching
    • image-20210304153546840
    • 위 이미지에서 Hungarian algorithm 노동자와 일이 있을 때, 노동자에게 일을 할당하는 방법을 고르는 알고리즘이란다. (O(n!)의 경우의 수 시간을, O(n^3)으로 바꾸는 방법) 정말 필요하면, [43] 논문을 보면 될 것 같다. (내가 예측한 결과 N개와 GT N개에 대해서 1대1 대칭을 만들어 줄 때, 그 경우의 수는 n! 이다. 100! = 9.332622e+157. 100^3 = 1e+9.)
    • (문제점 발견!) 여기서 1대1 대응을 할 때, 문제가 발생할 수 있는게, 예측한 N개의 결과에서 Bounding box 위치와 Class confident만 조금 다르고 거의 같은 예측을 했다면, 하나만 정답 GT에 대응되고 나머지는 버려진다. 하지만 다르게 생각하면, N개의 예측 결과 중에서 딱 Instance의 갯수만 객체라고 예측하고 나머지는 no object라고 예측하도록 만드는 것 이기도 하다.
    • 위 이미지, 맨 아래의 수식처럼, P_i (c_i) 즉 just probabilities 값을 사용한게 아니라 log-probabilities 값을 사용했다. 경험적으로 더 좋은 성능일 보여서 log-probabilities를 최종 Loss 수식으로 정했다.
    • Class imbalance를 해결하기 위해서, no object라고 나오는 결과들의 log-probabilities는 10배 감소시켰다.
  • (2) object-specific (bounding box) losses = Bounding box loss
    • L1을 사용하면, relative scaling of the loss 문제점이 발생한다. : 만약 각각 2개의 GT BB와 Predicted BB가 있다고 하나. 하나는 박스가 Large하고 하나는 Small 하다. 만약 L1 loss를 사용하면, 2개의 BB pair에 따른 IOU가 비슷하다고 하더라도, Large Box에 대한 Loss가 더 크기 마련이다.
    • 그래서 linear combination of the L1 loss & the generalized IoU loss 를 사용한다.
    • normalization에 대해서는 4개이미지. 400개의 prediction. 의 Total loss를 400으로 나눠서 사용했다는 건가? 이건 코드를 봐야겠다.
    • image-20210304154317185

3.2 DETR architecture

  • surprisingly simple
    • transformer architecture implementation with just a few hundred lines (코드 몇줄에 네트워크 완성 가능)
    • Inference code for DETR can be implemented in less than 50 lines (코드 몇줄에 Inference 가능)
  • Transformer encoder.
    • transformer architecture는 permutation-invariant 치환불변 하기 때문에(순서에 대한 정보가 없이 Input이 들어가기 때문에), fixed positional encoding을 추가해 준다.
  • Transformer decoder.
    • 그림의 Encoder 부분에는 x N이라고 적혀있다. 이게 누적적으로 이뤄지는게 아니라, 이미지의 인풋이 계속들어가며 독립적으로 N개의 dxWH feature를 만들어 내고, 각각의 dxWH가 Decoder에 들어가는 건가? 코드를 보면서 확인해야 할 듯하다. 코드를 보니, 누적되어 결과가 나온다. 예를 들어서 Feature map input이 dxHW이면, Encoder를 계속 반복해서 최종 Encoding 값으로 (차원은 모르겠고) N개가 나온다. 그리고 이게 Decoder로 들어가서 (NLP는 Sequencail하게 결과값이 Decoder의 맨아래 outpus로 들어가지만 여기서는 그런거 없고) 한방에 N개의 Prediction 결과가 나온다.
    • (youtube) Object query : N 명의 사람들 각각이, 자기가 하고 싶은 질문은 한다. 고 상상하라. 예를 들어서 첫번째 query가 묻는다. ‘헤이 이미지! 아래 왼쪽에 있는 객체는 뭐야?’ 이런한 질문을 N번 받고, 그 결과가 N번 출력된다. 그게 Prediction set 이다. 또한 N명의 사람들은 Multi-Head Self-Attention을 통과하면서 서로서로 Communication 한다. 그래서 나오는 최종 질문이 Decoder의 Multi-Head Attention으로 들어간다.
      image-20210304181917273
    • 따라서 아래의 그림을 보면, 하나의 query에서 하나의 결과가 나오는 것을 알 수 있다. 1사람이 물어본 것에 대해서 1가지 답변을 해주니까!
    • 위에 Query 이미지 figure 7 참조 (Decoder output slot analysis) : 각각의 query는 자신만의 질문 ‘특별함’을 가진다. 각각 다른 box size와 box center position 에 집중하는 것을 확인할 수 있다.
  • Prediction feed-forward networks (FFNs).
    • 3-layer perceptron with ReLU activation function
    • ∅ is used to represent that no object 이것은 다른 OD 모델에서 the “background” class라고 예측하는 것과 비슷하다.
  • Auxiliary decoding losses.
    • use auxiliary losses [1] in decoder during training. (?)
    • 아래의 필기에서, 핫핑크 영어단어는 코드에 있는 변수이름을 그대로 적어놓은 것이다.

T6


4. Experiments

image-20210304211644160

  • DERT = ResNet50 을 backbone으로 가짐. R101 = ResNet101. DC5 = 마지막 Feature map의 Resolution을 높혀서 Small object에서도 강한 성능을 보이게 만들기 위해서, dilation 을 마지막 Layer에 추가하고( (dilated C5 stage)), 초반 conv에 stride를 적용하지 않는다.

4.2 Ablations

  • ResNet-50-based DETR model 에 대해서 최종적으로 6 encoder, 6 decoder layers and width 256를 골랐다.
  • Number of encoder layers
    1. 위의 Table2 이미지 보기. Encoder의 사용 갯수를 다르게 해봄으로써, “global image level self-attention”이 얼마나 중요한지 확인할 수 있었다.
    2. encoder 과정에서 global scene reasoning (전체 장면 추론)이 이뤄지고, objects들끼리 disentangling (서로 풀림) 이 이뤄진다고 추론했다.
    3. 아래 이미지는, 마지막 encoder layer에서 출력되는 attention maps을 시각화한 것이다. (아래 이미지를 어떤 방식으로 시각홰 했는지 모르겠다.)
      image-20210304224435901
  • Number of decoder layers
    1. 6개의 decoder layer 각각을 한 후에 auxiliary losses (?) 를 수행했다. (위에 설명 및 논문 참조)
    2. 위의 Table4 이미지 보기. Decoder를 통해서 Encoding 결과와 Object query간의 소통(communication)이 이뤄지고, cross-correlations를 서로서로 파악해가며, 성능이 좋아진다.
    3. NMS를 사용하면, 초반에는 중복 예측 중 좋은 예측을 골라주므로 성능이 좋아지지만, Decoder layer(Depth)가 증가하면 NMS에 의한 성능 증가가 작아지는 것을 확인했다. 마지막에는 NMS가 성능을 더 낮추는 일이 발생해서 NMS를 쓰지 않는 것으로 결정했다.
    4. Decoder에서도 어떻게 attention이 이뤄지는지 시각화를 해 놓았다. 객체의 머리 팔다리 사지(extremities) 에 집중하는 것을 확인할 수 있다.
      image-20210304225511150
    5. 저자의 추론을 정리하자면, Encoder에서 global attention을 이용해, Instance의 분리가 이뤄지고, decoder에서는 class and object boundaries를 검출하기 위해서, 객체의 팔, 다리, 머리 (extremities)에 집중한다.
  • Importance of FFN
    • tranformers안의 FFN은 attention module에서 1x1 conv를 하는 작업과 비슷하고 생각할 수 있다.
    • tranformers안의 FFN을 제거했을 때, parameters는 25프로가 줄었지만, AP 성능이 2.3% 감소했다. 따라서 tranformers안의 FFN는 중요하다
  • Importance of positional encodings / Loss ablations
    • image-20210305111316215

4.4 DETR for panoptic segmentation

  1. We also add a mask head which predicts a binary mask for each of the predicted boxes.
  2. 아래의 이미지처럼, transformer decoder에서 나오는 ouput과 the output of the encoder 또한 input으로 받는다.
  3. N개의 box embeding 결과로 부터, M개의 attention heatmaps를 생성한다. 여기까지는 small resolution 이다. resolution을 증가시키기 위해서, FPN-like 아래의 architecture를 사용하고, 이것에 대해서는 부록에 추가설명이 있다.
    image-20210305112536771


DETR Code Review


1. DETR_demo.ipynb

  • https://colab.research.google.com/github/facebookresearch/detr/blob/colab/notebooks/detr_demo.ipynb#scrollTo=GJhCp8y0-b-H

  • 아주 짦은 코랩 파일이다. 이해하기도 아주 쉽다. Dert Github 내용을 전혀 사용하지 않았다. nn.Transformer 만을 사용한게 전부이다.

  • ## Network 설정
    class DETRdemo(nn.Module):
        def __init__(self, num_classes, hidden_dim=256, nheads=8,
                     num_encoder_layers=6, num_decoder_layers=6):
            super().__init__()
      
            # create ResNet-50 backbone
            self.backbone = resnet50()
            del self.backbone.fc
      
            # create conversion layer
            self.conv = nn.Conv2d(2048, hidden_dim, 1)
      
            # create a default PyTorch transformer
            self.transformer = nn.Transformer(hidden_dim, nheads, num_encoder_layers, num_decoder_layers)
      
            # prediction heads, one extra class for predicting non-empty slots
            # note that in baseline DETR linear_bbox layer is 3-layer MLP
            self.linear_class = nn.Linear(hidden_dim, num_classes + 1)
            self.linear_bbox = nn.Linear(hidden_dim, 4)
      
            # output positional encodings (object queries)
            self.query_pos = nn.Parameter(torch.rand(100, hidden_dim))
      
            # spatial positional encodings
            # note that in baseline DETR we use sine positional encodings
            self.row_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))
            self.col_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))
              
    	def forward(self, inputs):
            # propagate inputs through ResNet-50 up to avg-pool layer
            x = self.backbone.conv1(inputs)
            x = self.backbone.bn1(x)
            x = self.backbone.relu(x)
            x = self.backbone.maxpool(x)
      
            x = self.backbone.layer1(x)
            x = self.backbone.layer2(x)
            x = self.backbone.layer3(x)
            x = self.backbone.layer4(x)
      
            # convert from 2048 to 256 feature planes for the transformer
            h = self.conv(x)
      
            # construct positional encodings
            H, W = h.shape[-2:]
            pos = torch.cat([
                self.col_embed[:W].unsqueeze(0).repeat(H, 1, 1),
                self.row_embed[:H].unsqueeze(1).repeat(1, W, 1),
            ], dim=-1).flatten(0, 1).unsqueeze(1)
      
            # propagate through the transformer
            h = self.transformer(pos + 0.1 * h.flatten(2).permute(2, 0, 1),
                                 self.query_pos.unsqueeze(1)).transpose(0, 1)
              
            # finally project transformer outputs to class labels and bounding boxes
            return {'pred_logits': self.linear_class(h), 
                    'pred_boxes': self.linear_bbox(h).sigmoid()}
          
    ## 과거 학습된 Parameter 가져옴. 
    detr = DETRdemo(num_classes=91)
    state_dict = torch.hub.load_state_dict_from_url(
        url='https://dl.fbaipublicfiles.com/detr/detr_demo-da2a99e9.pth',
        map_location='cpu', check_hash=True)
    detr.load_state_dict(state_dict)
    detr.eval();
      
    ## 예측 및 결과 추출
    outputs = model(img)
    

2. Evaluation 을 통해서 debugging 수행하기

  1. Dataset 다운받기

    detr/cocodata
      annotations/  # annotation json files
      train2017/    # train images
      val2017/      # val images
    
  2. eval 수행하기

    !python main.py --batch_size 1 --no_aux_loss --eval --resume https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth --coco_path ./cocodata
    
  3. 참고사항

    • engine.py -> def evaluate -> outputs = model(samples)

    • 아래의 코드 설명은, 내가 코드의 흐름을 파악하기 위해서 하나하나 함수와 클래스를 따라가면서, 필심부분만 적어놓은 것이다.

    • import main.py
      test_stats, coco_evaluator = evaluate(model, ...)
           
      import engine.py
      def evaluate(..) :
      	outputs = model(samples)
                                                 
      # ----------------------------------------------------------------------- #
           
      import main.py 
      model, criterion, postprocessors = build_model(args) 
           
      import model.detr.py 
      def build(args):
          transformer = build_transformer(args)
               
           model = DETR(
              backbone,
              transformer,
              num_classes=num_classes,
              num_queries=args.num_queries,
              aux_loss=args.aux_loss,
          )
               
      import models.transformer.py 
      def build_transformer(args): 
          return Transformer(...)
           
      import models.detr.py
      class DETR(nn.Module):
          features, pos = self.backbone(samples)
          src, mask = features[-1].decompose()
               
          hs = self.transformer(self.input_proj(src), mask, self.query_embed.weight, pos[-1])[0]
               
          outputs_class = self.class_embed(hs)
          outputs_coord = self.bbox_embed(hs).sigmoid()
          out = {'pred_logits': outputs_class[-1], 'pred_boxes': outputs_coord[-1]}
          return out
          
      
    • 그래서 아래와 같이 models.detr.py에 class DETR(nn.Module): 를 디버깅 해보았다. (디버깅 중 에러 해결. NestedTensor’ object has no attribute ‘shape)

    • 처음의 sample에는 이미지 1개가 딱 들어가는 shape를 확인할 수 있었다. 하지만 아래의 작업을 수행하기에는, 보고 싶은 변수의 type이 tensor도 아니고, 그래서 shape도 한방에 볼 수 없고, 복잡해서 디버깅은 나중에 VScode에서 진행하기로 마음먹었다.
      image-20210305132022905

【Transformer】An Image is worth 16x16 words - Image Transformers

visionTransformer

(gif 출처 : https://github.com/lucidrains/vit-pytorch)

<Vision Transformer paper>

0. Conclusion, Abstract

  1. Transformers to image recognition 을 수행해보았다.
    • 지금까지 다른 논문들은, Computer vision에서 self-attention을 사용했다. self-attention을 하기 위해서 다른 논문들은 inductive biases into the architecture (전체 Network에 attention module을 따로 설치한 행위를 의미하는 듯) 을 적용했지만, 우리는 그러지 않았다.
    • CNN에 의존하는 방식이 아니라, Pure transformer 방식을 적용했다. classification을 잘 수행하는 것을 확인했고, CNN이 필수적이 아니라는 것도 확인했다.
    • Image sequence of Patches 를 NLP에서 사용하는 Transformer encoder에 넣었다.
    • classification 과제 (ImageNet, CIFAR-100, VTAB, etc.) 에서 SOTA를 달성했고, 다른 모델에 비해 가볍다.
  2. many challenges 남아있다.
    • detection and segmentation 으로 나아가야한다. “End-to-end object detection with transformers” 를 거론하고 있다.
    • self-supervised training methods 에 대한 탐구가 더 이뤄져야한다. - Our initial 실험에는 self-supervised pre-training을 사용해서 성능 향상을 이루었다. 하지만 self-supervised 만으로는 supervised 를 이길 수 없었다.

2. Method

  • original Transformer (Vaswani et al., 2017) 를 최대한 따르려고 노력했다. (그래서 이 논문에서는 original Transformer “Attention is all you need.” 에 나오는 내용은 추가로 설명하지 않는다. 그래서 이 논문이 어렵다. “Attention is all you need.”논문의 내용은 대강 아는데, (논문을 훑어 봐도 이전 Post 내용 이외에 특별한 내용은 없다. 결국에 코드를 봐서 이해하는게 필요하다.) )

  • 논문에 나오는 내용을 아래와 같이 최종 정리 해놓았다. 이해가 안되는 건, 논문에도 안 써 있다. 결국엔 코드를 봐야한다. 코드를 보자.

  • (코드 내용 추가) 아래 이미지 사이즈에서, h = w = image_size 이며, h=w는 p로 나누어 떨어져야한다.

  • (코드 내용 추가) 특히 아래 Position Embeding은 sin을 사용하지 않고, nn.parameter를 사용해 그냥 learnable 변수로 정의했다. Class embeding 또한 nn.parameter를 사용해 그냥 learnable 변수로 정의했다.

  • image-20210302180259210

  • Hybrid Architecture

    1. 위에서는 원본 이미지를 patch로 나눈 후, 1차원 백터로 Embeding을 해서 Transformer에 그대로 넣는 방식를 취했었다.
    2. (PS) Positional embeding 값도 똑같이 1차원이여야한다. 이 값은 original Transformer 논문 처럼 sin함수를 사용해도 되고, learnable parameter를 사용해도 된다. 아래의 코드에서는 learnable parameter를 사용했다.
    3. 하지만! CNN으로 Feature Map을 일부 뽑아내고, 그렇게 뽑아낸 Feature를 Transformer에 넣는 방식은 어떨까? 이 방식을 사용한 것이 Hybrid Architecture 이다.
    4. 아래에 실험결과가 나와있지만, 결과는 학습초반에는 좀 더 좋은 성능을 보이다가, 후반에 많은 데이터로 학습 시키고 나서는 1번의 일반 Transformer를 사용한 것이 더 좋은 성능을 보여주었다.

3. Experiments and Results

  • 읽지는 않겠다.
  • 필요하면 그때 찾아 읽자.
  • Youtube 발표자료 부분에 간략히 정리되어 있기도 하다.


<Vision Transformer - Pytorch code>

  • 원래 논문의 code 는 이 사이트(google-research/vision_transformer) 이다.
  • Pytorch vit 코드 링크 https://github.com/lucidrains/vit-pytorch
  • 하지만 이 코드는 flax, vit_jax 라는 새로은 딥러닝 프레임워크를 사용한다. 이 프레임워크는 tensorflow2.0이 망할 것 같아서 구글이 새로 내놓은 프레임워크 같다. 옛날에 Raddit을 통해서, pytorch vs tensorflow vs falx+vit_jax 에 대해서 검색해 본 결과, 대충 결론은 이랬다. “tensorflow 1.3으로 나왔던 코드들은 tensorflow 2.0으로 다시 만들어 지지않는다. 최근 논문들도 대부분 pytorch를 사용한다. 구글에서 만든 것이 항상 최고는 아니다. falx+vit_jax 를 구글에서 새로 만들어 발표하기는 했지만, 이게 어떻게 될지는 아무도 모른다”
  • 앞으로 내가 살면서 Pytorch는 영원하지 않다. 개발자는 개발 언어에 큰 비중을 두어서는 안된다. 영원할 것만 같은 개발 언어도 언젠간 망하기 마련이고, 개발자는 그 변화에 빠르고 신속하게 적응해야한다. 개발자는 코딩의 전반적 지식과, 알고리즘, 그리고 논문 지식을 통해서 능력을 발휘할 수 있다.
  • 아이러니 하게도, flax, vit_jax 로 만들어진 vit (vision transformer) 코드는 1.8k stars를 가지고 있고, pytorch로 만들어진 vit 코드는 2.8k이다. 원래 것 보다 더 높은 star를 가지고 있다.

Colab 환경세팅

from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/MyDrive/GCPcode/torch_package
!ls

# !git clone https://github.com/lucidrains/vit-pytorch.git
%cd vit-pytorch
!python setup.py install

# no module einops 문제 해결방법
!pip install einops==0.2.0
!pip install einops==0.3.0
  • vision transformer 에는 몇가지 사용방법이 존재한다.
  • 16x16 Image recognition 논문에서 사용한 방법이 아래 1번의 방법이다.
  • 나머지 2번 ~ 5번의 방법은, 다른 논문에서 소개된 방법론이다. 이것까지 코드로 어떻게 사용하는지 소개해 놓았다.
    1. from vit_pytorch import ViT
    2. from vit_pytorch.t2t import T2TViT
    3. SOTA self-supervised learning technique : from vit_pytorch import ViT + from byol_pytorch import BYOL
    4. Efficient Attention : Nystromformer (computer vision cost(메모리,시간)를 낮춰주는 새로운 방법)
    5. x-transformers : used the most vanilla of attention networks
  • 따라서, 일단 나는, 16x16 Image recognition 논문을 먼저 이해하고 싶으므로, 위의 1번의 방법만 잘 이해하면 된다.
  • 위 1번 방법의 코드는 vit-pytorch/vit_pytorch/vit_pytorch.py 여기있는게 전부이다.

코드 리뷰

  • 핵심 코드 https://github.com/lucidrains/vit-pytorch/blob/main/vit_pytorch/vit_pytorch.py
  • 아래의 코드 내부 주석에 소중한 내용들이 많이 들어갔으니 꼭 참고하기!!
  • from einops import rearrange, repeat 이라는 마법의 이미지 변환 모듈을 사용했다.
  • from torch import einsum 이라는 마법의 텐서 변환 모듈을 사용했다.
    • 위의 2 모듈은 string을 입력하면 그 문자에 맞추어, 배열을 변환해 준다.
    • 예를 들어 이렇게 Rearrange("b c (h p1) (w p2) -> b (h w) (p1 p2 c)", p1 = patch_size, p2 = patch_size)
  • 실행 코드
import torch
from vit_pytorch import ViT

v = ViT(
    image_size = 256, 
    patch_size = 32,
    num_classes = 1000,
    dim = 1024, # A image patch가 변환되어, 1차원 백터가 됐을 때, 백터 원소의 갯수
    depth = 6, # Transformer blocks 갯수 ( Transformer Encoder 그림에서 x L )
    heads = 16, # heads in Multi-head Attention layer 의 갯수
    mlp_dim = 2048, # Multi Layer perceptron 에서 0층 1층 2층에서 1층의 백터 갯수
    dropout = 0.1, # [0,1] 사이의 수. default = 0 
    emb_dropout = 0.1
)

img = torch.randn(1, 3, 256, 256)
mask = torch.ones(1, 8, 8).bool() # optional mask, designating which patch to attend to

preds = v(img, mask = mask) # (1, 1000)
  • class ViT(nn.Module)
class ViT(nn.Module):
    def __init__(self, *, image_size, patch_size, num_classes, dim, depth, heads, mlp_dim, pool = 'cls', channels = 3, dim_head = 64, dropout = 0., emb_dropout = 0.):
        super().__init__()
        assert image_size % patch_size == 0, 'Image dimensions must be divisible by the patch size.'
        num_patches = (image_size // patch_size) ** 2 # ( 224/32 = 16 ) ** 2 = 256의 Patchs
        patch_dim = channels * patch_size ** 2  # patch 하나가 가진 pixel의 총 갯수 = 32*32*3 = 3072
        assert pool in {'cls', 'mean'}, 'pool type must be either cls (cls token) or mean (mean pooling)'
        
        # from einops import rearrange, repeat 이라는 마법의 이미지 변환 모듈 사용
        # 아래의 과정을 통해서 이미지를 1차원 dim
        self.to_patch_embedding = nn.Sequential(
            Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = patch_size, p2 = patch_size),
            nn.Linear(patch_dim, dim), # 3072 -> 1024
        )

        # sin 함수를 이용한 embedding을 하는 줄 알았는데... 
        # randn 은 그냥 원하는 크기의 Tensor를 설정해줄 뿐, Parameter로 세팅해놓음으로써, Learnable이 된다.
        # 즉 pos_embedding 그리고 cls_token 는 Just Tensor가 아니라 Learnable 이다.
        self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim))
        self.cls_token = nn.Parameter(torch.randn(1, 1, dim))
        self.dropout = nn.Dropout(emb_dropout)

        # Transformer Encoder layer 정의
        self.transformer = Transformer(dim, depth, heads, dim_head, mlp_dim, dropout)

        self.pool = pool  # string in {'cls', 'mean'}
        self.to_latent = nn.Identity()

        # layerNorm 이라는게 있나보다. 그냥 mlp_head는 nn.Linear 라고 생각하면 편하다.
        self.mlp_head = nn.Sequential(
            nn.LayerNorm(dim),
            nn.Linear(dim, num_classes) # 1024 -> 1000
        )

    def forward(self, img, mask = None):
        x = self.to_patch_embedding(img)
        b, n, _ = x.shape

        cls_tokens = repeat(self.cls_token, '() n d -> b n d', b = b)
        x = torch.cat((cls_tokens, x), dim=1)
        x += self.pos_embedding[:, :(n + 1)]
        x = self.dropout(x)

        x = self.transformer(x, mask)
        # print(x.shape) # torch.Size([1, 65, 1024])

        x = x.mean(dim = 1) if self.pool == 'mean' else x[:, 0]
        # print(x.shape) # torch.Size([1, 1024])

        x = self.to_latent(x)
        out = self.mlp_head(x)
        # print(out.shape) # torch.Size([1, 1000])
        return out
    
"""
여기서 알아야 하는 것.
nn.LayerNorm(dim)
nn.Identity()
class Transformer(nn.Module):
"""
  • class Transformer(nn.Module):
  • 논문 그림에서 “Transformer Encoder” 를 그대로 코드 구현을 해 놓은 것이다.
class Transformer(nn.Module):
    def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0.):
        super().__init__()
        self.layers = nn.ModuleList([])
        for _ in range(depth):
            self.layers.append(nn.ModuleList([
                Residual(PreNorm(dim, Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout))),
                Residual(PreNorm(dim, FeedForward(dim, mlp_dim, dropout = dropout)))
            ]))
    def forward(self, x, mask = None):
        for attn, ff in self.layers:
            x = attn(x, mask = mask)  # LayerNorm + Attention   + Residual 	
            x = ff(x)			      # LayerNorm + FeedForward + Residual 
        return x

"""
여기서 알아야 하는 것.
Residual
PreNorm
FeedForward
Attention
"""
  • class Residual : Skip connection 구현
  • class PreNorm : LayerNorm + [FeedForward or Attention]
  • class FeedForward : Multi Layer perceptron = 2층 nn.Linear
class Residual(nn.Module):
    # Skip connection 구현
    def __init__(self, fn):
        super().__init__()
        self.fn = fn # 무조건 class PreNorm 
    def forward(self, x, **kwargs):
        return self.fn(x, **kwargs) + x

    
class PreNorm(nn.Module):
    # LayerNorm + [FeedForward or Attention]
    def __init__(self, dim, fn):
        super().__init__()
        self.norm = nn.LayerNorm(dim)
        self.fn = fn  # class FeedForward 혹은 class Attention 둘 중 하나
    def forward(self, x, **kwargs):
        x = self.norm(x)
        return self.fn(x, **kwargs)

    
class FeedForward(nn.Module):
    # Multi Layer perceptron = 2층 nn.Linear
    def __init__(self, dim, hidden_dim, dropout = 0.):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(dim, hidden_dim),
            nn.GELU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim, dim),
            nn.Dropout(dropout)
        )
    def forward(self, x):
        return self.net(x)

  • class Attention(nn.Module) : Multi Head Attention 모듈 구현
  • 아래에서 Keys, Querys, Values가 의미하는게 뭘까? 이전Post 내용에 따르면, 1차원 백터에서 어떤 부분에 더 집중해야 하는지? 를 나타낸다고 한다.
  • 아래의 qkv = self.to_qkv(x).chunk(3, dim = -1) 에서 x는 이미지 전체를 1차원 백터(1024개)로 embeding한 값들이 8*8 (64개 patchs)가 모두 모여 있는 백터이다. 즉, 1024 x 64의 x.shape를 가지고 있을 것이다.
  • 자, 그렇다면 64개의 patch 하나하나를 하나의 단어라고 생각하자.
  • 이전Post 내용에 따르면 “Hello I love you”에서 Love는 I와 you에 더 attention해야하고, 따라서 더 큰 weight를 줘야한다.
  • 같은 원리로 64개의 patch 각각에 대해서, 1개의 Patch는 다른 patch 중 어느 것에 더 집중해서 attention해야하는지를 weight값으로 알려주는 것이 Keys, Querys, Values이고, 이 처리를 모두 하고 나온 백터가 qkv이다.
class Attention(nn.Module):
    def __init__(self, dim, heads = 16, dim_head = 64, dropout = 0.):
        '''
        dim = patch를 1차원화 백터 원소의 갯수 = 1024 개
        heads = 1, 2, 3 ... ~ h (Multi-head Attention)에서 h 갯수
        
        처음 들어가는 1개 image patch의 차원 [1, 1024]
        [x1 ~ x65] = [1, 65, 64] # 원래 patch갯수는 64개 + extra class embedding 1개 = 65개
        하나의 Head에 의해 나오는 y_i의 차원 [1, 64]
        [y1 ~ y65] = [1, 65, 64] 
        '''
        super().__init__()
        inner_dim = dim_head *  heads # 64*16 = 1024
        project_out = not (heads == 1 and dim_head == dim)

        self.heads = heads
        self.scale = dim_head ** -0.5 # 0.125
		"""
        # qkv의 nn.linear 를 그림처럼 따로 하는게 아니라, 한꺼번에 해버린다.
        # 아래의 *3 이 의미하는 것은 qkv 3개를 말하는 건가?
        # inner_dim 은 qkv 중 하나의 linear를 통과했을 때 나오는 총 원소의 갯수
        # 즉 dim_head는 위 Transformer 이미지에서, 하나의 작은 linear를 통과했을 때 나오는 원소의 갯수 이다. 
        
        # input은  queries, keys, values와 연산되어 (nn.linear), forward 코드와 같이 각각 q, k, v 변수가 된다. 
        # by queries : (input)1024 vectors -> 64 vectors * 16개 head 
        # by keys : 1024 vectors -> 64 vectors * 16개 head 
        # by values : 1024 vectors -> 64 vectors * 16개 head 
        """
        self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False)

        self.to_out = nn.Sequential(
            nn.Linear(inner_dim, dim), # (64*16 = 1024) -> 1024개
            nn.Dropout(dropout)
        ) if project_out else nn.Identity()

    def forward(self, x, mask = None):
        """
        # heads의 갯수 설정으로 내부에서 다수의 head가 알아서 돌아간다. 
        # 주의! heads는 Transformer Encoder의 Lx에서 L이 아니다! 맨 위 사진의 1~h에서 h 이다!
        # 따로 분류해서 연산하지 않고, 한꺼번에 묶어서 연산해 버린다. 
        # 그래서 이 코드로는 위 그림의 이해가 한방에 되지 않을 수 있다.
        
        # 따라서 아래 내용이 복잡하지만... "이거 다 통과하면 하나의 Multi Head Attention 을 통과하는 구나! 라고 알아두자."
        """
        
        b, n, _, h = *x.shape, self.heads
        # print(x.shape) # torch.Size([1, 65, 1024])
        qkv = self.to_qkv(x).chunk(3, dim = -1) 
        # print(qkv.shape, qkv[0].shape) # (3,) torch.Size([1, 65, 1024])
        # torch.chunk Tensor를 자른다.
        # q, k, v 각각, input에서 by queries, keys, values 처리를 하고 나오는 '결과'
        q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = h), qkv) 
        # print(q.shape,k.shape,v.shape) # torch.Size([1, 16, 65, 64]) torch.Size([1, 16, 65, 64]) torch.Size([1, 16, 65, 64])

        # torch.einsum (https://pytorch.org/docs/stable/generated/torch.einsum.html)
        # tensor를 원하는 형태로 변환해줘!
        dots = einsum('b h i d, b h j d -> b h i j', q, k) * self.scale
        mask_value = -torch.finfo(dots.dtype).max

        if mask is not None:
            mask = F.pad(mask.flatten(1), (1, 0), value = True)
            assert mask.shape[-1] == dots.shape[-1], 'mask has incorrect dimensions'
            mask = rearrange(mask, 'b i -> b () i ()') * rearrange(mask, 'b j -> b () () j')
            dots.masked_fill_(~mask, mask_value)
            del mask

        attn = dots.softmax(dim=-1)

        out = einsum('b h i j, b h j d -> b h i d', attn, v)
        """
        여기까지 out = torch.Size([1, 16, 65, 64])
        <맨 위의 Transformer 최종 정리 사진과 꼭 함께 보기>
        이 말은 하나의 Head에 의해 나오는 y_i는 64개의 백터를 가진다. 총 [y1 ~ y65] = [1, 65, 64] 차원을 가지게 된다. 
        """
        out = rearrange(out, 'b h n d -> b n (h d)')
        out =  self.to_out(out)
        # print(out.shape) # torch.Size([1, 65, 1024])
        return out

Youtube 발표자료

p1

P2

![PR-281_ An Image is Worth 16x16 Words_ Transformers for Image Recognition at Scale_210303110807-10.png](https://github.com/junha1125/Imgaes_For_GitBlog/blob/master/2021-1/16x16_Transformers_for_Image_Recognition/PR-281%20An%20Image%20is%20Worth%2016x16%20Words_%20Transformers%20for%20Image%20Recognition%20at%20Scale_210303_110807-10.png?raw=true)

  • Method는 내가 한 정리가 더 좋다.
  • Experiments and Results

P3

P3

P4

P5

P5

P5

P5

P5

P5

【MOT】MOTS - Multi-Object Tracking and Segmentation

  • 논문 : MOTS: Multi-Object Tracking and Segmentation
    필기 완료된 파일은 OneDrive\21.겨울방학\RCV_lab\논문읽기 에 있다.
  • 분류 : MOT
  • 저자 : Paul Voigtlaender, Michael Krause, Aljosa sep, Jonathon Luiten
  • 읽는 배경 : 연구실 과제 참여를 위한 선행 학습
  • 느낀점 :
    • 코드를 많이 보고 싶은데, Tensorflow….
    • 솔직히, 결과들을 보면 이 모델이 정말 좋은 모델인가..? 라는 생각이 든다. Conv3D 그리고 Association head에서 다른 것들에 비해서 좋은 성능이 나왔다는 생각이 많이 들지 않는다.
    • 그들의 성능평가 matrix 자체 점수를, 원래 조금이라도 올리기가 매우 힘든건가? 확실히 아직은 MOTS 에 대해서 더 많은 연구가 이뤄져야 할 듯 하다.
    • 이 논문보다는 다른 (bounding box) MOT 논문을 찾아 다시 공부하자. 그렇게 신박한 방법은 없다. 아래의 내용정리만으로 이해가 어려우니, 필요하면 논문을 다시 보고 + 코드를 다시보고 공부해야한다. 아니면 MOT 논문을 공부해보고 이 논문을 다시 보자.


0. Abstract, Conclusion

  • (문제점) 지금까지 MOT + Segmentation을 같이 수행하는 benchmark model과 dataset이 존재하지 않았다.
  • (해결) 우리가 semi-automatic annotation procedure을 사용해서 만든 2개의 MOT dataset을 소개했다. 이미 존재하는 MOT 데이터(Bounding Box detection only) 에서 Segmentation 정보를 직접 추출해서, 그거를 Training data로 사용했다.
  • 기존의 MOTA matrics(평가지표)을 기반으로 새로 만들어낸 MOTSA, sMOTSA를 소개했다.
  • baseline model을 개발했다. detection + tracking + segmentation 을 모두 동시에 하는 single convolutional network 이다.

1. Introduction

  • (현재) bounding box level tracking 성능이 Saturation 되었다.
  • (문제점) 하지만 bounding box level tracking 에는 문제점이 있다. 겹처진 객체에 대해서 too coarse 한 BB를 가진다는 점이다. 또한 BB는 object에 대한 roughly fit 이기 때문에, overlapping BB(서로 겹치게 예측된 BB)와 그 GT를 비교하면, ambiguities 존재하는 것을 알 수 있다. (predicted BB가 맞는것(Positive)… 같기도 하면서 아니기도 한 그런…)
    image-20210219193943400
  • (해결책) BB와 다르게 Segmentation 정보는 non-overlapping 하므로 GT와 비교할 때 아주 단순한 방법으로 비교 가능하다.
  • (그래서 우리는) Mask R-CNN에 3D convolution을 사용한 TrackR-CNN을 만들어 냈다.
  • 논문 전체 contributions(summary)
    1. KITTI [13] and MOTChallenge [38] datasets 를 기반으로 MOTS를 위한 dataset 생성
    2. soft Multi-Object Tracking and Segmentation Accuracy (sMOTSA) measure(평가지표) 소개
    3. TrackR-CNN
    4. 우리 모델의 유용함 증명한다. 그 뿐만 아니라, 우리의 데이터 셋과, segmentation + tracking single network가 충분히 있음직하고 좋은 성능을 발휘한다는 것을 증명할 것이다.

2. Related work

  1. Multi-Object Tracking Datasets : a known set of classes로부터 unknown number of targets을 추적한다. Bounding box를 기반으로 한다. + 논문에 데이터셋 몇가지가 소개되어 있다.
  2. Video Object Segmentation Datasets : instance segmentations을 수행하기는 하나, 일렬의 비디오에 only few objects 만이 존재한다. 우리의 MOTS 모델은 미리 정의된 classes들과 crowded objects를 고려한다. + 논문에 데이터셋 몇가지가 소개되어 있다.
  3. Video Instance Segmentation Datasets : Cityscapes처럼 automotive scenario를 사용하는 3개의 데이터 소개한다. 하지만 이들은 동영상이 아주 작은 subset(짧은 frame 수)으로 구성되어 있거나, 특히 ApollloScape 데이터는 객체의 identities 정보가 없다. (tracking dataset으로 사용 불가)
  4. Methods
    • MOTS와 비슷한 작업을 하는 다른 논문들 몇가지 소개. 필요하면 찾아보기. 다른 논문들과 달리 MOTS는 많은 객체들이 동영상에서 들어가고 나간다. 또한 다른 논문들은 segmentation tracking 정보를 추출할 수는 있지만, MOTS annotation dataset이 없었기 때문에, 그들의 performance를 평가할 수 없었다.
    • LSTM을 사용해서 Tracking을 수행하는 2개의 논문 소개한다. [34, 2017], [51, 2017] 하지만 이들은 detection을 수행한 Frame들에 대해서 Hungarian matching procedure라는 전통적인 후처리 방법을 사용한다. MOTS에서는 그런 후처리 작업 수행하지 않는다.
  5. Semi-Automatic Annotation (반 자동 instance segmentation 주석 처리 방법)
    • deep learning을 사용하지 않는 전통적 컴퓨터 비전 방식의 annotation 기술들 몇가지가 소개 된다.
    • MOTS에서는 Polygon-RNN 이라는 방법을 사용한다. 다각형의 꼭지점을 정의하는 모델이다.
    • Fluid Annotation(사진 전체 mask-rcnn) 방법은, Tracking을 고려하지 않고, base dataset의 bounding box annotation 정보도 사용하지 않기 때문에, MOTS에서 사용하지 않는다.

3. Datasets

  1. Semi-automatic Annotation Procedure
    1. DeepLabV3+ 모델을 사용한다. Input에는 BB에 의해 crop된 + 아주 작은 region added(BB보다 조금 크게) 가 이뤄진 이미지를 사용한다.
    2. COCO, Mapillary dataset으로 pre-train 된 DeepLabV3+모델이라 할지라도, [KITTI MOTS, MOTSChallenge] dataset을 1번과 같은 방법으로 inference를 수행하면 성능이 poor하다고 한다. (아마 domain change 때문에) 그래서 초반에는 all manually created masks 를 가지고 학습시켜준다. 그러다 보면 상대적으로 괜찮은 Mask predict 값을 추출하게 되는데, 이때도 아직은 완벽하지는 않다.
    3. 위 과정 이후, DeepLabV3+을 이용해서 우선 predict segmentation를 하고, 그렇게 나오는 결과값(flawed generated masks)을 직접 manually 수정한다. 이렇게 수정한 이미지를 사용해 training을 다시 수행한다.
    4. 일정수준의 pixel-level accuracy이 나올때까지 위의 작업을 계속 반복하며 수행한다.
  2. KITTI MOTS dataset
    • 원래 이 데이터는 21개의 training sequences를 가지고 있다. 이것을 MOTS를 하기 위해 적절히 나눈다. car, pedstrian의 전제 숫자가 비슷하도록 데이터를 최대한 잘 분배했다. training set : validation set = 12 : 9
    • 특히나, 이 데이터를 pre-train 된 DeepLabV3+에서 inference를 하면 poorly 성능을 보인다. 이것은 “instance segmentation model들이 temporal reasoning을 사용(결합)해야만 한다는” 주요한 동기부여가 된다. (뭔소린지 정확히 모르겠다. instance segmentation을 하기 위해 temporal 정보를 어떻게든 사용한다면 성능이 훨씬 좋아질 수 있다는 건가? 이 방법을 사용해서 연구를 해도 좋을 것 같다.)
  3. MOTS Challenge dataset
    • 이 데이터 셋은 특히나 pedestrians in crowded scenes으로 이루어져 있다. 따라서 많은 occlusion(겹침) 문제가 발생한다. 따라서 pixel-wise description(mask 정보) 를 사용함으로써 특별히 이득을 볼것으로 예상된다고 한다.

image-20210219203814793


4. Evaluation Measures

  1. 변수 정의
    • M은 Ground True Segmentation 정보 ( 1 instance -> 1 channel bool 형식 )
    • H가 Predicted Segmentation hypothesis (예측 Instance Segmentation 값)
    • image-20210220180053696
  2. Establishing Correspondences (Predict를 얼마나 Correct하게 했는지 수치화)
    • image-20210220180940631
    • 위 그림에 숫자 동그리마 필기 찾기.
    • 0번째 수식 : c(h) = IOU 값을 이용해선 correctness 수치화량 값. 보통 Segmentation에서는 IOU(h,m) > at most 0.5 를 겨우 넘는 수준이라고 한다. 즉 BB보다 IOU값이 높게 나오기 힘들다.
    • 1번째 수식 ~ 3번째 수식 : h (prediced mask instance 집합의 원소), m (ground ture mask instance 집합의 원소) 를 활용한 TP, FP, FN 정의
    • 4번째 수식 : mask 뿐만 아니라, id까지 동일해야 한다. t에 관한 수식은 GT dataset에서 (논문의 주석5) does not count id switches if the target was lost by the tracker 이기 때문에 저런 수식이 나오는 듯 하다. 그리고 같은 ID인지 판단하는 알고리즘은 정확하게 적혀있지 않아있다. 따라서 필요하면 직접 코드를 보고 공부를 해야할 듯 하다.
    • 5번째 수식은 (IDS 수식은 정확히 이해되지 않는다. 필요하면 다시 공부하자.) m들 중에서, h들과 고려해봤을때 (같은 mask를 가르키고 있다고 판명할 만한 h가 있기는 하지만) ID까지 일치하는 객체가 없는 m의 갯수이다. 이것도 높으면 안 좋은 것.
  3. Mask-based Evaluation Measures
    • 아래의 수식들은 CLEAR MOT metrics [4, 2008]의 내용들을 기반으로 한다. 따라서 완벽한 이해가 안되면, CLEAR MOT 수식에 대해서 먼저 공부해야할 듯 하다.
    • image-20210220181902975
    • 얼마나 MOTS를 잘 수행하고 있는지 계산하는 matrix들이다.
    • 6번째 ~ 9번째 수식들을 사용하면 되고, 이 값이 높을 수록 MOTS가 잘 수행되고 있다고 판단할 수 있다.

5. Method

image-20210220182108558

  1. 아래의 내용들이 그렇게 구체적이지 않다. 따라서 이용하고 싶다면, 코드를 꼭 봐야할 필요가 있다. (Tensorflow 1.13 코드)
  2. Integrating temporal context
    • depthwise separable 3D convolution layers with 3×3 (spatial) ×3 (time) filter kernels. 즉 위의 필기에서 (3x3x256)은 filter 는 필터 차원이고, x128은 filter 의 갯수이고, 3x는 3D conv를 필요한 추가 차원이다.
    • ResNet-101
    • 위의 사진에서는 3D conv가 들어가지만, 대체신경망으로 (일반 LSTM과 다르게 the spatial structure 를 유지하고 있는) Convolutional LSTM (+ skip connection) 을 사용하는 것도 고려해 보았다고 한다. 논문에서 Convolutional LSTM를 검색하면, 이것을 사용할 때의 장점, 효과, 실험과정, 에 대해서 간단히 살펴볼 수 있다.
  3. Association Head
    • Association Head를 사용한 Inference
      • fully connected layer
      • Association Vectors 를 생성한다. 두 백터 사이의 유사도 판별은 단순하게 Euclidean distance 방법을 사용한다.
      • image-20210220182250679
    • Association Head 학습시키기
      • the batch hard triplet loss (proposed by Hermans et al. [18] adapted for video sequences) 의 방법을 사용하여 학습시킨다.
      • D denote the set of detections for a video (비디오에서 검출되는 모든 객체의 갯수)
      • d ∈ D consists of a mask mask_d and an association vector a_d
      • 아래 수식에서 margin alpha = 0.2가 가장 좋았다.
      • image-20210220182453584
  4. Mask Propagatio
    • image-20210220182551872
    • PWC-Net [55, 2018] 모델을 사용해서 Optical flow 계산
  5. Tracking
    • 이 내용은 논문에서 수식과 디테일 없이 간단하게 적어놓았다. 논문을 봐도 이해가 잘 안된다.
    • their association vector similarity (Euclidean distance)를 기반으로 Tracking을 수행한다. γ threshold 이상을 가지는 detections를 찾는다.
    • the Hungarian Algorithm을 사용햐서 Matching을 수행한다. threshold of β 이상을 가지는 detection을 찾는다.
    • 적절한 tracking hyper-parameter (δ, β, γ)를 찾기 위해 random search(이것저것으로 다 실험해봄)를 사용했다고 한다.
    • The resulting tracks (tracking하기 위해 찾아낸 detections) 들 서로서로가 겹칠 수 있다. (다중으로 뽑힐 수 있다.) 여기서는 MNS와 같은 방식으로 a higher confidence를 가지는 mask detections들을 선택한다.

6. Experiments

  • 40 epochs
  • a learning rate of 5 · 10^(−7) using the Adam optimizer
  • mini-batches which consist of 8 adjacent frames
  • Titan X
  • a speed of around 2 frames per second (아마 1번 mini-batch 결과가 나오는데, 4초 정도 걸리나 보다)
  • Main Results
    • image-20210220230519597
    • 맨위의 TrackR-CNN(box orig)는 mask head 가 없는 TracR-CNN이다. (PS. CAMOT [43] : stereo 정보를 사용)
    • +MG : segmentation masks as a post-processing step. 즉 Mask R-CNN의 the mask head 이라고 한다.

    • 코드 사용이 가능한 Segmentation-based tracker 가 없다. 대신 the bounding box-based tracker인 CIWT [42] and BeyondPixels [53]에 fine-tunning된 Mask R-CNN의 the mask head를 결합한 모델을 사용해 보았다.
  • Temporal Component
    • backbone feature map과 RPN 사이의 2개의 Conv3D (two depthwise separable 3D convolutional layers)를 넣었을 때의 장점
    • image-20210220233713166
  • Association Mechanism
    • image-20210220233436415
    • Association head를 사용하지 않고, 다른 기본적인 방법을 사용했을 때 성능의 증가율
  • Results on MOTS Challenge
    • image-20210220233927803
    • four methods that perform well on the MOT17 benchmark + Mask R-CNN fine-tuned on MOTSChallenge 이 모델들에 비해서는 좋은 성능을 보이고 있다.
    • 마지막 결과을 보면 확실히 segmenting all pedestrians 이 매우 어려운 문제로 남아있다는 것을 확인할 수 있다.

Pagination


© All rights reserved By Junha Song.