【LightWeight】Understanding MnasNet+NAS-FPN from youtube w/ code

1. MnasNet from youtube

  • 논문에 나오는 최종 모델 Architecture
    image-20210210145223586
  • 발표자분들끼리 하는 이야기로, 이런 NAS 작업을 우리같은 일반인이 하기는 쉽지 않다. 구글의 목표는 “너네가 원하는 신경망을 최적으로 찾고 싶다면, 너네 스스로 하지말고 돈 좀 내고 우리가 만든 플랫폼을 사용해서 최적의 신경망을 찾아” 라는 것을 목표로 한다고 한다. 따라서 NAS를 일반인이 하기에는 더욱 어려운 것 같다.
  • 그럼에도 불구하고 이 논문이 나오기 전, EnasNet은 [기존에 800개의 GPU로 21일을 학습시켜서 최적의 모델을 찾은 NAS]에 비해서 학습 효율이 더 좋게 만들기 위한 목적을 가지고 있다. 1개의 GPU로 8시간을 학습했다고 한다. 나중에 정말 NAS를 공부해야한다면 EnasNet 또한 읽어보는 것도 좋겠다.
  • 강의 필기 자료

img01 img02 img03 img04 img05 img06 img07 img08 img09 img10 img11 img12 img13 img14 img15 img16 img17 img18 img19 img20 img21 img22 img23 img24 img25 img26 img27 img28 img29 img30



2. NAS-FPN from youtube

  • 논문에 나오는 최종 모델 (아래 그림에서 (a) -> (f)는 모델의 발전 과정이다.) image-20210210145039802
  • 강의 필기 자료

img01 img02 img03 img04 img05 img06 img07 img08 img09 img10 img11 img12 img13 img14 img15 img16 img17 img18

3. code - MnasNet-PyTorch

  • Github1 - AnjieCheng/MnasNet-PyTorch <- MnasNet.py 파일 1개만 있다.
  • Github2- Cadene/pretrained-models.pytorch <- NASNet 뿐만 아니라, Backbone으로 사용하기 좋은 pretrained-model들이 다앙햐게 있다.
# MnasNet.py 
class MnasNet(nn.Module):
    def __init__(self, n_class=1000, input_size=224, width_mult=1.):
        super(MnasNet, self).__init__()

        # setting of inverted residual blocks
        self.interverted_residual_setting = [
            # t, c, n, s, k
            [3, 24,  3, 2, 3],  # -> 56x56
            [3, 40,  3, 2, 5],  # -> 28x28
            [6, 80,  3, 2, 5],  # -> 14x14
            [6, 96,  2, 1, 3],  # -> 14x14
            [6, 192, 4, 2, 5],  # -> 7x7
            [6, 320, 1, 1, 3],  # -> 7x7
            """
            t : expand_ratio(Channel 몇 배로 확장 후 축소) 
            c : output_channel 
            n : 같은 block 몇번 반복? 
            s : stride 
            k : kernel
            """
        ]

        assert input_size % 32 == 0
        input_channel = int(32 * width_mult)
        self.last_channel = int(1280 * width_mult) if width_mult > 1.0 else 1280

        # building first two layer
        # 여기서 Conv_3x3, SepConv_3x3 함수는 nn.Sequential( ... )를 return 하는 함수이다.
        self.features = [Conv_3x3(3, input_channel, 2), SepConv_3x3(input_channel, 16)]
        input_channel = 16

        # building inverted residual blocks (MBConv)
        for t, c, n, s, k in self.interverted_residual_setting:
            output_channel = int(c * width_mult)
            for i in range(n):
                if i == 0:
                    self.features.append(InvertedResidual(input_channel, output_channel, s, t, k))
                else:
                    self.features.append(InvertedResidual(input_channel, output_channel, 1, t, k))
                input_channel = output_channel

        # building last several layers
        self.features.append(Conv_1x1(input_channel, self.last_channel))
        self.features.append(nn.AdaptiveAvgPool2d(1))

        # make it nn.Sequential
        self.features = nn.Sequential(*self.features)

        # building classifier
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(self.last_channel, n_class),
        )

        self._initialize_weights()

    def forward(self, x):
        x = self.features(x)
        x = x.view(-1, self.last_channel)
        x = self.classifier(x)
        return x

【Detection】Understanding YOLOv4 paper w/ code, my advice

  • 논문 : YOLOv4: Optimal Speed and Accuracy of Object Detection

  • 분류 : Object Detection

  • 저자 : Alexey Bochkovskiy, Chien-Yao Wang, Hong-Yuan Mark Liao

  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.

  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.

  • 느낀점 :

    • 논문 리뷰 정리를 할 때. 자꾸 같은 내용은 여기저기 쓰지 말아라. 한 곳에 몰아 정리하자.

      • 예를 들어 A,B라는 Key Idae가 있다고 치자. 그럼 아래 처럼 실제 논문에는 “같은 내용 반복하거나, 어디 다른 곳에서 추가 특징을 적어 놓는다” 그렇다고 나도 따로따로 분산해서 정리해 두면 안된다. “깔끔하게 정말 핵심만 한곳에 모아 정리해야 한다” 즉. 굳이 논문과 같은 목차로 정리해야한다는 강박증을 가지지 말아라. 어차피 핵심만 모으면 별거 없고, 한곳에 모인다.

      •       
        $ 실제 논문에는 이렇게 적혀 있다.
        1. Conclusion ,abstract
          - A idea
          - A의 장점1
          - A의 장점2
          - B idea
          - B의 장점1
        2. introduction
          - A의 장점1
          - A의 장점2
          - B의 장점1
          - B의 장점2
        3. Relative Work
          - A의 장점3
          - B의 장점2
          - B의 장점3
                
        $ ** 내가 정리해야 하는 방법 **
        1. Conclusion ,abstract
          - A idea
          - A의 장점1
          - A의 장점2
          - A의 장점3
          - B idea
          - B의 장점1
          - B의 장점2
          - B의 장점3
        
        
      • YoloV4 는 새로운 기법을 공부하기 위해서 읽는 논문이 아니로, 그냥 Object Detection Survey 논문이다.
  • 목차

    1. YoloV4 from youtube (바로가기)
    2. YoloV4 Paper (바로가기)
    3. Code - Tianxiaomo/pytorch-YOLOv4 (바로가기)
    4. About YoloV5 (바로가기)
  • PS

  • 추가로 읽어야겠다고 생각되는 논문

    1. PAN - path aggregation network
    2. ATSS : Bridging the Gap Between Anchor-based and Anchor-free Detection via Adaptive Training Sample Selection (citation : 74)
    3. RFB : Receptive Field Block Net for Accurate and Fast Object Detection (ASPP의 발전된 형태)
    4. Cross stage partial connections (DenseNet의 경량화 버전)
    5. Batch Normalization 블로그 & 동영상, CBN (Cross Batch Normalization)
    6. Soft-NMS -> DIoU-NMS
    7. CIoU-loss
    8. Mish Activation
    9. DropBlock regularization
    10. Class label smoothing

1. YoloV4 from youtube

  • youtube 논문 발표 링크 - 설명과 정리를 잘해주셨다.
  • 이 정도 논문이면, 내가 직접 읽어보는게 좋을 것 같아서 발표자료 보고 블로그는 안 찾아보기로 함
  • 강의 필기 PDF는 “OneDrive\21.겨울방학\RCV_lab\논문읽기”

img01 img02 img03 img04 img05 img06 img07 img08 img09 img10 img11 img12 img13 img14 img15 img16 img17 img18 img19 img20 img21 img22 img23 img24 img25 img26 img27

2. YoloV4 Paper Review

1. Conclustion, Abstract, Introduction

  • Faster / more Accurate(AP_(50…95) and AP_(50)) / best-practice with only one conventional GPU (1080 Ti or 2080 Ti GPU)
  • batch-normalization and residual-connections 과 같은 통념적으로 사용되는 Feature(여기서는 특정기술,특정방법론 이라고 해석해야함. Feature Map의 Feature 아님)뿐만 아니라, 아래와 같이 YoloV4에서 많은 성능향상을 준 Feature들이 있다.
    1. 무시가능한 특정기술 : Self-adversarial-training (SAT) (-> 좋다는 결과 없음. 일단 무시)
    2. 중간 중요도의 특정기술 : CmBN, DropBlock regularization, and CIoU loss. 기법들
    3. 중상 중요도 특정기술 : Weighted-Residual-Connections (WRC), Cross-Stage-Partial-connections (CSP), Cross mini-Batch Normalization (CmBN), Mish-activation
    4. 자신들이 Modified한 특정기술 : Cross Batch Normalization (CBN), Path aggregation network(APN), CBAM(SelfAttentionModul)
    5. 자신들이 추가하거나 수정한 특정기술: Mosaic data augmentation
    6. (1) Bag-ofFreebies and (2) Bag-of-Specials methods : 아래 목차에서 차근히 다룰 예정
  • 최종 성능 : 43.5% AP (65.7% AP50) for the MS COCO / speed of ∼65 FPS on Tesla V100.
  • image-20210208163946588
    1. ASFF : Learning Spatial Fusion for Single-Shot Object Detection (citation : 14)
    2. ATSS : Bridging the Gap Between Anchor-based and Anchor-free Detection via Adaptive Training Sample Selection (citation : 74)
  1. Object detection models
    • image-20210208184736493
    • 최근에 핫한 기술에 이런 것들이 있다.
    • 특히 Neck 이란? different stages로부터 Feature Maps 정보를 Collect한다.
  2. Bag of freebies
    • change the training strategy or increase the training cost 하는 방법들
    • data augmentation
      1. pixel-wise adjustments
      • photometric distortions : the brightness, contrast, hue, saturation, and noise of an image.
      • geometric distortions : random scaling, cropping, flipping, and rotating 2. simulating object occlusion issues
      • random erase(칼라 구멍), CutOut(검정 구멍)
      • hide-and-seek, grid mask : 일부 사각형 구역 검정
      • DropOut, DropConnect, and DropBlock 위 기법과 비슷한 컨셉
      • MixUp(두 이미지 blending), CutMix(구멍 - 다른 사진+Label) : multiple images together 사용하기
      • style transfer GAN : 현재 내가 가진 the texture bias 줄인다.
    • the problem of semantic distribution bias (예를들어, data imbalance)
    • Only two-stage : hard negative example mining & online hard example mining
    • one-stage : focal loss
    • label smoothing [73] , label refinement network [33]
    • the objective function of Bounding Box (BBox) regression
    • MSE : corresponding offset를 예측하는 것은, 온전체 객체 그 자체의 정보를 이용하는 것이 아니다.
    • IoU loss : IOU가 커지도록 유도됨. offset Loss는 (GT 박스가) 큰 객체에서는 상대적으로 loss가 커지는 경향이 있었는데, IOU loss에서는 이런 문제가 없음.
    • G_IOU : 객체의 모양이나 회전 정보를 포함
    • DIoU : GT와 BB의 center간의 distance 고려
    • CIoU : overlapping area, center distacne, the aspect ratio 모두 고려 (GOOD)
  3. Bag of specials
    • increase the inference cost 하는 방법들
    • enhance receptive field
      • SPP [25], ASPP(dilated ratio) [5] -> RFB(가장 종합적 이해와 낮은 Cost 좋은 성능 향상)[47]
    • attention module
      • channel-wise attention(channel 기준 pooling) and pointwise-wise attention(1x1xdepth의 cell 기준 pooling)
      • Squeeze-and-Excitation (SE) -> Spatial Attention Module (SAM=CBAM) (extra calculation 적음. GPU 연산 속도에 영향 없음)
    • feature integration
      • skip connection, hyper-column [22], FPN
      • 새로운 관점의 FPN : SFAM(SE module to execute channelwise level) [98] , ASFF(point-wise level reweighting) [48], and BiFPN(scale-wise level re-weighting and Adding feature maps of different scales) [77].
    • activation function
      • LReLU [54], PReLU [24] : zero gradient problem 해결
      • ReLU6 [28], Scaled Exponential Linear Unit (SELU) [35], hard-Swish [27]
      • Swish and Mish : continuously differentiable activation function.
    • post-processing
      • greedy(origin) NMS : optimizing & objective function 두개가 일관(일치)되게 만든다. by Confidence score
      • soft NMS : greedy NMS가 Confidence score의 저하 문제를 고려함
      • DIoU NMS : soft NMS에서 the center point distance개념을 추가
      • 하지만 anchor-free method 에서는 더 이상 post-processing을 필요로 하지 않는다.
    • Normalization
      • Batch Normalization에 대해서는 나중에 다시 진지하게 공부해 봐야겠다.
      • Batch Normalization (BN) [32], Cross-GPU Batch Normalization (CGBN or SyncBN) [93], Filter Response Normalization (FRN) [70], or Cross-Iteration Batch Normalization (CBN) [89]
    • Skip-connections
      • Residual connections, Weighted residual connections, Multi-input weighted residual connections, or Cross stage partial connections (CSP)

3. Methodology

  1. Backbone 선택
    • 아래의 조건을 만족하는 Cross-Stage-Partial-connections (CSP) (DenseNet의 경량화 버전) 과 DarkNet을 접목시켜서 사용. or CSPResNext50
    • Higher input Resolution For Small-objects
    • More Layers For Higher receptive field
    • More parameters For more accurate
  2. 많은 실험을 통한 Selection of BoF and BoS (주의할점 : 여기에서 좋은 결과를 내어야만 좋은 Method인 것은 아니다. 저자가 코드를 잘 못 이해하고 코드 적용이 잘못 됐을 수도 있는 거니까. By PPT발표자)
  3. Additional improvements
    1. data augmentation Mosaic : 4개의 이미지 합치기, batch normalization에 효과적
    2. CmBN collects statistics only between mini-batches within a single batch. Batch No
      image-20210208210015808
    3. SAM(CBAM) 그리고 PAN을 아래와 같이 수정했다. (그림만 나오지 구체적인 방법 없다.)
      • image-20210208210419416
  4. 최종적으로 YoloV4에서 사용한 방법론
    • image-20210208204847617
    • 시간이 날 때마다, 위의 방법론들에 대해서 찾아 공부하는 것도 좋을 것 같다.
  5. 실험결과는 윗 목차의 PPT 내용 참조

3. Tianxiaomo/pytorch-YOLOv4

  1. Github Link : Tianxiaomo/pytorch-YOLOv4 (중국어 Issue가 많아서 아쉬웠지만, 이거말고 1.1k star를 가지고 있는 YoloV4-pytorch repo도 대만사람이여서 그냥 둘다 비슷하다고 판단. 2.6k star인 이 repo보는게 낫다)
  2. ONNX : Open Neural Network Exchange
    • machine learning frameworks(Pytorch, Caffe, TF)들 사이의 Switching을 돕기 위해 만들어진 툴 by Facebook, Microsoft
    • onnx라는 파일 형식이 있다. Convert Pytorch into ONNX Tutorial
    • 그래서 아래와 같은 파일이, 이 깃허브 파일에 존재한다.
      • demo_pytorch2onnx.py : tool to convert into onnx
      • demo_darknet2onnx.py : tool to convert into onnx
  3. 이렇게 정리 되어 있어서 너무 좋다. 우리가 여기서 집중해야 할 파일은 models.py image-20210208143148246
  4. 2021.02.08 : ONNX와 YoloV4에 대한 코드 공부는 지금 당장 필요 없다. 위에서 사용된 Method들 중 모르는 것은 일단 논문을 읽어야 한다. 그리고 각 Method에 따른 코드를 Github에서 다시 찾던지, 혹은 이 YoloV4 repo에서 찾아서 공부하면 된다.

4. About YoloV5

  • YoloV5 Git issue : Where is paper? // The project should not be named yolov5
  • 위의 Issues를 읽어보면, 다음과 같은 것을 알 수 있다.
    1. 논문은 아직 나오지 않았다.
    2. yoloV5에 대한, 사람들의 불만이 있다. yoloV4에서 특별히 새로울게 없다.
  • 그럼에도 불구하고, YoloV5 github는 8500k의 star를 가지고 있다. YoloV4가 2600개의 star인것에 비해서.
  • 우선은 YoloV4 까지만 공부하자. 나중에 모델 사용에 있어서는 YoloV5를 사용하는게 맞는 듯 하다.
  • 어차피 YoloV4, YoloV5 모두, YoloV1,2,3의 저자인 Joseph Redmon에 의해서 만들어진 모델은 아니다.

【LightWeight】Understanding DenseNet, MobileNet V3 from youtube w/ advice

  • 논문1 : MobileNet V3 / Youtube Link1
  • 논문2 : DenseNet / Youtube Link2
  • 분류 : Light Weight
  • 공부 배경 : MobileNetV3 Paper 읽기 전 선행 공부로 youtube 발표 자료 보기
  • 선배님 조언:
    1. 삶의 벨런스? 석사 때는 그런거 없다. 주말? 무조건 나와야지. “가끔은 나도 쉬어야 돼. 그래야 효율도 올라가고…” 라고 생각하니까 쉬고 싶어지는 거다. 그렇게 하면, 아무것도 없이 후회하면서… 석사 졸업한다. “딱 2년만 죽었다고 생각하고 공부하자! 후회없도록! 논문도 1학년 여름방학 안에 하나 써보자!”
    2. 평일에는 1일 1페이퍼 정말 힘들다. 평일에는 개인 연구 시간 하루에 1시간도 찾기 힘들다. 그나마 주말에라도 해야한다. 지금이야 논문 읽고 배운 것을 정리하는게 전부지만, (1) 학교 수업 듣기 (2) 논문 읽기 (3) 코딩 공부 하기 (4) 코드 직접 수정하고 돌려보기 (5) 논문 쓰기. 까지 모두 모두 하려면 끝도 없다.
    3. 이번 여름방학 이전에, 아이디어 내고 코드 수정해서 결과 내보고 빠르게 제출하든 안하든 논문 한편 써보자.
    4. 1학기 초에 연구 주제 확정하자.
  • 목차
    1. (이전 Post) Inception Xception GoogleNet (바로가기)
    2. (이전 Post) MobileNet v1 (바로가기)
    3. (이전 Post) MobileNet v2 (바로가기)
    4. MobileNet V2 - Manifold of Interest , Linear Bottlenecks Code (바로가기)
    5. MobileNet V3 (바로가기)
    6. DenseNet (바로가기)
  • 강의 필기 PDF는 “OneDrive\21.겨울방학\RCV_lab\논문읽기”
  • <아래 이미지가 안보이면 이미지가 로딩중 입니다>

1. Linear Bottlenecks Code

  • 결국 Relu안하는 Convolution Layer이다. ㅅ… 욕이 나온네. “별것도 아닌거 말만 삐까번쩍하게 한다. 이게 정말 수학적으로 증명을 해서 뭘 알고 논문에서 어렵게 설명하는건지?, 혹은 그냥 그럴 것 같아서 실험을 몇번 해보니까 이게 성능이 좋아서 멋진 말로 끼워맞춘건지 모르겠다.

  • Github Link

    1. MobileNet V2 코드 - 파일이 1개 뿐이고 생각보다 엄청 쉽다. 이건 뭐 FPN 파일 하나 코드보다 훨씬 이해하기 쉽다.

    2. class InvertedResidual(nn.Module):
          def __init__(self, inp, oup, stride, expand_ratio):
              super(InvertedResidual, self).__init__()
              self.stride = stride
              assert stride in [1, 2]
           
              hidden_dim = int(inp * expand_ratio)
              self.use_res_connect = self.stride == 1 and inp == oup
           
              if expand_ratio == 1:
                  self.conv = nn.Sequential(
                      # dw
                      nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # pw-linear ***** 이거가 Linear Bottlenecks *****
                      nn.Conv2d(hidden_dim, oup, kernel_size=1, stride=1, padding=0, bias=False),
                      nn.BatchNorm2d(oup),
                  )
              else:
                  self.conv = nn.Sequential(
                      # pw
                      nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # dw
                      nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # pw-linear ***** 이거가 Linear Bottlenecks *****
                      nn.Conv2d(hidden_dim, oup, kernel_size=1, stride=1, padding=0, bias=False),
                      nn.BatchNorm2d(oup),
                  )
      
  • Manifold 학습 이란

    1. 매니폴드 학습이란, <그림 1>과 같은 형태로 수집된 정보로부터 <그림 2>와 같이 바르고 곧은 유클리디안 공간을 찾아내는 것을 말합니다.
    2. 아래의 그림처럼, 100차원 vector들이 100차원 공간상에 놓여있다. 하지만 유심히 보면, 결국 백터들은 2차원 평면(왼쪽 그림) 혹은 3차원 공간(오른쪼 그림) 으로 이동 시킬 수 있다. 즉 100차원 공간이라고 보여도 사실은 2차원 3차원으로 더 잘 표현할 수 있는 백터 이었다는 것이다.
    3. 이렇게 높은 차원의 백터을, 낮은 차원의 직관적이고 곧은 공간으로 이동시킬 수 있게 신경망과 신경망의 파라메터를 이용한다.
    4. image-20210207134456533
  • Manifold 란?

    1. image-20210207134724874
    2. 스위스롤(왼쪽그림)을 우리가 보면 3차원이지만, 그 위에 올라가 있는 개미가 느끼기엔 2차원이다.
    3. 매니폴드 학습이란 ‘눈을 감고(학습이되지 않은 상태에서) 비유클리디안 형태를 만져가며(데이터를 이용해) 모양을 이해해(모델을 학습해) 나가는 것이다’. 즉, 스위스롤을 2차원 평면으로 피는 과정이다.
    4. 오른쪽 그림과 같이 2차원 데이터를, 1차원으로 필 수 있다면 데이터와의 유사도 측정등에 매우 좋을 것이다.
    5. 혹은 차원을 늘리기도 한다. 예를 들어 오른쪽 그림의 실을 잡고 들어올리는 행위가, 차원을 늘리는 행위이고, 그것은 신경망의 Layer를 추가하는 행위라고도 할 수 있다.
  • Manifold of Interest 위의 내용까지 간략히 요약 정리!

    1. 실용적으로 말해서! “conv혹은 fc를 통과하고 activation function을 통과하고 나온 (Subset) Feature가 Manifold 이다!” 그리고 “그 Manifold 중에 우리가 관심있어하는 부분, 가장 많은 이미지의 정보를 representation하는 일부를 논문에서는 Manifold of interest 라고 한다.”
  • Linear Bottlenecks

    1. image-20210207135326788
    2. 논문 설명 + 나의 이해 : Input data = x 가 맨 왼쪽과 같이 표현 된다고 하자. 그리고 Activation_Function( T * x) 를 수행한다. 여기서 T는 Input data의 차원을 위 사진의 숫자와 같이 2,3,5,15,30 차원으로 늘려주는 FC Layer라고 생각하자.
    3. 결과를 살펴보면, 낮은 차원으로 Enbeding하는 작업은, 특히 (비선형성 발생하게 만드는) Relu에 의해서 (low-dimensional subspace = 윗 이미지 그림을 살펴 보면) 정보의 손실이 많이 일어난다. 하지만 고차원으로의 Enbeding은 Relu에 의해서도 정보의 손실이 그리 많이 일어나지 않는다.
    4. 솔직히 논문이나 PPT내용이 무슨소리 하는지는 모르겠다.
    5. 결국에는 위와 같은 “정보 손실”을 줄이기 위해서, 비선형이 Relu를 쓰지 않고 Linear Function을 쓰겠다는 것이다.

<아래 이미지가 안보이면 이미지가 로딩중 입니다>

2. MobileNet V3

  • 참고하면 좋은 블로그 (1). Blog1 (2). Blog2
  • AutoML-and-Lightweight-Models
    • 1.) Neural Architecture Search - Reinforcement 개념이 들어간다.
    • 2.) Lightweight Structures
    • 3.) Model Compression, Quantization and Acceleration
    • 4.) Hyperparameter Optimization
    • 5.) Automated Feature Engineering.
  • 위의 개념이 많이 들어가기 시작해서 사실 들으면서, 거의 이해가 안됐다. 따라서 Lightweigh-Model 주제로 연구를 하게 된다면 그때 이해해야 겠다.
  • 하지만.. 연구실 선배님들의 연구 주제와 비슷하게 가져가는게 낫기 때문에, 이 분야는 깊게 고민해보자.

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

3. DenseNet

  • AlexNet, ZFNet(필터 사이즈 및 갯수 등 하이퍼파라미터의 중요성 부각)

  • VGG : Small Filters, Deeper networks -> 3X3 여러개를 사용하는 것의 파라메터 갯수 관점에서 더 효율적.

  • Inception = GoogleNet : FC Layer를 줄이기 위해 노력. 다양한 conv를 적용하고 나중에 Concat. 이때 큰 Filter size conv를 하기 전에 1x1으로 channel reduction (= BottleNet Layer)을 해준다.

  • ResNet : Residual Connnetion(=Skip Connection + Element-wise addition). Layer가 깊다고 무조건 좋은게 아니었다. Gradient Vanishing문제! -> ResNeXt = ResNet + Inception
    image-20210207200428536

  • ResNet의 Improving 형태 -> Srochastic Depth : 오른쪽 그림의 회색과 같이, 랜덤하게 일부 Layer를 끄고 학습일 시킨다. 더 좋은 결과가 나오더라
    image-20210207200451130

  • Densely Connected Convolutional Networks

    • ResNet 처럼 다음단만 연결하지 말고, 모조리 다 연결해보자.

    • Element-wise addition 하지 말고, Channel-wise Concatenation 하자!

    • Dense And Slim하다! 왜냐면 Channel을 크게 가져갈 필요없기 때문이다. Layer를 통과할 때마다 k(=12)개씩 Channel 수가 증가하도록만 만들어도 충분히 학습이 잘 되니까.

    • image-20210207200909357

    • 또는 아래와 같이 BottleNetck Layer를 사용하면 아래와 같다.
      image-20210207201255358

    • 위의 모든 연산을, 하나의 Layer를 통과한 것으로 본다면, 모든 연산후에는 항상 k개의 channel이 생기게 만든다. (어차피 나중에 (l = 이전에 통과한 Layer 갯수) l x k 개의 Channel과 합쳐야 하므로 새로 생긴 k가 너무 크지 않도록 만든다. 여기서 k는 12를 사용했다고 함)

    • 위의 작업들을 모듈화로 하여, 여러번 반복함으로써 다음과 같은 전체 그림을 만들 수 있다. 논문에서는 일반적으로 DenseBlock을 3개 정도 사용하였다.
      image-20210207201616537

    • 장점

      1. 학습이 잘된다. Error Signal의 전달 = Backpropa가 잘된다.
      2. 기존의 것들은 중간 Layer의 Channel의 size가 매우 커야 학습이 잘 됐는데, 우리의 Channel은 작은값 k를 이용해서 최대 lxk개의 Channel만을 가지도록 만들었다.
      3. 그마큼 사용되는 # parameters 또한 줄어진다. O(C*C(중간 Layer의 channel 갯수)) » O(L*k*k)
      4. 아래의 그림처럼 모든 Layer의 Feature들을 사용한다. 아래 그림의 ‘별’은 Complex정도를 의미한다. 원래 다른 network는 Classifier에서 가장 마지막 별5개짜리 Layer만을 이용한다. 하지만 우리의 Classifier는 지금까지의 모든 Layer결과를 한꺼번에 이용한다. 따라서 굉장히 효율성이 좋다.
        image-20210207202130406
    • 결과

      • image-20210207202525782
    • 논문에 없는 추가 내용

      • image-20210207202600943
      • Easy Example은 앞의 Classifier1에서 처리하고, Hard Example은 뒤의 Classifier3에서 처리하도록 만들면, 더 빠른 예측이 가능하다. 그니까.. Classifier1에서 일정 이상의 값이 나온 것은 예측값 그대로 결과에 사용하고 거기서 Stop.(빨리 끝. 전체 평균 처리 속도 상승) 반대로 모든 클래스에서 일정 threshold값 이상이 나오지 않는다면, 다음 Classifier에서 분류를 다시 해보는 작업을 수행한다.
      • 전체 수식 정리
        image-20210207203000407

【LightWeight】Understanding Xception, MobileNet V1,V2 from youtube w/ advice

  • 논문1 : MobileNet V1 paper link / Youtube Link1
  • 논문2 : MobileNet V2 paper link / Youtube Link2
  • 논문2 : Xception YoutubeLink
  • 분류 : LightWeight
  • 공부 배경 : MobileNetV3 Paper 읽기 전 선행 공부로 youtube 발표 자료 보기
  • 선배님 조언:
    1. Experiment와 Result 그리고 Ablation는 구체적으로 보시나요? 핵심 부분을 읽다가, 핵심이 되는 부분을 캐치하고 이것에 대해서 호기심이 생기거나, 혹은 이게 정말 성능이 좋은가? 에 대한 지표로 확인하기 위해서 본다. 따라서 필요거나 궁금하면 집중해서 보면 되고 그리 중요하지 않은 것은 넘기면 된다. 만약 핵심 Key Idea가 Experiment, Result, Ablation에 충분히 설명되지 않는다면 그건 그리 좋지 않은 아이디어 혹은 논문이라고 판단할 수 있다.
    2. 공부와 삶의 균형이 필요하다. 여유시간이 나서 유투브를 보더라도 감사하고 편하게 보고 쉴줄 알아야 하고, 공부할 때는 자기의 연구분야에 대한 흥미를 가지는 것도 매우 중요하다. 또한 취미나 릴렉스할 것을 가지고 가끔 열심히 공부하고 연구했던 자신에게 보상의 의미로 그것들을 한번씩 하는 시간을 가지는 것도 중요하다.
    3. 여러 선배들과 소통하고, 완벽하게 만들어가지 않더라도 나의 아이디어로 무언가를 간단하게 만들어 보고 제안해 보는것도 매우 중요하다. 예를 들어서, “나에게 이런 아이디어가 있으니, 이 분야 논문을 더 읽어보고 코드도 만들어보고 연구도 해보고 비교도 해보고 실험도 많이 해보고, 다~~ 해보고 나서 당당하게! ㅇㅇ선배님께 조언을 구해봐야겠다!” 라는 태도 보다는 “나에게 이런 아이디어가 있고… 논문 4개만 더 읽고 대충 나의 아이디어를 PPT로 만들어서 ㅇㅇ선배님께 보여드려보자! 그럼 뭐 좋은건 좋다고 고칠건 고치라고 해주시겠지…! 완벽하진 않더라도 조금 실망하실지라도 조금 철면피 깔고 부딪혀 보자!!” 라는 마인드.
    4. 논문. 미리미리 써보고 도전하자. 어차피 안하면 후회한다. 부족한 실력이라고 생각하지 말아라. 어려운 거라고 생각하지 말아라. 일단 대가리 박치기 해봐라. 할 수 있다. 목표를 잡고 도전해보자.
  • 느낀점 : 말만 삐까번쩍, 번지르르 하게 해놓은 글이 너무 많다. 사실 몇개 대충 실험해보고 성능 잘나오니까.. 이거를 말로 포장을 해야해서 뭔가 있어보이게 수학적으로 마치 증명한것 마냥 이야기하는 내용이 머신러닝 논문에 너무 많다. 정말 유용한 지식만 걸러서 듣자. Experiment, Result, Ablation 를 통해서 증거를 꼭 찾아보자.
  • 목차
    1. Inception Xception GoogleNet (바로가기)
    2. MobileNet v1 (바로가기)
    3. MobileNet v2 (바로가기)
    4. (다음 Post) MobileNet V2 - Manifold of Interest , Linear Bottlenecks Code (바로가기)
    5. (다음 Post) MobileNet V3 (바로가기)
    6. (다음 Post) DenseNet (바로가기)
  • 강의 필기 PDF는 “OneDrive\21.겨울방학\RCV_lab\논문읽기”

  • <아래 이미지가 안보이면 이미지가 로딩중 입니다>

1. Inception Xception GoogleNet

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

2. MobileNetV1

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

3. MobileNetV2

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

4. Linear Bottlenecks Code

  • 결국 Relu안하는 Convolution Layer이다. ㅅ… 욕이 나온네. “별것도 아닌거 말만 삐까번쩍하게 한다. 이게 정말 수학적으로 증명을 해서 뭘 알고 논문에서 어렵게 설명하는건지?, 혹은 그냥 그럴 것 같아서 실험을 몇번 해보니까 이게 성능이 좋아서 멋진 말로 끼워맞춘건지 모르겠다.

  • Github Link

    1. MobileNet V2 코드 - 파일이 1개 뿐이고 생각보다 엄청 쉽다. 이건 뭐 FPN 파일 하나 코드보다 훨씬 이해하기 쉽다.

    2. class InvertedResidual(nn.Module):
          def __init__(self, inp, oup, stride, expand_ratio):
              super(InvertedResidual, self).__init__()
              self.stride = stride
              assert stride in [1, 2]
           
              hidden_dim = int(inp * expand_ratio)
              self.use_res_connect = self.stride == 1 and inp == oup
           
              if expand_ratio == 1:
                  self.conv = nn.Sequential(
                      # dw
                      nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # pw-linear ***** 이거가 Linear Bottlenecks *****
                      nn.Conv2d(hidden_dim, oup, kernel_size=1, stride=1, padding=0, bias=False),
                      nn.BatchNorm2d(oup),
                  )
              else:
                  self.conv = nn.Sequential(
                      # pw
                      nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # dw
                      nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
                      nn.BatchNorm2d(hidden_dim),
                      nn.ReLU6(inplace=True),
                      # pw-linear ***** 이거가 Linear Bottlenecks *****
                      nn.Conv2d(hidden_dim, oup, kernel_size=1, stride=1, padding=0, bias=False),
                      nn.BatchNorm2d(oup),
                  )
      
  • Manifold 학습 이란

    1. 매니폴드 학습이란, <그림 1>과 같은 형태로 수집된 정보로부터 <그림 2>와 같이 바르고 곧은 유클리디안 공간을 찾아내는 것을 말합니다.
    2. 아래의 그림처럼, 100차원 vector들이 100차원 공간상에 놓여있다. 하지만 유심히 보면, 결국 백터들은 2차원 평면(왼쪽 그림) 혹은 3차원 공간(오른쪼 그림) 으로 이동 시킬 수 있다. 즉 100차원 공간이라고 보여도 사실은 2차원 3차원으로 더 잘 표현할 수 있는 백터 이었다는 것이다.
    3. 이렇게 높은 차원의 백터을, 낮은 차원의 직관적이고 곧은 공간으로 이동시킬 수 있게 신경망과 신경망의 파라메터를 이용한다.
    4. image-20210207134456533
  • Manifold 란?

    1. image-20210207134724874
    2. 스위스롤(왼쪽그림)을 우리가 보면 3차원이지만, 그 위에 올라가 있는 개미가 느끼기엔 2차원이다.
    3. 매니폴드 학습이란 ‘눈을 감고(학습이되지 않은 상태에서) 비유클리디안 형태를 만져가며(데이터를 이용해) 모양을 이해해(모델을 학습해) 나가는 것이다’. 즉, 스위스롤을 2차원 평면으로 피는 과정이다.
    4. 오른쪽 그림과 같이 2차원 데이터를, 1차원으로 필 수 있다면 데이터와의 유사도 측정등에 매우 좋을 것이다.
    5. 혹은 차원을 늘리기도 한다. 예를 들어 오른쪽 그림의 실을 잡고 들어올리는 행위가, 차원을 늘리는 행위이고, 그것은 신경망의 Layer를 추가하는 행위라고도 할 수 있다.
  • Manifold of Interest 위의 내용까지 간략히 요약 정리!

    1. 실용적으로 말해서! “conv혹은 fc를 통과하고 activation function을 통과하고 나온 (Subset) Feature가 Manifold 이다!” 그리고 “그 Manifold 중에 우리가 관심있어하는 부분, 가장 많은 이미지의 정보를 representation하는 일부를 논문에서는 Manifold of interest 라고 한다.”
  • Linear Bottlenecks

    1. image-20210207135326788
    2. 논문 설명 + 나의 이해 : Input data = x 가 맨 왼쪽과 같이 표현 된다고 하자. 그리고 Activation_Function( T * x) 를 수행한다. 여기서 T는 Input data의 차원을 위 사진의 숫자와 같이 2,3,5,15,30 차원으로 늘려주는 FC Layer라고 생각하자.
    3. 결과를 살펴보면, 낮은 차원으로 Enbeding하는 작업은, 특히 (비선형성 발생하게 만드는) Relu에 의해서 (low-dimensional subspace = 윗 이미지 그림을 살펴 보면) 정보의 손실이 많이 일어난다. 하지만 고차원으로의 Enbeding은 Relu에 의해서도 정보의 손실이 그리 많이 일어나지 않는다.
    4. 솔직히 논문이나 PPT내용이 무슨소리 하는지는 모르겠다.
    5. 결국에는 위와 같은 “정보 손실”을 줄이기 위해서, 비선형이 Relu를 쓰지 않고 Linear Function을 쓰겠다는 것이다.

【Detection】Understanding M2Det paper w/ code, my advice

  • 논문 : M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network

  • 분류 : Object Detection

  • 저자 : Qijie Zhao , Tao Sheng , Yongtao Wang∗ , Zhi Tang

  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.

  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.

  • 느낀점 :

    • 최근 논문을 많이 읽어서 느끼는 점은, 각 논문은 특별한 목표가 1,2개 있다. (예를 들어 Cascade는 close false positive 객체를 줄이기 위함이 목표이고, FPN는 Multi-scale object detect를 목적으로 한다.) 그리고 그 목표 달성을 위해, 이전 신경망들의 정확한 문제점을 파악한다. 그 문제점을 해결하기 위해 새로운 아이디어를 첨가한다. Cascade에서 배운 것 처럼, 복잡한 아이디어를 마구 넣는다고 성능이 좋아지지 않는다. 핵심은 목표를 확실히 잡고, 문제점을 확실히 분석하고, 그것을 해결하기 위해 아이디어를 넣어보는 일렬이 과정이 정말 중요한 것 같다.
    • 가장 이해하기 쉽게 씌여져 있는 논문 같다. 문법이나 용어가 쉽고, 같은 단어가 많이 반복되서 나에게는 너무 편했다. 또한 그림도 이미 완벽해서 더이상 다른 논문 글로 이해할 필요가 없었다. 이런 논문이 Top-Conference논문이 아니라, AAAI 논문이라는게 조금 아쉽다.

1. M2Det Paper Review

1. Conclusoin

  • Multi-Level Feature Pyramid Network (MLFPN) for different scales
  • New modules
    1. Multi-lebel features by Feature Fusion Module (FFM v1)
    2. Thinned U-shape Modules (TUMs) + Fature Fusion Modules (FFM v2s)
    3. multi-level multi-scale features (= 즉! the decoder layers of each TUM)
    4. multi-level multi-scale features With the same scale (size) by a Scale-wise Feature Aggregation Module (SFAM)
    5. SOTA Among the one-stage detectors on MS-COCO

2. Abstract, Introduction

  • Scale-variation problem -> FPN for originally classification tast
  • MLFPN construct more effective feature pyramids then FPN for Objec Detection tast

3.Introduction

  • conventional method for Scale variation
    1. image pyramid at only testing time -> memory, computational complexity 증가
    2. feature pyramid at both training and testing phases
  • SSD, FPN 등등은 for originally classification(backbone이니까) tast -> 한계가 존재한다.
    1. 그냥 backbone 중간에서 나온 형태 이용 - 정보 불충분 - object detection 하기 위해 정보 불충분
    2. FPN의 p1, p2, p3는 Single-Level Feature 이다. 우리 처럼 Multi-Level Feature Pyramid가 아니다.
    3. Low level feature -> simple appearances // high-level feature -> complex appearances. 유사한 scale의 객체는 complex appearances로써 구별되어야 하는데, Single-Level Feature로는 충분하지 않다.
    4. Related Work : Faster R-CNN, MS-CNN, SSD, FPN, DSSD, YOLOv3, RetinaNet, RefineDet
    5. image-20210205154750949
  • 우리의 진짜 목적은 effective feature pyramid for detecting objects of different scales 이다.
    • 우리 모델은 위의 한계를 해결한다. 어차피 뒤에 똑같은 내용 또 나올 듯.

4. Proposed Method

  • 꼭 아래의 그림을 새탭으로 열어서 이미지를 확대해서 볼 것. 논문에 있는 내용 중 중요한 내용은 모두 담았다. 정성스럽게 그림에 그리고 필기해놨으니, 정성스럽게 참고하고 공부하기.

image-20210205165329776

image-20210205165329777

  • MLFPN 내용 추가
    • FFMv1 : VGG에서 나오는 2개의 semantic Feature map 융합. FPN은 여기서 low feature map data를 사용하는데, 이건 충분한 정보가 아니다. 그 feature map은 classification을 위한 feature이지, object detection을 위한 feature이 아니다.
    • TUM : several feature maps 생성
      • first TUM : learn from X_base only. AND second … third.. 8th.
      • image-20210205165329775
      • L = # Levels, (=8) = # TUM. 어찌보면 여기가 진짜 FPN와 유사한 작업이 수행된다.
      • 마지막에 1x1 conv를 수행해서, smoothness를 추가한다.
  • SFAM
    • Channel-wise Attention Module (Hu, Shen, and Sun 2017)
      • In order to Encourage features to focus on channels (that they benefit most) - 가장 중요한 channel에 집중!
      • global average pooling 그리고 excitation step(2개의 nn.Linear Layer)
  • Network Configurations
    • To reduce the number of parameters, FFMv2를 통과하고 나오는 Channel을 256으로 설정했다. 이 덕분에 GPU로 학습하기 쉬워졌다.
    • Original input size는 320, 512, 800 을 받을 수 있게 설정하였다.
  • Detection Stage
    • 6 scale 즉 Multi-Level Feature Pyramid에서, 2개의 Convolution layer를 통과시켜서, location regression and classification 정보를 얻어 내었다.
    • default(anchor) boxes 설정 방법은 SSD를 따랐다. (2개 size + 3개 ratios = 6 Anchor).
    • 코드에 의하면, 마지막에 objectness score같은거 사용 안함. 딱 4 * 6 + self.num_classes * 6 값만 나옴.
    • Anchor 중에서 (objectness score) 0.05이하의 anchor들은 low score로써 Filter out 시켜버렸다. (아에 Backgound라고 판단하여 이 Anchor로는 학 및 추론에 사용을 안해버리는 방법. 이 작업만으로도 많은 Negative Anchor들을 필터링 할 수 있다고 함.)
    • 근데.. 코드를 봤는데 위와 같이 objectness score와 같은 것도 없다. 이상하다. Detect최종 결과에는 위의 (4+#class) x 6 개의 정보 밖에 없다. 그리고 0.05를 기준으로 특별하게 하는 작업도 없다. 0.05를 github repository에서 검색해보면 아무 정보도 없다. 대신 Negative Mining을 적극적으로 사용한다.
    • 0.01까지 낮춰 보았지만, 너무 많은 detection results발생으로, inference time에 영향을 크게 주어서 0.05를 사용하였다.
    • 그리고 Input size가 800x800이면, scale ranges를 6에서 조금 더 늘렸다.
    • 더 정확하게 BB를 남기기 위해서, soft-NMS (Bodla et al. 2017) 를 사용했다.

5. Experiments

  • Implementation details
    • 5 epoch -> learning rate : 2 × 10^−3
    • 2 × 10−4 and 2 × 10−5 까지 감소 그리고 150 epochs에서 stop
    • Image 320, 512 size -> Titan X GPUs / Image 800 size -> NVIDIA Tesla V100
    • batch size : 32
    • VGG-16 backbone 5일 학습, ResNet-101 backbone 6일 학습
  • Comparison with State-of-the-art
    • image-20210205192721973
    • 성능 비교 표를 보면 확실히 성능은 좋다. 특히나 Small object에 대해서 아주 성능이 좋은 것을 알 수 있다. 다만.. FPS가 좀 떨어진다. 320에서 30, 512에서 15, 800에서 10정도 나온다.
    • 특히나 Multi Scale test를 사용하면 훨씬 좋은 성능이 나오는 것을 확인할 수 있었다.
    • M2Det가 매우 깊은 depth때문에 좋은 성능이 나오는 것만은 아니라고 한다. 파라미터수를 비교해보면 M2Det 800은 147M이다. ResNetXt-101-32x8d-FPN은 205M, Mask R-CNN은 s 201M parameters인 것과 비교해보면 파라메터 수는 적당하다고 한다.
  • Ablation study
    • image-20210205193004588
  • Speed
    • VGG16- reduced 사용. better speed-accuracy.
    • image-20210205193928225
  • Discussion
    • 우리꺼 좋다ㅇㅇ. 라고 말하는 중.

2. qijiezhao/M2Det

  1. Github Link : qijiezhao/M2Det - 저자가 직접 pytorch사용해서 모델 구현

  2. 논문의 내용이 충분히 자세했기 때문에… 논문 이해가 잘 안되서 코드에서 찾아보고 싶은 부분이 없다. 위의 논문 내용을 어떻게 구현했는지 코드구현 공부로써는 엄청 좋을 것 같다. torch를 공부하는 개념으로…

  3. 적당한 모듈화가 아주 잘 되어 있다.

  4. M2Det/configs/CC.py : config 파일 제작 클래스를 아주 간단하게 직접 제작

    class ConfigDict(Dict):
        def __setattr__(self, name, value):
            if isinstance(value, dict):
                value = ConfigDict(value)
            self._cfg_dict.__setattr__(name, value)
               
            # 이런 함수도 직접 제작함 따라서
            # setattr(self, key, value) 이런식의 함수 사용도 가능.
    
  5. M2Det/m2det.py : 신경망 구현의 핵심 틀이 다 들어 있음.

    """
    from layers.nn_utils import * 에 TUM, SFAM와 같은 핵심 모듈이 구현되어 있있음
    여기서 함수를 그대로 가져와서 모델 구현에 사용
    """
    class M2Det(nn.Module):
           
    def build_net(phase='train', size=320, config = None):
    	return M2Det(phase, size, config)
    
  6. M2Det/layers/modules/multibox_loss.p

    class MultiBoxLoss(nn.Module):
        """
    	1. (default threshold: 0.5) 로써 IOU 0.5이상의 BB만을 
        Positive로 판단. 나머지는 다 Negative .
        2. Hard negative mining to filter the excessive number of negative examples
        """
    
  7. negative mining은 어떻게 구현 및 사용한건지는 다음에 필요하면 찾아보자. layers/modules/multibox_loss.py#L94

    class MultiBoxLoss(nn.Module):
        """SSD Weighted Loss Function
        Compute Targets:
            1) Produce Confidence Target Indices by matching  ground truth boxes
               with (default) 'priorboxes' that have jaccard index > threshold parameter
               (default threshold: 0.5).
            2) Produce localization target by 'encoding' variance into offsets of ground
               truth boxes and their matched  'priorboxes'.
            3) Hard negative mining to filter the excessive number of negative examples
               that comes with using a large number of default bounding boxes.
               (default negative:positive ratio 3:1)
         """
    	# Hard Negative Mining
        loss_c[pos.view(-1,1)] = 0 # filter out pos boxes for now
        loss_c = loss_c.view(num, -1)
        _,loss_idx = loss_c.sort(1, descending=True)
        _,idx_rank = loss_idx.sort(1)
        num_pos = pos.long().sum(1,keepdim=True)
        num_neg = torch.clamp(self.negpos_ratio*num_pos, max=pos.size(1)-1)
        neg = idx_rank < num_neg.expand_as(idx_rank)
           
    # MultiBoxLoss 를 reference하는 코드 부분    
    # M2Det/utils/core.py
    def set_criterion(cfg):
        return MultiBoxLoss(cfg.model.m2det_config.num_classes,
                            overlap_thresh = cfg.loss.overlap_thresh,
                            prior_for_matching = cfg.loss.prior_for_matching,
                            bkg_label = cfg.loss.bkg_label,
                            neg_mining = cfg.loss.neg_mining,
                            neg_pos = cfg.loss.neg_pos,
                            neg_overlap = cfg.loss.neg_overlap,
                            encode_target = cfg.loss.encode_target)
    

【Detection】Understanding Cascade R-CNN paper with code

  • 논문 : Cascade R-CNN: Delving into High Quality Object Detection

  • 분류 : Object Detection

  • 저자 : Zhaowei Cai, Nuno Vasconcelos

  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.

  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.

  • 느낀점 :

    • 최근 논문일수록, 블로그나 동영상의 내용 정리가 두리뭉실하고 이해하기 힘들다. 디테일성은 거의 없다. 따라서 그냥 논문 읽는게 최고다. 만약 블로그에 내용 정리가 잘 되어 있다고 하더라도, 내가 블로그 내용에 대한 신뢰가 안가서, 합리적 추론의 이해(덜 디테일한 설명은 나의 생각을 좀 더 추가해서 이해하는 과정)을 할 수도 없다. 따라서 논문이나 읽자. 시간 낭비하지 말고.
    • SSD 코드를 공부했을때 모듈화가 심각해서 보기가 힘들었다. 하지만 그것은 “처음부터 끝까지 다 봐야지.” 라는 욕심때문에 보기 힘들었던 것 같다. 하지만 사실 그렇게 코드를 보는 경우는 드믄것 같다. “내가 궁금한 부분만 찾아보거나, 내가 사용하고 싶은 모듈만 찾아서 사용한다.”라는 마음으로 부분 부분 코드를 본다면, 내가 원하는 부분을 전체 코드에서 찾는 것은 그리 어렵지 않다. 라는 것을 오늘 느꼈다.

1. Cascade R-CNN

1-(1). 참고 자료

  1. (1) Cascade R-CNN 블로그, (2) Cascade R-CNN Youtub동영상1

  2. 참고 자료 소감 :

    • 블로그 : 너무 result 해석에 많은 초점을 둔다. 방법론에 대해서는 구체적이지는 않아, 나에게는 이해가 어려웠다. 논문이나 읽자.
    • 동영상 : 핵심이 Casecade-Mask RCNN이다. 디테일이 거의 없다. 안봄.
  3. 참고자료 내용 정리 :

    1. 이 논몬은 object detector의 약점을 잘 파악했다. 이 논문을 통해, 아주 복잡한 방법을 적용해서 성능 향상을 미약하게 이루는 것 보다는, 문제점을 잘 파악하기만 하면 어렵지 않게 성능을 향상시킬 수 있음을 보여준다.

    2. 문제점 파악하기

      1. Introduction에 실험 그래프가 나온다. 블로그 글은 이해 안되서, 논문 읽는게 낫겠다.

        image-20210204160324773

    3. Cascade R-CNN은 위 사진의 오른쪽 그림의 구조이다. 굳이 설명하지 않겠다. 특히 단계를 거듭할 수록 보다 더 높은 IOU를 기준으로 학습시킨다.

    • 과거 방식 (1) 단순하게 하나의(같은) classifier를 Iterative하게 사용하는 것은 큰 성능 향상을 주지 못한다. (2) 서로 다른 classifier를 여러개 만들고, 각각의 IOU기준을 다르게 주고 학습을 시키는 방법도 성능 향상은 그저 크지 않다. 즉 여러 classifier의 ensenble 방법이다.
    • Cascade R-CNN은 각각의 classifier는 각각 Threshold 0.5, 0.6, 0.7 로 학습. 예측 bounding box와 GT-box가 겹치는 정도가 Threshold 이상이여야지만, 옳게 예측한 것이라고 인정해줌. 이하라면 regressing 틀린거로 간주하고 loss를 준다.

1-(2). Paper Review

  1. Conclustion
    • multi-stage object detection framework (=extension)
    • overfitting, mismatch at inference 문제점 해결
  2. 기본 이론
    • Bounding Box와 GT-box와의 IOU threshold보다…
      • 크면 Positive Bounding box(당당하게 이건 객체다! 라고 말하는 예측 BB값),
      • 작으면 Negative(Bounding Box이긴 하지만, 아무래도 이건 객체는.. 아니다. 라고 말하는 예측 BB값)
      • 여기서 P, N이, [TP FP TN FN]에서 P, N 이다.
  3. abstract, Introduction
    • 현재 문제점들
      • close false positives = “close but not correct 거의 맞췄지만.. 아니야” bounding boxes 가 많기 때문에 더욱 어려운 문제이다.
      • 통상적으로 우리는 IOU threshold = 0.5 를 사용합니다. 하지만 이것은 a loose requirement for positives (약간은 느슨한,쉬운 요구조건) 입니다. 따라서 detector는 자주 noise bounding box를 만들어 낸다. 이것 때문에 우리는 항상 reject close false positives 에 어려움을 더 격고 있다.
      • 즉. 아래의 그림과 같이, u=0.5일 때.. Detected bounding box에 대해서 너무 약한 threshold를 주기 때문에 아래와 같은 noise스러운 박스들이 많이 추출 된다.
        image-20210204172936186
    • 분석해보기
      • image-20210204173847031
      • 그림(c) : X : Input Proposal(RPN에서 나오는 BB와 GT), Y : detection performance(Classifier에서 오는 BB와 GT) u=0.7에서는 일정 이상의 X에서만 높은 Y값이 나온다.
      • 그림(d) : u=0.5로 했을때(0.5이상은 모두 객체로 탐지. 모든 Positive들), Threshold(이 이상만 TP로 판단. 이 이외는 FP)가 어떤 때든 상대적으로 좋은 AP가 도출 된다.
      • ( 일반적으로 이렇게 하나의 IOU값으로 최적화된 모델(Detector)은 다른 IOU threshold에서도 최적화된 값(Hypotheses=예측/추론값)이 나오기 힘들다. )
      • 그렇다고 u를 그냥 높게 하는 건 좋지 않다. (d)에서 보이는 결과도 그렇고 Overfitting이 발생하는 경향도 있다. 또한 (c)에서 처럼 u=0.7에서는 일정 이상의 X에서만 높은 Y값이 나온다. 일정 이하는 그리.. 최적화된 신경망이 만들어 진다고 볼 수 없다.
      • 이 논문의 저자는 생각했다. bounding box regressor를 0.5 ~ 0.6 ~ 0.7 의 u로 키워가며 stage를 거치게 하는 것은 (c)에서, 낮은 X에서는 파랑Line을, 중간 X에서는 초록Line을, 높은 X에서는 빨간Line이상의 값을 OutputIOU로 가지게 함으로써 적어도 회색 대각선보다는 높은 곳에 점이 찍히게 하는 것을 목표로 한다.
    • 우리의 방법
      • 나만의 직관적 이해 : ⭐⭐
        1. 만약 RPN에서 나온 BB와 GT간의 IOU가 0.55이고, Classifier에서 나온 BB와 GT간의 IOU가 0.58라고 해보자.(class는 맞았다고 가정)
        2. 만약 Threshold=0.6이라면, (클래스는 맞았음에도 불구하고 BB위치가 틀렸기 때문에) 이것은 FP라고 처리 된다.
        3. 이것이야 말로 close false positives 이다.
        4. 하지만 아까 0.58의 BB정보를 sequentially하게 옆의 Classifier에 넘겨주고 이 Classifier에서 나오는 BB와 GT간의 IOU가 0.61이 된다면!
        5. 이것은 완벽히 close false positives에 대한 문제를 해결해준 것이라고 할 수 있다.
      • Cascade R-CNN does not aim to mine hard negatives.(즉 클래스에 관점에서 AP를 높히는 것이 아니다.) Instead, by adjusting bounding boxes(Regressing 관점에서 AP를 높이려는 목표를 가진다.)
  4. Related Work, Object Detection
    1. Offset Relative 공식 :
      image-20210204220629271
    2. image-20210204220646554
    3. Figure 3 (b) : same classifier / 모두 u = 0.5 / 따라서 위의 그래프 (c)에서 보는 것처럼 u=0.5이고 X가 일정 이상일때 오히려 Y값이 더 낮아지는 현상을 간과 했다. / 또한 위 그림의 Figure2에서 보는 것처럼, (blue dot) 첫번째 stage에서 BB의 offset Relative로 인해 refine이 이뤄지지만, 두, 세번째 stage에서는 분산 값이 좁게 변한다. 초기에 이미 Optimal이라고 판단하는 듯 하다 /
    4. Detection Quality
      • image-20210204222136796
    5. Figure3-(c) Integral Loss
      • U = {0.5, 0.55, ⋅⋅⋅ , 0.75}를 가지는 Classifier들을 모두 모두 모아서 Ensemble을 수생한다.
      • 많은 Classifier가 있으므로, 이들에 대한 모든 Classifier Loss는 아래와 같다.
      • image-20210204222421487
      • 아래 Figure4의 첫번째 그래프를 보더라도, 0.7이상의 IOU를 가지는 BB는 2.9프로 밖에 안된다. 이래서 좋은 U를 가지는 Classifier는 빨리 Overfitting이 되버린다. 따라서 이러한 방법으로 close false positives문제가 해결되지는 않았다.
      • image-20210204222640714
  5. Cascade R-CNN
    1. Cascaded Bounding Box Regression
      • 4-3에서 blue dot에 대한 설명과 다르게 distribution이 1-stage와 비슷하게 유지되도록 노력했다. (그래서 나온 결과가 u=0.5, 0.6, 0.7)
      • image-20210204232921641 는 normalized 된다. [Faster R-CNN] 널리 사용되는 방법이란다. 코드에서는 구체적인 normalization을 이루진 않았다. (필요하면! 아래의 아래 6-2 stat 부분 참조.)
    2. Cascaded Detection
      • image-20210204234748605
  6. Experimental Results
    1. Implementation Details
      • four stages : 1_RPN and 3_detection with U = {0.5, 0.6, 0.7}
      • horizontal image flipping 이외에 어떤 data augmentation도 사용되지 않았다.
    2. Generalization Capacity
      • 지금까지는 예측 BB의 GT와의 IOU를 증가시키려고 노력했다. 그럼 Figure(3)-d에서 C1,C2,C3는 어떻게 이용할까? 실험을 통해서 그냥 C3를 이용해서 Class 예측을 하는 것보다는, C1,C2,C3을 앙상블함으로써 더 좋은 AP를 얻어내었다고 한다.
      • image-20210205123349693
      • (블로그 내용 참조 그리고 FasterRCNN논문도 나중에 참고해보기. 참고해봤는데 이런 내용 없다. 그래서 일단 블로그 작성자에게 “구체적으로 어디서 나온 내용이냐고” 질문 해봄. 질문이 잘 갔는지 모르겠다…) Regression Statistics = stat : 위의 offset relative 델타 값들은, Faster-RCNN에서 이 파라메터가 잘 나오게 학습시킬 때 L1 loss를 사용한다. 이때 델타값을 normalization하지 않으면 자칫 학습이 잘 이뤄지지 않는 문제가 있었다고 한다. 그래서 각 좌표값을 normalize하는 작업을 수행했다. (4-1의 수식처럼) 각 Stage에서 각자의 기준으로, regressing offset relative값에 대한 normalization을 수행했다는 의미인듯 하다.
      • Cascade 모듈은 다른 곳에서 쉽게 적용될 수 있다. 다른 기본 모델에 cacade모듈을 적용하여 효과적인 AP 상승을 이뤄낼 수 있었다고 한다.

2. guoruoqian/cascade-rcnn_Pytorch

  1. Github Link : guoruoqian/cascade-rcnn_Pytorch

  2. 코드가 어느 정도 모듈화가 되어 있다. 하지만 보는데 그리 어려운 정도는 아니다.

  3. ROI pooing + ROI Align/ Cascade + Noncacade/ 와 같이 비교를 위한 코드도 함께 들어가 있다.

  4. 핵심 신경망 구현 코드는 이것이다. cascade-rcnn_Pytorch/lib/model/fpn/cascade/fpn.py
    여기서 FPN도, RPN의 사용도, Cacade Multi-stage Module, Loss계산 까지 모두 구현 되어있다. 물론 다른 곳에서 구현된 함수와 클래스를 마구마구 사용하지만….

  5. # cascade-rcnn_Pytorch/lib/model/fpn/cascade/fpn.py
    class _FPN(nn.Module):
           
        def __init__(self, classes, class_agnostic):
            self.RCNN_loss_cls = 0
            self.RCNN_loss_bbox = 0
            self.RCNN_rpn = _RPN_FPN(self.dout_base_model)
            self.RCNN_roi_align = RoIAlignAvg(cfg.POOLING_SIZE, cfg.POOLING_SIZE, 1.0/16.0)
            # 다른 신경망을 봐야함 FPN에는 없음 아래 내용 2nd, 3rd에 동일 적용
            self.RCNN_bbox_pred = nn.Linear(1024, 4)
            self.RCNN_bbox_pred = nn.Linear(1024, 4 * self.n_classes)
            # 이게 u = 0.5, 0.6, 0.7 적용은 아래의 신경망이 사용된다.
            self.RCNN_proposal_target = _ProposalTargetLayer(self.n_classes)
               
        def forward(self, im_data, im_info, gt_boxes, num_boxes):
    		# Feature Map 뽑기
            rpn_feature_maps = [p2, p3, p4, p5, p6]
            mrcnn_feature_maps = [p2, p3, p4, p5]
            rois, rpn_loss_cls, rpn_loss_bbox = self.RCNN_rpn(rpn_feature_maps, im_info, gt_boxes, num_boxes)
               
            # 첫번째 Classifier
            roi_data = self.RCNN_proposal_target(rois, gt_boxes, num_boxes)
            roi_pool_feat = self._PyramidRoI_Feat(mrcnn_feature_maps, rois, im_info)
            pooled_feat = self._head_to_tail(roi_pool_feat)
            bbox_pred = self.RCNN_bbox_pred(pooled_feat)
            cls_score = self.RCNN_cls_score(pooled_feat)
            # 두번째 Classifier
            roi_data = self.RCNN_proposal_target(rois, gt_boxes, num_boxes, stage=2)
            roi_pool_feat = self._PyramidRoI_Feat(mrcnn_feature_maps, rois, im_info)
            pooled_feat = self._head_to_tail_2nd(roi_pool_feat)
            bbox_pred = self.RCNN_bbox_pred_2nd(pooled_feat)
            cls_score = self.RCNN_cls_score_2nd(pooled_feat)
            # 세번째 Classifier
            roi_data = self.RCNN_proposal_target(rois, gt_boxes, num_boxes, stage=3)
            roi_pool_feat = self._PyramidRoI_Feat(mrcnn_feature_maps, rois, im_info)
            pooled_feat = self._head_to_tail_3rd(roi_pool_feat)
    		bbox_pred = self.RCNN_bbox_pred_3rd(pooled_feat)
            cls_score = self.RCNN_cls_score_3rd(pooled_feat)
                   
    
  6. self.RCNN_proposal_target = _ProposalTargetLayer(self.n_classes)
       
    # cascade-rcnn_Pytorch/lib/model/rpn/proposal_target_layer.py 
    class _ProposalTargetLayer(nn.Module):
        """
        Assign object detection proposals to ground-truth targets. 
        Produces proposal classification labels and bounding-box regression targets.
           
        내가 예측한 BB값과 GT값을 비교해서, Positive에 해당하는 BB만을 return하는 코드 같다
        """
        if stage == 1:
            fg_thresh = cfg.TRAIN.FG_THRESH
            bg_thresh_hi = cfg.TRAIN.BG_THRESH_HI
            bg_thresh_lo = cfg.TRAIN.BG_THRESH_LO 
        elif stage == 2:
            fg_thresh = cfg.TRAIN.FG_THRESH_2ND
            bg_thresh_hi = cfg.TRAIN.FG_THRESH_2ND
            bg_thresh_lo = cfg.TRAIN.BG_THRESH_LO
        elif stage == 3:
            fg_thresh = cfg.TRAIN.FG_THRESH_3RD
            bg_thresh_hi = cfg.TRAIN.FG_THRESH_3RD
            bg_thresh_lo = cfg.TRAIN.BG_THRESH_LO
        ... 
          
    # cascade-rcnn_Pytorch/lib/model/utils/config.py 
    __C.TRAIN.FG_THRESH = 0.5
    __C.TRAIN.FG_THRESH_2ND = 0.6
    __C.TRAIN.FG_THRESH_3RD = 0.7
    
  7. 델타 (offset relative) normalization : 확실한 건 아니지만, 아래의 코드에 이런 것을 확인할 수 있었다. 하지만 아래의 과정은 rois의 x,y값을 그저 0~1사이의 값으로 만들어 줄 뿐이다. 따라서 normalization는 아니다. // 그 아래의 코드에 BBOX_NORMALIZE_STDS라는 것도 있는데, 이건 GT에 대해서 normalization을 하는 코드이다. // 아무래도 역시 Faster-RCNN에서 먼저 공부하고 다른 Faster-RCNN이나 Mask-RCNN의 코드를 함께 보는게 더 좋겠다.

    if self.training:
        roi_data = self.RCNN_proposal_target(rois, gt_boxes, num_boxes)
        rois, rois_label, gt_assign, rois_target, rois_inside_ws, rois_outside_ws = roi_data
       
        ## NOTE: additionally, normalize proposals to range [0, 1],
        #        this is necessary so that the following roi pooling
        #        is correct on different feature maps
        # rois[:, :, 1::2] /= im_info[0][1] # image width로 나눔
        # rois[:, :, 2::2] /= im_info[0][0] # image height로 나눔
       
    # lib/model/rpn/proposal_target_layer.py 
    class _ProposalTargetLayer(nn.Module):
        def __init__(self, nclasses):
             self.BBOX_NORMALIZE_STDS = torch.FloatTensor(cfg.TRAIN.BBOX_NORMALIZE_STDS)
             self.BBOX_INSIDE_WEIGHTS = torch.FloatTensor(cfg.TRAIN.BBOX_INSIDE_WEIGHTS)
        def forward(self, all_rois, gt_boxes, num_boxes, stage=1):
            self.BBOX_NORMALIZE_MEANS = self.BBOX_NORMALIZE_MEANS.type_as(gt_boxes)
            self.BBOX_NORMALIZE_STDS = self.BBOX_NORMALIZE_STDS.type_as(gt_boxes)
            self.BBOX_INSIDE_WEIGHTS = self.BBOX_INSIDE_WEIGHTS.type_as(gt_boxes)
               
    

【Detection】Understanding RefineDet paper with code

  • 논문 : Single-Shot Refinement Neural Network for Object Detection
  • 분류 : Object Detection
  • 저자 : Shifeng Zhang , Longyin Wen3
  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.
  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.
  • 참고 블로그 : Method Review
  • 느낀점 :

1. RefineDet

1-1. 블로그 내용 정리

  1. 논문의 핵심은 “Multi-Scale Testing기법” : test 시에도 multi scale을 적용하는 방식

  2. 하나의 이미지를 여러 scale에서 학습을 하는 논문

    1. SSD에서는 여러 scale의 feature map에 대해서 적용을 하였고 학습
    2. YOLO는 학습 데이터의 해상도를 320x320 부터 608x608까지 다양한 scale로 resize를 하여 학습
  3. RefineDet은 SSD 계열의 모델이다. (아래 model Architecture 사진 참조)

    1. 1) Anchor Refinement Module(ARM) : Anchor에 대한 binary classification수행. negative anchor들을 걸러내면서, 동시에 anchor들의 위치를 조절(RetinaNet에서 Focal Loss, YOLOv3에서 Objectness score 역할 for class imbalance)
    2. 2) Object Detection Module
  4. RefineDet의 종류는 (input size) 320, 512, (with Multi-Scale Testing) + 가 있다.

  5. 최근 논문인 M2Det에서도 "Multi-Scale Testing기법"을 적극적으로 사용해 성능을 많이 올렸다. 특히 AP_small 에서 훨씬 좋은 성능을 얻어 내었다.

  6. Multi-Scale Testing Algorithm

    • Filp과 UpScaling, DownScaling을 사용한다. 원본 이미지가 작을 수록 UpScaling을 많이 한다. 이 경우 Small Object 검출 성능을 높히고 FalsePositive(신경망은 객체라고 판단했지만 GT에는 아닐 경우)를 방지하기 위해 일정 크기 이하의 검출 결과만 사용한다.

    • 모든 Scale에서 Inference한 결과를 모아서 NMS를 적용한다.

    • """
      im_detect(net, im, ratio*targe_size) : im를 ratio만큼 늘리거나 줄여서 inference 수행
      마지막 모든 결과를 모아서 NMS 수행
      """
      det0 = im_detect(net, im, targe_size)
      det0_f = flip_im_detect(net, im, targe_size)
           
      det1 = im_detect(net, im, int(0.6*targe_size))
      det1_f = flip_im_detect(net, im, int(0.6*targe_size))
               
      det2 = im_detect(net, im, int(1.2*targe_size))
      det2_f = flip_im_detect(net, im, int(1.2*targe_size))
               
      det3 = im_detect(net, im, int(1.4*targe_size))
      det3_f = flip_im_detect(net, im, int(1.4*targe_size))
               
      det4 = im_detect(net, im, int(1.6*targe_size))
      det4_f = flip_im_detect(net, im, int(1.6*targe_size))    
               
      det5 = im_detect(net, im, int(1.8*targe_size))
      det5_f = flip_im_detect(net, im, int(1.8*targe_size))
           
      cls_dets = np.row_stack((det0, det_r, det1, det2, det3, det4, det5, det7))
      cls_dets = soft_bbox_vote(cls_dets) # nms 적용
      

1-2 Paper Review

  1. Conclusion
    • ARM (anchor refinement module)
      1. negative anchors를 필터링 한다. classifier의 search sapce를 줄이기 위해서.
      2. 거칠게(대충=Coarsely) anchors 사이즈와 location을 조정한다.
    • ODM (object detection module)
      1. refined anchor를 받는다.
      2. 각 anchor에 대한 적절한 multiclass labels을 예측한다.
    • multi-task loss 사용한다.
  2. Abstract, Introduction, Related Work
    • ARM과 ODM에 대한 똑같은 설명
    • TCB (transfer connection block) : ARM에서 ODM에게 Feature를 보내주는 모듈
    • SSD -> DSSD (SSD+Deconvolution) -> DSOD(learn object detectors from ‘scratch’) -> Focal Loss, classification strategies(for class imbalance problem)
    • image-20210203173932901
  3. Network Architecture
    • 핵심은 이와 같다,
      1. TCB, ARM, ODM
      2. Two-step cascaded regression
      3. Negative anchor filtering
    • transfer connection block (TCB)
      1. Eltw sum = sum them in the element-wise way
      2. ARM으로 부터 내려오는 Feature는 the feature maps associated with anchors(Anchor에 대한 정보를 담고 있는 feature) 라고 할 수 있다.
    • Two-step cascaded regression
      1. 과거 모델들 단점 : the small objects 검출에 관한 낮은 성능
      2. ARM에서 Anchors의 size와 location을 조정한다!
        • 하나의 cell에 n개의 anchor box를 할당한다. 각 cell에 대해 4개의 offset값, 2개의 confidence score(background=negative, foreground=positive) 값을 예측한다. (총 6개 값이 ARM에서 예측됨 = the refined anchor boxes feature)
        • ODM에서는 각 cell에 대해서 c+4의 channel이 output으로 나오게 설정한다.
        • image-20210203193841008
        • 빨간색 X의 의미는 틀렸다는 의미다!! celadon parallelogram(청자색 평행사변형) 의 feature가 6 channel로 concat되는게 아니다. 코드를 확인해 보면 다음과 같이 설명할 수 있다.
        • “ARM에서 만들어지는 변수 arm_loc, arm_conf는 loss를 계산하는데 사용된다. 이 Loss값을 줄이기 위해 arm_loc, arm_conf는 최대한 정답값에 가까워지기 위해 노력한다. 그 말은 ARM의 Feature map(코드에서 Source변수)들이, arm_loc, arm_conf이 정확하게 나오도록, 값이 유도된다는 뜻이다. 이 과정을 통해 ARM의 Feature map은 ODM에서 Localization, Detection을 하기 위해 필요한, 충분한 정보를 담게 된다는 것을 의미한다.”
    • Negative Anchor Filtering
      1. 2개의 confidence score 중 negative 값이 일정 threshold(=0.99) 이상 보다 크면, ODM training 중에 사용하지 않는다. 이 과정에서 너무 많은 negative anchor가 제외되고, negative anchor box에 대한 loss값은 줄어든다. (Focal Loss 때의 Post 참조)
      2. inferene 동안에 negative값이 너무 커도, ODM에서의 detection값은 무시된다.
  4. Training and Inference

    • Anchors Design and Matching

      1. stride : sizes 8, 16, 32, and 64 pixels
      2. scale : stride x 4
      3. ratios : three aspect ratios (i.e., 0.5, 1.0, and 2.0)
      4. GT와 the best overlap score를 가지는 Anchor box를 matching 시킨 후, 그리고 0.5이상의 IOU를 가진 Anchor box를 매칭 시켰다. (?) (그렇다면 Positive, Negative 값의 GT값이 무엇인지 궁금하다. 코드를 봤지만 나중에 필요하면 다시 찾아보는게 좋겠다.)
    • Hard Negative Mining

      1. 대부분의 ARM_confidence값이 큰 Negative를 가진다. 너무큰 Negative를 가지는 값은 ODM에서 나오는 c+4값은 무시된다. (즉 Negative값이 Focal loss나 objectness score로 사용된다.)
      2. training 에서 top loss를 만들어내는 Negative anchor에 대해서만 ODM 학습을 한다.(위의 설명처럼, 예측 negative값이 1에 가깝지 않을수록 negative anchor에 대한 loss가 커진다.) 거기다가 한술 더떠서 SSD의 hard Negative Mining기법을 사용해서, Negative : Positive의 비율을 3:1정도로 유지 되도록 anchor를 준비해 loss값을 계산한다.
    • Loss Function

      1. ARM을 위한 Loss, ODM을 위한 Loss로 나뉜다.

      2. image-20210203230521468

      3. 여기서 궁금한것은 (1)번 항에서 Negative(=background)와 Positive(=foreround)에 대한 모든 학습이 이뤄질텐데, 왜 Positive anchor갯수만 사용하는 N_arm으로 나누지? 코드를 봐도 그렇다. 이유는 모르겠다. 하지만 큰 의미는 없는 듯 하다.

      4. num_pos = pos.long().sum(1, keepdim=True)
        num_neg = torch.clamp(self.negpos_ratio*num_pos, max=pos.size(1)-1)
                
        N = num_pos.data.sum().float()
        #N = max(num_pos.data.sum().float(), 1)
        loss_l /= N
        loss_c /= N
        
    • Optimization

      1. the “xavier” method to randomly initialize
      2. batch size = 32
      3. SGD with 0.9 momentum and 0.0005 weight decay
      4. initial learning rate to 10−e
      5. use slightly different learning rate decay policy
    • Inference

      1. theta=0.99보다 큰 Negative를 가지는 conf는 ARM에 부터 제거 된다.
      2. ARM에서 anchor를 refine하고 그거를 다시 ODM에서 anchor refine한 값이 예측 Bounding Box 좌표
      3. Out으로 나오는 모~든 예측 Bounding box 중에서, confidence가 놓은 순서로 400개의 예측 box를 찾고, 그 400개에 대해서 NMS를 수행한다.
      4. 좀 더 정확한 사항은 ‘detection_refinedet.py-NMS수행’ 파일 참조. (논문에 이상하게 쓰여 있다)
  5. Experiment

    • 모든 데이터에 대해서, multi-scale testing 기법을 사용해서 더 좋은 결과를 얻었다. (블로그와 달리 이 논문에서는 multi-scale testing에 대한 설명은 하나도 없다. “그냥 썼다.”가 끝이다. 몇배를 어떻게 하고~ 에 대한 이야기는 없다. )

luuuyi/RefineDet.PyTorch

  1. Github Link : luuuyi/RefineDet.PyTorch

  2. 모듈화가 적어서 아주 이해하기 쉬운 코드

  3. RefineDet.PyTorch/models/refinedet.py

    • class RefineDet(nn.Module):
          """
          sources = list() : VGG를 통과하고 나오는 중간중간의 faeture map들
          tcb_source = list() : Source에서 (ARM처리를 일단 하고) TCB처리를 하고 나오는 feature map
          arm_loc = list() 
          arm_conf = list()
          odm_loc = list()
          odm_conf = list()
               
      	(A)1 내가 신기한것은 odm_loc를 계산한는데, arm_loc를 절대 사용하지 않는다. [(A)2,(A)3 이어서...]
          """
          def __init__(...):
          	self.detect = Detect_RefineDet(num_classes, self.size, ...)
              # arm, odm, tcb 구현에 필요한 layer 등록
          def forward(self, x):
              # 84 ~ 103 Line : Sources 변수에 VGG Conv2D 통과+계산해서 값 넣기
              # 106 ~ 129 Line : ARM처리하고 arm_loc, arm_conf 만들어 내고, tcb_source 변수에 값 넣기
              # 131 ~ 149 Line : ODM처리하고 odm_loc, odm_conf 만들어 넣기
              # 139 ~ ... Line : 아래와 같이 arm_loc, arm_conf, odm_loc, odm_conf 최종값 return 하기
              if self.phase == "test":
                  output = self.detect(
                          arm_loc.view(arm_loc.size(0), -1, 4),           # arm loc preds
                          self.softmax(arm_conf.view(arm_conf.size(0), -1,
                                       2)),                               # arm conf preds
                          odm_loc.view(odm_loc.size(0), -1, 4),           # odm loc preds
                          self.softmax(odm_conf.view(odm_conf.size(0), -1,
                                       self.num_classes)),                # odm conf preds
                          self.priors.type(type(x.data))                  # default boxes
                      ) # 정제된 값을 결과로 주세요! (최종 Bounding Box, What max conf class)
              else:
                  output = (
                          arm_loc.view(arm_loc.size(0), -1, 4),
                          arm_conf.view(arm_conf.size(0), -1, 2),
                          odm_loc.view(odm_loc.size(0), -1, 4),
                          odm_conf.view(odm_conf.size(0), -1, self.num_classes),
                          self.priors # anchor box의 가장 기본 위치 저장되어 있음
                      ) 
              returne output
      
    • RefineDet.PyTorch/layers/functions/detection_refinedet.py

      • class Detect_RefineDet(Function):
            """
            Decode predictions into bboxes.
            test시에 나오는 결과 값은 c+4개 confidence, localization 값이 아니다. 
            이렇게 결과를 내보내면 사용자는 이게 뭔 값인지 절대 모른다. 
        	따라서 max confidnence class값이 무엇인지, 최종 예측 bounding box가 무엇인지 정제해서 값을 던져주어야 한다. 이 클래스는 그런 역할을 한다. 
               	
        	(A)3 그러면서 Detect_RefineDet함수가 돌아갈때는 '기본 Anchor위치에 arm_loc를 먼저 적용하고, 그 다음에 odm_loc를 적용해서 나오는 예측 bounding box 값'을 정답값으로 사용한다. 
            """
            for i in range(num):
                default = decode(arm_loc_data[i], prior_data, self.variance)
             default = center_size(default)
                decoded_boxes = decode(loc_data[i], default, self.variance)
                
        
    • RefineDet.PyTorch/train_refinedet.py

      • def train():
            """
            (A)2 loss를 계산할 때, '기본 Anchor위치에 arm_loc를 먼저 적용하고, 그 다음에 odm_loc를 적용해서 나오는 예측 bounding box 값'을 가지고 loss를 계산하는 줄 알고 코드를 확인해 봤더니... 그것도 아니다. (내가 잘 못찾는 거일 수도 있다.) 
            """
            refinedet_net = build_refinedet('train', cfg['min_dim'], cfg['num_classes'])
                   
            arm_criterion = RefineDetMultiBoxLoss(2, 0.5, True, ...)
            odm_criterion = RefineDetMultiBoxLoss(cfg['num_classes'], 0.5, True, ...)
                   
            net = refinedet_net
            out = net(images)
                   
            optimizer.zero_grad()
            # RefineDetMultiBoxLoss 가 정의된 refinedet_multibox_loss.py 파일을 보면 (A)2 결론을 내릴 수 있다.
            arm_loss_l, arm_loss_c = arm_criterion(out, targets)
            odm_loss_l, odm_loss_c = odm_criterion(out, targets)
                   
            arm_loss = arm_loss_l + arm_loss_c
         odm_loss = odm_loss_l + odm_loss_c
            loss = arm_loss + odm_loss
         loss.backward()
        
    • RefineDet.PyTorch/eval_refinedet.py

      • if __name__ == '__main__':
            net = build_refinedet('test', int(args.input_size), num_classes)  
            test_net(args.save_folder, net, args.cuda ...)
               
        def test_net(save_folder, net, cuda, dataset, transform, top_k, ...)
            detections = net(x).data     
        
    • RefineDet.PyTorch/layers/modules/refinedet_multibox_loss.py

      • # 구체적으로 설명할 수 없지만, 궁금한게 Loss함수에 많이 구현되어 있다. 자주 볼거다.
        defaults = priors.data # Anchor들이 '이미지 위'에 위치하는 위치()를 정확하게 적어놓은 값.
        if self.use_ARM:
            refine_match(self.threshold, truths, defaults, self.variance, labels,
                         loc_t, conf_t, idx, arm_loc_data[idx].data)
        else:
            refine_match(self.threshold, truths, defaults, self.variance, labels,
                             loc_t, conf_t, idx)
        
    • RefineDet.PyTorch/layers/box_utils.py

      • def refine_match(threshold, truths, priors, variances, ...):
            """
            (A)4 내가 (A)2에서 했던 말이 맞았다!!
            loss를 계산할 때, refine_match라는 함수를 통해서 만약 ODM에 대한 odm_loc_data를 계산하고 싶다면, priors 위치를 한번 arm_loc_data로 offset refine한 후, 다시 odm_loc_data로 offset refine하고 나서 원래 GT-bounding box 위치랑 비교를 한다. 
            이 함수에서 그러한 작업을 수행한다. 
            """
        

      -

【Detection】Understanding YOLOv3 paper without code

  • 논문 : YOLOv3: An Incremental Improvement
  • 분류 : Object Detection
  • 저자 : Joseph Redmon, Ali Farhadi (University of Washington)
  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.
  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.
  • 내 블로그 관련 Post : YOLO (You Only Live Once) V1 V2 V3 핵심정리
  • 느낀점 :
    • 겨우 5페이지 밖에 안되는 논문이기 때문에, 궁금한것만 대충 읽고 Youtube의 발표 자료를 이용해 공부하려고 한다. 또한 모르는 것은 코드 중심으로 공부해야겠다. 그럼에도 불구하고, 역시 내가 직접 논문을 읽는게 직성이 풀린다. 그리고 누군가의 설명을 들으면 솔직히 의심된다. 이게 맞아? 그리고 정확히 이해도 안된다. 물론, 논문도 자세하지 않기 때문에 누군가의 설명을 참고해서 직관적인 이해를 하는 것도 좋지만, Yolov3는 논문이 신기한 논문이라서, 논문 그 자체로도 이해가 잘 됐다.
    • 추가 참고 동영상 : PR-207: YOLOv3: An Incremental Improvement
    • 이미 알던 방법론을 많이 사용했기 때문에, 코드는 안봐도 될 것 같다.

1. YOLOv3

  1. TECH REPORT not Paper
  2. Bounding Box Prediction
    • Anchor(=bounding box != GT_object)를 이용한 the relative offset 개념을 그대로 사용한다.
    • 이전 모델들과 다르게, 각 bounding-box가 an objectness score 개념을 사용한다. 한 객체에 대해서 가장 많이 겹친 box만 objectness score target = 1을 준다. (지금까지 IOU (+confidence)를 이용해서 일정 이상의 값이면 Positive라고 판별하고 objectness score = confidence = 1 을 주었다.)
    • only assigns one bounding box prior for each ground truth object
    • 한 객체 GT에 대한 하나의 bounding box 이외에, 다른 박스들은 class predictions와 coordinate(offset)으로 어떤 loss도 발생시키지 않는다. 단지 objectness sore에 의한 loss만 적용된다.
  3. Class Prediction
    • not use a softmax for multilabel classification. Yes logistic classifiers
    • binary cross-entropy loss
  4. Predictions Across Scales
    • image-20210202212841671
    • 주황색 단이 우리가 SSD나 RetinaNet에서 보는 detect-head classification, regression 단이다.
    • 위와 같이 3개의 P(pyramid feature)를 사용한다. 그리고 하나의 cell에 대해서, 3개의 Anchor box만 사용한다.
    • COCO dataset에 대해서, K-mean clustering을 사용해서 가장 적절한 bounding box(Anchor box 크기)값을 찾는다. 결론적으로 (10×13),(16×30),(33×23) // (30×61),(62×45),(59× 119) // (116 × 90),(156 × 198),(373 × 326) 를 사용한다. (동영상 : 내가 찾고자 하는 객체의 특징을 반영해서 bounding box크기를 적절히 설정하는 것도 아주 중요하다. 예를 들어 사람을 detect하고 싶다면 가로로 긴 박스는 필요없다)
    • 당연히 작은 bounding box는 가장 마지막 단의 cell에서 사용되는 box, 큰 bounding box는 가장 첫번째 단의 cell에서 사용되는 box이다.
  5. Things We Tried That Didn’t Work
    • Offset predictions : linear 함수를 사용해봤지만 성능 저하.
      image-20210202222512434
    • Focal Loss : objectness score라는 개념이 들어가서, 이것으로 easy, hard Image에 따른 성능 저하는 없었다. 차라리 Focal Loss를 사용해서 성능 저하가 일어났다. 또한 objectness score 덕분에 hard negative mining과 같은 작업을 하지 않았다. 즉 objectness score를 통해 class imbalance 문제를 다소 해결했다.
    • Dual IOU thresholds and truth assignment : Faster RCNN 에서는 2개의 IOU thresholds를 사용했다. (0.7과 0.3) 0.7을 넘으면 Positive example, 0.7과 0.3 사이는 학습에 사용하지 않고, 0.3 이하는 Negative example로 background 예측에 사용했다. 비슷한 전력을 사용했지만 결과는 좋지 않았다.
  6. COCO의 AP 계산에 대한 비판
    • YOLOv3는 좋은 detector이다. 하지만 COCO AP는 IOU를 [0.5부터 : 0.95까지 : 0.05단위로] 바꾸며 mAP를 계산한다. 이건 의미가 없다! 인간이 IOU 0.3~0.5를 눈으로 계산해보라고 하면 못하더라!
    • COCO에서는 Pascal voc보다 labelling 이 정확한건 알겠다.(Bounding Box를 정확하게 친다는 등) 하지만 IOU가 0.5보다 정확하게 Detect해야한다는 사실은 의미가 없다. 0.5보다 높게 Threshold를 가져가면… classification은 정확하게 됐는데, regression 좀 부정확하게 쳤다고 그걸 틀린 판단이라고 확정해버리는 것은 억울하다.
    • mAP는 옳지 않은 지표이다.
      • image-20210202223526436
      • 이 그림에서 위의 Detector 1 이 훨씬 잘했다고 우리는 생각한다. 하지만 둘다 mAP를 계산하면 놀랍게도 1이 나온다. 2개를 이용해 recall, precise 그래프를 그려보면 오른쪽 위와 같은 그래프가 된다. 초록색 라인이 Detector1이고 주황색 라인이 Detector2이다!
      • mAP 이론 설명 이전 Post

【docker】container setting using ML-workspace

1. install docker

2. 필수 명령어

  • $ sudo docker image list
    $ sudo docker image rm <img_name>
    $ sudo docker container list -a 
    $ sudo docker container rm <container-ID>
    $ sudo docker container stop <container-ID>
    $ sudo docker container start <container-ID>
    

3. How to RUN ml-workspace

  • docker run -d \
        -p 8080:8080 \  # port 설정 
        --name "ml-workspace" \
        -v "${PWD}:/workspace" \
        --env AUTHENTICATE_VIA_JUPYTER="mytoken" \
        --shm-size 512m \
        --restart always \
        mltooling/ml-workspace:0.12.1
    
  • -p : port 설정 설명, -p : port설정

  • -v : 나같은 경우 "$pwd"/docker_ws:/workspace

    • bind mount
    • 나의 컴퓨터 terminal의 현재 “$pwd”/docker_ws (나같은 경우 /home/junha/docker_ws)
    • container의 new ubuntu root에 /workspace라는 폴더 생성 후
  • -env AUTHENTICATE_VIA_JUPYTER=”내가 설정하고 싶은 비밀번호”

  • -d : background container start

4. Docker container와 VScode 연동하기

  1. 첫번째 VScode 사용하는 방법
    • ml-workspace에서 알려주는 vscode
    • vscode 서버를 사용한 실행.
    • 원하는 폴더를 체크박스_체크 를 해주면, vscode옵션을 선택할 수 있다.
    • 이렇게 하면 EXTENSIONS 를 나의 컴퓨터 그대로 사용하기는 어려우므로 VScode docker 연동법을 공부해보자.
  2. 컴퓨터 VScode의 docker SSH 를 사용하서 연결하기.
    • Remote-container EXTENSION을 설치해준다.
    • ctrl+shift+p -> Remote-Containers: Attach to Running Container
      • 자동으로 현재 container 목록이 보인다. 원하는거 고르면 remote vscode 새창 뜬다
      • 아주 잘 됨.
    • 굳이 IP설정을 해주지 않더라도 잘 연결된다. (GCP에서의 SSH 설정하기 이것과는 달리..)
    • 만약 문제가 생기면 config 파일 여는 방법
    • ctrl+shift+p -> Remote-Containers: Open Attached Container Configuration File

5. detectron2 using ml-workspce

  1. import torch, torchvision
     print(torch.__version__, torch.cuda.is_available())
       
     import detectron2
     from detectron2.utils.logger import setup_logger
     setup_logger()
       
     # import some common libraries
     import numpy as np
     import os, json, cv2, random
       
     # import some common detectron2 utilities
     from detectron2 import model_zoo
     from detectron2.engine import DefaultPredictor
     from detectron2.config import get_cfg
     from detectron2.utils.visualizer import Visualizer
     from detectron2.data import MetadataCatalog, DatasetCatalog
       
     im = cv2.imread("./input.jpg")
       
     cfg = get_cfg()
     cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
     cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5  # set threshold for this model
     cfg.MODEL.DEVICE = "cpu" # 필수!!!!
     cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
     predictor = DefaultPredictor(cfg)
     outputs = predictor(im)
       
     print(outputs["instances"].pred_classes)
     print(outputs["instances"].pred_boxes)
    
  2. $ python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.7/index.html
    $ pip install torch==1.7.1+cpu torchvision==0.8.2+cpu torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html
    
  3. 1번을 그대로 실행하니 에러발생. 2번의 과정을 통해서 에러 해결.

  4. 디버깅이 안된다. Step into로 들어가면, 내가 보고 있는 py파일 뿐만 아니라, Import하는 함수 내부로 들어가서 어떤 파일과 함수가 실행되는지 보고 싶은데 안된다. docker container 내부, ubuntu의 env 속, python 모듈은 디버깅으로 들어갈 수 없는 건가??

  5. 에러내용 - DefaultPredictor가 어떤 흐름으로 실행되는지 대충 훔처 볼 수 있다.

     AssertionError:
     Torch not compiled with CUDA enabled
     # /opt/conda/bin/python /workspace/test.py
     1.7.1 False
     ** fvcore version of PathManager will be deprecated soon. **
     ** Please migrate to the version in iopath repo. **
     https://github.com/facebookresearch/iopath 
        
     ** fvcore version of PathManager will be deprecated soon. **
     ** Please migrate to the version in iopath repo. **
     https://github.com/facebookresearch/iopath 
        
     model_final_f10217.pkl: 178MB [01:03, 2.79MB/s]                                                                                                                                                        
     # MODEL.DEVICE = 'cpu' 
     -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     test.py 29 <module>
     outputs = predictor(im)
        
     defaults.py 223 __call__
     predictions = self.model([inputs])[0]
        
     module.py 727 _call_impl
     result = self.forward(*input, **kwargs)
        
     rcnn.py 149 forward
     return self.inference(batched_inputs)
        
     rcnn.py 202 inference
     proposals, _ = self.proposal_generator(images, features, None)
        
     module.py 727 _call_impl
     result = self.forward(*input, **kwargs)
        
     rpn.py 448 forward
     proposals = self.predict_proposals(
        
     rpn.py 474 predict_proposals
     return find_top_rpn_proposals(
        
     proposal_utils.py 104 find_top_rpn_proposals
     keep = batched_nms(boxes.tensor, scores_per_img, lvl, nms_thresh)
        
     nms.py 21 batched_nms
     return box_ops.batched_nms(boxes.float(), scores, idxs, iou_threshold)
        
     _trace.py 1100 wrapper
     return fn(*args, **kwargs)
        
     boxes.py 88 batched_nms
     keep = nms(boxes_for_nms, scores, iou_threshold)
        
     boxes.py 41 nms
     _assert_has_ops()
        
     extension.py 62 _assert_has_ops
     raise RuntimeError(
        
     RuntimeError:
     Couldn't load custom C++ ops. This can happen if your PyTorch and torchvision versions are incompatible, or if you had errors while compiling torchvision from source. For further information on the compatible versions, check https://github.com/pytorch/vision#installation for the compatibility matrix. Please check your PyTorch version with torch.__version__ and your torchvision version with torchvision.__version__ and verify if they are compatible, and if not please reinstall torchvision so that it matches your PyTorch install.
    

6. Debug Docker Containers

  1. 명학이의 도움으로 다음의 과정을 진행해 보았다. -> 안됨

    1. ctrl + shift + p -> setting -> > debug : launch json 검색-> Python file 선택
    2. 명학이가 보내준 사진대로 설정. 안됨.
  2. VS code Docker debuging : 지금 당장 나에게 맞는 방법은 아니다.

    1. https://code.visualstudio.com/docs/containers/debug-common
    2. https://code.visualstudio.com/docs/containers/debug-python
  3. Youtube로 공부해보기 -> 나에게 맞는 정보 없음

    • Link : How to debug Docker containers! (Python + VSCode)

      1. Use docker exec
        • $ docker run -d \
              -p 8080:8080 \  # port 설정 
              --name "ml-workspace" \
              -v "${PWD}:/workspace" \
              --env AUTHENTICATE_VIA_JUPYTER="mytoken" \
              --shm-size 512m \
              --restart always \
              --entrypoint=bash
              mltooling/ml-workspace:0.12.1
          
        • $ docker exec -it <docker-container-name or ID> bash
          # new shell start 
          $ python
          >> 여기서 module 디버깅
          
      2. Use Docker cp

        • print해서 나올 파일을 text.txt파일에 저장되도록 만든다.

        • with open("time.txt",'w+') as f:
          	f.write(str(<출력하고 싶은 변수>))
          
        • docker cp command 사용하기

        • $ docker cp <docker-container-name or ID>:/absolut/path/filename ./my_ubuntu/terminal/relative/path
          
  4. 직접 문제 해결

    • 나의 문제는 docker remote container가 실행되고 있는 상태(아래 이미지)에서 step-into dugging이 안되는 것이다.

    • image

    • Google 검색 : “vscode python debug step into not working”

    • 참고한 사이트 : stack overflow - Python debugging - Step into

    • 우분투에서 ctrl + shift + p -> > debug : launch json 검색-> Python file 선택 이 파일 내부의 내용을 아래 처럼 수정한다.

    • 사실 아래처럼 다 바꿀 필요는 없고, 진짜 중요한 것은 justMyCode : false 이다. 이것만 처리해주면 된다.

      {
           // Use IntelliSense to learn about possible attributes.
           // Hover to view descriptions of existing attributes.
           // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
           "version": "0.2.0",
           "configurations": [
               {
                   "name": "Python: Current File",
                   "type": "python",
                   "request": "launch",
                   "program": "${file}",
                   "console": "integratedTerminal",
                   "debugOptions" : ["DebugStdLib"],
                   "justMyCode": false        
                 }
           ]
       }
      
    • 하지만!! SSH server’s Docker container에서는 debug json 검색해도 찾을 수가 없었다. 더 쉬운 다른 방법은 이것을 클릭하면 된다!
      image

    •      
      {
           // Use IntelliSense to learn about possible attributes.
           // Hover to view descriptions of existing attributes.
           // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
           "version": "0.2.0",
           "configurations": [
               {
                   "name": "Python: Current File",
                   "type": "python",
                   "request": "launch",
                   "program": "${file}",
                   "console": "integratedTerminal",
                   "debugOptions" : ["DebugStdLib"],
                   "justMyCode": false        
                 }
           ]
       }
      
    • step into 된다!!

    • image

    • image

    • 2번째 에러 : Module cv2 has no member

    • 해결 방법 : https://12340zszs.tistory.com/67

    • image

Pagination


© All rights reserved By Junha Song.