【Detection】Understanding RetinaNet paper with code

  • 논문 : Focal Loss for Dense Object Detection

  • 분류 : Object Detection

  • 저자 : Tsung-Yi Lin, Priya Goyal (Facebook AI Research (FAIR))

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

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

  • 내 블로그 관련 Post : RetinaNet - Focal Loss, FPN

  • 느낀점 :

    1. 이번에 참고한 코드가 너무 쉽게 잘 되어 있어서 맘에 든다. SSD에서는 Anchor생성을 위해 s라는 개념을 사용했는데, 이 코드와 논문에서는 s의 개념을 사용하지 않는다.
    2. 그래서 이 anchor 사이즈가 적당한거야? 라는 생각이 들긴 한다. 이 정도 anchor사이즈면 이미지에 어느정도 크기로 (anchor box를) 대보는거지? 라는 생각이 들지만 굳이 그런 수학적 계산을 할 시간은 없다.
    3. 역시 논문만 봐서는 자세하게 이해못하는게 당연하다. 코드를 봐야 이해가 된다.

1. RetinaNet

  1. Abstract, Introduction, Related Work
    • Class Imbalance :
      • one-stage detector는 너무 많은 candidate location을 추론한다.(Faster-RCNN에서는 RPN에서 한번 거리고, 마지막 regression에서 한번 거리즈만..) 하지만 극히 일부만 진짜 object가 들어 있다. 이 이유는 2가지 이다.
      • (1) most locations are easy negatives(backgorund 혹은 크고 선병한 객체)-학습에 도움 안됨 (2) the easy negatives가 학습을 압도한다.
      • Class Imbalance문제를 focal loss를 사용해서 naturally, handle 하고 자 한다.
      • robust loss 라는 방식은 hard example의 loss를 더욱 키우는 방식이지만, focal loss에서는 반대이다. easy example의 loss를 아주 작게 만든다.
  2. Focal Loss
    • image-20210202134254020
    • γ는 2~5값을 사용했고, α는 balanced variable 이다. Focal loss의 정확한 형태(정확한 하이퍼파라메터값)은 중요하지 않다. 적당한 어떤 값이하도 효율적으로 작동한다.
    • for γ = 2, α = 0.25 works best
  3. RetinaNet Detector
    • 이 논문의 핵심은 Forcal Loss. to eliminates the accuracy gap between easy and hard examples. 따라서 Architecture는 아주 simple.
    • image-20210202145424687
    • (c) subnet에 들어갈 Channels = 256 and # Anchor = 9. 그리고 Ryramid간의 parameter share는 안한다.
  4. Anchors
    • On pyramid levels P3 to P7, areas of 32^2 to 512^2 개의 cell에 각각 Anchor가 적용된다.
    • Cover the scale range 32 - 813 pixels
    • ratios {1:2, 1:1, 2:1}. sizes {2 0 , 2 1/3 , 2 2/3 } -> 9 anchors
    • Each anchor -> K of object classes + 4 of box regression target
    • loss 계산 위해서
      • IoU threshold of 0.5 이상 -> 객체를 가진 Anchor로 판단.
      • IoU threshold of 0.4 이하 -> background로 판단
    • 1개의 Anchor에서는 많아 봤자 1개의 객체만 검출 -> 한 cell에 대한 multi 객체 탐색 안함
    • SSD에서 공부한 것 처럼, anchor에 대해서 GT box로 가기 위해서 어떻게 늘리고 이동해야하는지에 대한 localization 값을 구하기 위해서 Anchor를 사용한다.
  5. Box Regression Subnet
    • 각 Anchor에 대해서 4개의 값을 예측해야 한다. (box가 얼마나 이동해야 하는 regression offset값)
    • the purpose of regressing the offset(=the relative offset) from (1) each anchor box to (2) a nearby ground-truth object
    • classification subnet과 regression subnet은 구조를 완전히 같이 사용하지만, 파라미터 공유 안함

2. yhenon/pytorch-retinanet

  • 진짜 잘 만든 코드가 “누구든 쉽게 이해 가능한 코드“라면, 정말 잘 만든 코드이다.

  • lufficc/SSD가 모듈화를 아주 잘 해놓은 코드라고 하지만, 너무 복잡하다. 차라리 이 패키지가 공부하기 아주 좋다.

  • pytorch-retinanet/retinanet/losses.py : class FocalLoss(nn.Module):

    • class FocalLoss(nn.Module):
          def forward(self, classifications, regressions, anchors, annotations):
              # predict한 classifications, regressions 결과가 parameter로 들어온다. 
              # annotation에 Ground True값이 들어온다. 
              alpha = 0.25
              gamma = 2.0
              classification_losses = [] 
              regression_losses = [] # 나중에 이 loss를 모아서 return
                  
              # 1. compute the loss - 이미지에 객체가 하나도 없을 때
                  
              # 2. compute the loss for classification
              focal_weight = alpha_factor * torch.pow(focal_weight, gamma)
              bce = -(targets * torch.log(classification) + (1.0 - targets) * torch.log(1.0 - classification)) # object, background 모두. targets =[1,0]
              cls_loss = focal_weight * bce
                  
              # 3. compute the loss for regression
              """ L127 ~ L160까지 Anchor box와 GT와의 regression 계산 과정(SSDw/codePost 참조)= target"""
              regression_diff = torch.abs(targets - regression[positive_indices, :])
              regression_loss = torch.where(torch.le(regression_diff, 1.0 / 9.0),  0.5 * 9.0 * torch.pow(regression_diff, 2), regression_diff - 0.5 / 9.0 )
                  
              return torch.stack(classification_losses).mean(dim=0, keepdim=True), torch.stack(regression_losses).mean(dim=0, keepdim=True)
      
  • pytorch-retinanet/retinanet/model.py

    1. class PyramidFeatures(nn.Module): # 너무 간단해서 놀랍다.

    2. class RegressionModel(nn.Module): # 정말 위의 이미지와 똑같은 5 layer conv

    3. class ClassificationModel(nn.Module): # 정말 위의 이미지와 똑같은 5 layer conv

    4. class ResNet(nn.Module):

      • self._make_layer를 완벽하게 정의하여 아주 깔끔.
      • RetinaNet이라는 class없다. 이거 자체가 ResNet이다.
    5. def resnet<18,34,50,101,152>(num_classes, pretrained=False, **kwargs):

      • 위에서 정의한 class ResNet을 사용한다.

      • train.py, validation.py 에서 아래와 같이 RetinaNet을 호출한다.

      • from retinanet import model
        retinanet = model.resnet50(num_classes=dataset_val.num_classes(), pretrained=True)
        # retinanet = model.resnet<101,152>(num_classes=dataset_train.num_classes(), pretrained=True)
               
        
      • train.py, validation.py 여기의 코드도 optimizer와 reschedule의 사용을 아주 아름답고 간단하게 했기 때문에, 나중에 꼭 참고하면 좋을 듯 하다.
  • pytorch-retinanet/retinanet/anchors.py

    1. def generate_anchors(base_size=16, ratios=None, scales=None):
          """
          scales : [   1,   1.259,   1.5874 ]
          ratios : [ 0.5,       1,        2 ]
          base_size : anchor box 한변의 길이
          		= self.sizes = [2 ** (x + 2) for x in self.pyramid_levels(=[3, 4, 5, 6, 7])]
          """
          return (x1, y1, x2, y2) 형태의 9개의 anchors (9 x 4 행렬)
           
      class Anchors(nn.Module):
          def forward(self, image):
              image_shape = np.array(image_shape)
              image_shapes = [(image_shape + 2 ** x - 1) // (2 ** x) for x in self.pyramid_levels] # backbone을 통과하고 나오는 feature map size
              return 이미지 위에 올라갈 모든 Anchor들이 좌표값이 반환된다. 큰것부터 작은것까지.
      
    2. 그리고 model.py의 class ResNet(nn.Module): 에서 다음과 같이 사용된다.

      • class ResNet(nn.Module):
             self.anchors = Anchors()
             def forward(self, inputs):
                anchors = self.anchors(img_batch)
                return self.focalLoss(classification, regression, anchors, annotations)
        
      • 잘.. 생각해보면 별거 없다.

【Python-Module】Pytest Module study

  • pytest는 패키지를 완성하는 동안, 하나의 .py파일을 test하는 하나의 좋은 모듈이다.

  • pytest이전에는 assert 기반의 unittest (wiki-unitest)가 많이 사용되었지만, 최근에 와서는 pytest가 더 편리해서, 더 많이 사용되는 듯 하다. (pypi에서 검색을 해봐도, unittest는 최근 update가 2015이고, pytest는 2021년이다. 또한 raddit에서도 ‘just use pytest’라고 한다.)
  • 이 Pytest에 대해 공부해보자.
  • 그럼에도 불구하고, detectron2와 mmdetection에서는 unittest를 사용한다. 하지만 연구실 석박사 선배님들이 Unit Test 모듈을 사용하시는 것 같지는 않다. 필요하면 그 때 찾아서 공부해, 보도록 하자.

1. Referece

  1. https://wikidocs.net/80337
  2. https://jiyeonseo.github.io/2020/03/10/pytest/
  3. https://semaphoreci.com/community/tutorials/testing-python-applications-with-pytest
  4. https://docs.pytest.org/en/latest/contents.html : Pytest가 정말 절실히 필요하다고 느껴질 때, 이 공식 문서로 다시 공부하자. 혹은 취미로 조금씩 공부해 놓으면 나중에 많은 도움이 될 듯 하다.

1.1 Level up Python - pytest

  • Unit Test 란?
    유닛이란 보통 함수 단위라고 생각하면 좀 더 이해가 될 겁니다. 프로그램은 결국 데이터와 이를 처리하는 함수로 구성되는데 각 함수를 충분히 테스트하면 전체 프로그램에서 문제가 발생하는 것을 최소화할 수 있을겁니다. 그래서 함수를 구현한 후 함수의 입력과 예상되는 출력을 비교함으로써 함수를 테스트하는 겁니다.

  • 이 글을 통해서, Pytest는 디버깅을 하면서, 각 변수에는 어떤 type size(view) length 를 가지는지 확인하는 방법이 아니다. 라는 것을 깨달았다. 코드 내부에 구현한 함수 or 클래스가 잘 통작하는지? 어떤 인풋에 대해서 내가 원하는 Output이 나온지? 확인하는 모듈인 것 같다.

  • 사용예시 코드

    # mymath.py
    def average(a):
        return sum(a) / len(a)
      
    # test_mymath.py
    from mymath import average
    def test_average():
        assert average([1, 2, 3]) == 2 # assert 사용해야하는 듯
      
    # terminal
    $ pytest [-v] [-c <filename>] 
    
  • (-c 옵션을 하지 않으면) pytest를 실행한 pwd에서 test_ 접두사 , _test 접미사 를 붙인 파일을 자동으로 test하고, assert 결과가 Ture면 그냥 pass. False면 내부 변수가 뭐여서 false가 발생했는지 출력해준다.

1.2 빠르게 시작하는 pytest

  • 나중에 필요하면, 공부하자. 지금은 아니다.

【detectron2】Detectron2 Tutorial and Overview

아래의 과정을 하면 된다. 지금 코렙으로 밖에 작업하지 못해서 실제 내가 할 수 있는 작업은 굉장히 제한적이다.

1. INSTALL.md

  • Build Detectron2 from Source : $ pip install \<module_name\> -f \<url or path to an html file for parsing link to archives\>
  • Use the container(with docker ≥ 19.03). 이 과정은 docker를 사용하고 싶다.
    1. ml-workspace의 docker Image를 활용한 detectron2 모듈 설치
    2. detectron2 dockerfile을 사용한 $ docker build

2. Colab Notebook

  • 자세한 설명은 과거 detectiron2를 사용한 선박검출 프로젝트 이전 Post 참고
  • install
    1. pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.7/index.html
  • Inference
    1. cfg = get_cfg() (from detectron2.config import get_cfg)
    2. predictor = DefaultPredictor(cfg) (from detectron2.engine import DefaultPredictor)
    3. outputs = predictor(im)
    4. out = Visualizer.draw_instance_predictions(outputs[“instances”].to(“cpu”)) (from detectron2.utils.visualizer import Visualizer)
  • Train & Inference
    1. def get_balloon_dicts -> return: [ {‘file_name’: ~},{:height’: ~},{‘annotations’ : [{ }, { }] } ]
    2. DatasetCatalog.register(“balloon_” + d, lambda d=d: get_balloon_dicts(“balloon/” + d)) (from detectron2.data import MetadataCatalog, DatasetCatalog)
    3. change cfg like “cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1”
    4. trainer = DefaultTrainer(cfg) (from detectron2.engine import DefaultTrainer)
    5. %load_ext tensorboard
    6. predictor = DefaultPredictor(cfg)
    7. AP 계산하기 :
      from detectron2.evaluation import COCOEvaluator, inference_on_dataset
      from detectron2.data import build_detection_test_loader

3. Getting Started with Detectron2

  • $ python demo.py 실행법(webcam, video, cpu, save output 등..)
  • $ python train_net.py

4. Mask-rcnn \w code

  • 이 과정을 통해 detectron2 코드 내부를 좀 더 깊이 이해해보기

【In-Segmen】Understanding Mask-RCNN(+RPN) paper with code

  • 논문 : Mask R-CNN
  • 분류 : Original Instance Segmentation
  • 저자 : Kaiming He, Georgia Gkioxari (Facebook AI Research)
  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.
  • 읽으면서 생각할 포인트 : 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.
  • 느낀점 :
    1. RoIAlign 논문 보면 이해할 수 있게 만들어 놓은 줄 알았는데, 그렇지도 않다. 차라리 아래의 Post글을 보는게 훨씬 좋다. 이런걸 보면, 논문을 읽고, 나의 생각을 조금 추가해서 이해하는게 정말 필요한듯 하다. 논문에는 정확한 설명을 적어놓은게 아니므로.
    2. 논문 요약본 보다는, 직관적(intuitive) 이해를 적어놓은 유투브나, 아래의 Bilinear interpolation과 같은 블로그를 공부하는게 자세한 이해, 완벽한 이해를 가능케 하는 것 같다.
  • 내 블로그 관련 Post :
    • (1) Mask R-CNN by DVCR
      1. FCN : Pixel wise Classification
    • (2) Mask R-CNN Youtube 내용 정리
      1. bounding box 내부의 객체 class에 상관없이, Box 내부에 masking 정보만 따내는 역할을 하는 Mask-branch를 추가했다.
      2. Equivariance 연산(<-> Invariant)을 수행하는 Mask-Branch는 어떻게 생겼지? Mask-branch에 가장 마지막 단에 나오는 feature map은 (ROI Align이후 크기가 w,h라 한다면..) 2 x w * 2 x h * 80 이다. 여기서 80은 coco의 class별 mask 모든 예측값이다. 80개의 depth에서 loss계산은, box의 class에 대상하는 한 channel feature만을 이용한다. 나머지는 loss 계산시 무시됨.
      3. ROI Align 이란? : Input-EachROI. output-7x7(nxn) Pooled Feature. nxn등분(첫번째 quantization)->각4등분(두번째 quantization)->Bilinear interpolation->각4등분에 대해 Max Pooling->(nxn) Pooled Feature Map 획득.
    • (3) FCN
      1. 해당 이미지(필기 무시)를 확인해보면, 어디서 deconv(파라메터 학습 필요)를 사용하고, 어디서 Bilinear Interpolation이 이뤄지는지 알 수 있다.
      2. 최종 아웃풋 image_w x image_h x 21(classes+background)

1. Mask-RCNN

  1. Abstract, Introduction, Related Work
  2. Mask R-CNN
    • Mask Representation :
      1. mask-branch output : [m^2 x K channel] binary(sigmoid) mask (K-classes, mxm masks of resolution)
      2. fc layer를 사용하는 것보다, FCN 개념의 convolutions을 사용함으로써 더 좋은 결과. spatial dimensions information을 읽지 않을 수 있었다.
    • but Loss_mask is only defined on the k-th mask(K channel 중 k번째 채널)
    • RoIAlign : bilinear interpolation, ROI를 n x n으로 자른 후의 한 cell을 논문에서는 bin이라고 표현함. ROIAlign은 논문에서 이해할 수 없게 적어놓았다.
    • Network Architecture : straightforward structure bask-branch
    • RPN 개념은 faster-rcnn을 그대로 이용했으므로, mask-rcnn 코드를 보고 RPN의 활용을 좀 더 구체적으로 공부해 보자. faster-rcnn 논문 보지말고 이전 나의 블로그 포스트 참조(20-08-15-FastRCNN)
  3. 특히 Localization Loss function & default(Anchor) boxes about scales and aspect ratios 에 대한 내용은 SSD w/ code Post 를 참고 하면 좋은 이해가 가능하다.

2. Detectron2 - MaskRCNN

  1. Detectron2 전반적인 지식은 다음 게시물 참조 (Detectron2 Tutorial and Overview)
  2. config 파일 분석하기 - mmdetection에서는 py 파일의 dict 형식을 이용한 것과 다르게, yaml 형식 이용
    • image
  3. from detectron2.config import get_cfg 분석하기
    • detectron2/config/config.py : def get_cfg() -> CfgNode:
    • detectron2/config/config.py : class CfgNode(_CfgNode):
    • from fvcore.common.config import CfgNode as _CfgNode
    • facebookresearch/fvcorefvcore : github -> from yacs.config import CfgNode as _CfgNode
    • 즉 yacs 모듈을 이용한 config 파일 생성
    • 어렵게 생각할거 없이(중간과정 공부할 필요 없이), 나는 아래의 작업만 하면 된다.
      1. cfg = get_cfg() 로 생성한 변수 cfg에 들어가는 모든 변수 확인 (config/defaults.py)
      2. 여기서 필요한 cfg 자료만 수정하기
      3. 그 이후 detectron2의 모든 파일들은 cfg.DATALOADER.NUM_WORKERS 이와 같이 cfg파일 내부에 저장된 변수만 그대로 불러 사용한다. (그래서 더더욱 fvcore, yacs 몰라도 됨)
      4. self.model = build_model(self.cfg) (class DefaultPredictor: IN engine/defaults.py)
  4. class DefaultPredictor in engine/defaults.py
    • class DfaultPredictor에 대한 “”” 주석 설명 (defaults.py#L161- 별거없음)
    • def __init__(self, cfg) : self.model = build_model(self.cfg)
    • detectron2/modeling/meta_arch/build.py : def build_model(cfg): model = META_ARCH_REGISTRY.get(meta_arch)(cfg)
      • cfg.MODEL.META_ARCHITECTURE 에 적혀있는 model architecture 를 build한다. ( weight는 load하지 않은 상태이다. DfaultPredictor에서 model weight load 해준다. checkpointer.load(cfg.MODEL.WEIGHTS) )
      • from detectron2.utils.registry import Registry -> META_ARCH_REGISTRY = Registry("META_ARCH")
      • detectron2/utils/registry.py : from fvcore.common.registry import Registry
      • fvcore로 넘어가는거 보니… 이렇게 타고 가는게 의미가 없는 듯 하다.
    • 따라서 다음과 같은 디버깅을 수행해 보았다.
      image
    • model의 핵심은 GeneralizedRCNN 인듯하다. 따라서 다음의 파일을 분석해보기로 하였다.
      • detectron2/modeling/meta_arch/rcnn.py : class GeneralizedRCNN(nn.Module):
      • 이 과정은 다음을 수행한다
        1. Per-image feature extraction (aka backbone)
        2. Region proposal generation
        3. Per-region feature extraction and prediction
    • 여기까지 결론 :
      • 내가 원하는 것은, 원래 이해가 안됐다가 이해가 된 부분의 코드를 확인해 보는 것 이었다.(3.2 참조) 하지만 이 같은 코드 구조로 공부를 하는 것은 큰 의미가 없을 듯 하다.
      • 어쨋든 핵심은 detectron2/detectron2/modeling 내부에 있는 코드들이다. 코드 제목을 보고 정말 필요한 내용의 코드만 조금씩 읽고 이해해보는게 좋겠다. 여기있는 클래스와 함수를, 다른 사용자가 ‘모듈로써’ 가져와서 사용하기 쉽게 만들어 놓았을 것이다. 따라서 필요하면 그때 가져와서 사용해보자.

3. multimodallearning/pytorch-mask-rcnn

  1. Github Link : multimodallearning/pytorch-mask-rcnn

  2. 코드가 모듈화가 거의 안되어 있다. model.py에 거의 모든 구현이 다 되어 있다. 그래서 더 이해하기 쉽다.

  3. 아래의 내용들이 코드로 어떻게 구현되었는지 궁금하다.

    • (1) RPN-Anchor사용법
    • (2) ROI-Align
    • (3) Mask-Branch
    • (4) Loss_mask
    • (5) RPN의 output값이 Head부분의 classification/localization에서 어떻게 쓰이는지
  4. 원래는 공부하려고 했으나… 나중에 필요하면 다시 와서 공부하도록 하자.

  5. 2020.02.04 - RefineDet까지 공부하면서 코드를 통해서 헷갈리는 것을 분명히 파악하는 것이 얼마나 중요한 것인지 깨달았다. 따라서 그나마 가장 궁금했던 것 하나만 빠르게 분석하려고 한다.

  6. (5) RPN의 output값이 Head부분의 classification/localization에서 어떻게 쓰이는가?

    • RPN에서 나오는 2(positive, negative objectness score)+4(offset relative) = 6개의 정보.

    • 위에서 나온 ROI 중에서, 정말 객체가 있을 법한 정제된 ROI 즉 rpn_rois를 추출

    • rpn_rois에서 4(offset relative) 값만 이용한다. Backbone에서 나온 Feature Map에서 저 4(offset relative)에 대한 영역만 ROI Pooing (ROI Align)을 수행한다.

    • **pytorch-mask-rcnn/model.py ** 코드로 확인

    • # pytorch-mask-rcnn/model.py
           
      def proposal_layer(inputs, proposal_count, nms_threshold, anchors, config=None):
          """
          RPN에서 나온 결과들 중 정말 필요한 ROI만을 걸러주는 Layer
          아래의 (bg prob, fg prob) = (negative=easy confidence, pasitive=hard confidence)를 이용해서 적당한 
          Inputs:
              rpn_probs: [batch, anchors, (bg prob, fg prob)]
              rpn_bbox: [batch, anchors, (dy, dx, log(dh), log(dw))]
          Returns:
              Proposals in normalized coordinates [batch, rois, (y1, x1, y2, x2)]
          """
               
      outputs = list(zip(*layer_outputs)) # BackBone + RPN을 통과하고 나온느 결과들
      outputs = [torch.cat(list(o), dim=1) for o in outputs] 
      rpn_class_logits, rpn_class, rpn_bbox = outputs
           
      # rpn_rois 위의 함수에 의해 나온 정제된 rpn_rois 
      rpn_rois = proposal_layer([rpn_class, rpn_bbox],
                                proposal_count=proposal_count,
                                nms_threshold=self.config.RPN_NMS_THRESHOLD,
                                anchors=self.anchors,
                                config=self.config)
           
      # rpn_rois가 self.classifier에 들어가는 것에 집중
      if mode == 'inference':
          mrcnn_class_logits, mrcnn_class, mrcnn_bbox = self.classifier(mrcnn_feature_maps, rpn_rois)
               
      # rpn_rois가 detection_target_layer함수에 의해 rois가 되고, self.classifier에 들어가는 것에 집중
      elif mode == 'training':
          rois, target_class_ids, target_deltas, target_mask = detection_target_layer(rpn_rois, gt_class_ids, gt_boxes, gt_masks, self.config)
          mrcnn_class_logits, mrcnn_class, mrcnn_bbox = self.classifier(mrcnn_feature_maps, rois)    
      
    • # self.Classifier가 무엇인가? 
      self.classifier = Classifier(256, config.POOL_SIZE, config.IMAGE_SHAPE, config.NUM_CLASSES)
      # Line 908
      class Classifier(nn.Module):
          def forward(self, x, rois): # x : backbone 통과하고 나온 feature map
              x = pyramid_roi_align([rois]+x, self.pool_size, self.image_shape
              # ** [rois]+x 에 집중!! list에 append 되는 거다! **
      		# 그 이후 conv2 계속 통과...    
           
      def pyramid_roi_align(inputs, pool_size, image_shape):
      	"""
      	feature map을 받고 거기서 ROI Pooing => ROP Align 을 수행해 reture해주는 함수
           	
      	Inputs = [rois]+x 
                  Input[0] : refined boxes by 'proposal_layer' func - [batch, num_boxes, (y1, x1, y2, x2)
                  Input[1] : Feature maps - List of feature maps from different levels 
           	
      	Input[0] 가 가리키는 영역에 대해서 Input[1]에서 부터 ROI Aling(Pooing)을 수행한다. 
           	
      	return [pooled feature map : RPN이 알려준, Feature Map 중에서 '객체가 있을법한 영역'만 뽑아낸 조각난 Feature map]
      	"""
      

【Detection】Understanding SSD paper with code w/ my advice

  • 논문 : SSD: Single Shot MultiBox Detector
  • 분류 : Original Object Detection
  • 저자 : Wei Liu , Dragomir Anguelov, Dumitru Erhan , Christian Szegedy
  • 읽는 배경 : Recognition Basic. Understand confusing and ambiguous things.
  • 읽으면서 생각할 포인트 : 이전 나의 SSD 정리 Post, 코드와 함께 최대한 완벽히 이해하기. 이해한 것 정확히 기록해두기.
  • 느낀점 :
    1. 논문을 정말 깔끔하게 정리해놓은 사이트(SSD 분석)이 있다. 내용도 좋지만, 어떻게 논문을 정리 했는지를 참고하자. 지금은 논문을 추후에 작성하기 위해, 내용을 아주 짧게 요악하는 것 보다는 논문의 논리전개가 어떤지 기록하고 있다. 하지만 어느정도 익숙해지면, 이와 같은 논문 정리가 필요한 것 같다. 정말 핵심적인 내용만! 사실 논문이 말하는 ‘핵심’은 한 문단으로도 충분히 설명 가능하다. 그것만 기억해 두면 된다는 사실을 잊지 말자.
    2. 하지만 내가 위의 사이트를 참고하지 않는 이유는, 저런 논문 정리는 이미 많이 봤다. 내가 직접 논문을 읽고 도대체!! Bounding Box를 어떻게 사용하고, Loss함수를 어떻게 정의해서 사용하는지. 내가 직접 논문 읽고 이해하고 싶었기 때문이다.
    3. SSD논문 자체도 그리 자세하지 않다… 원래 논문이 이렇게 자세하지 않을 수 있나보다. 만약 논문을 읽으면서 완벽하게 이해되지 않았다면, (1) 논문에는 잘 적혀있는데 내가 이해하지 못했거나 (2) 논문이 원래 자세하지 않거나. 둘 중 하나이다. 따라서 논문을 읽고 100프로 이해가 안됐다고 해도, (2)경우일 수 있으니, 모른다고 좌절하지 말자.
  • 선배 조언
    1. 날 먼저 판단하지 마라. 박사나 석사나 학사나 똑같다. 동급이다. 누가 더 잘하고 못하고가 없다. 내가 궁금한 분야를 좀만 공부하면, 금방 그 이상의 실력을 가질 수 있다.
    2. 자신있게 하고 싶은걸 해라.
    3. 느낀점 :
      • 카이스트는 주중과 주말 상관없이 모든 사람이 열심히 공부하고 연구하고 그러는 줄 알았다. 하지만 내가 상상한 그 정도는 아니었다. 여기 계신 분들도 토일 쉬고 점심,저녁 2시간씩 쉬고 쉬고 싶은날 쉬고 그러시는 것 같다. (물론 집에서도 조금씩 공부하시지만..) 그러면 여기 계신 분들이 우리나라에서 많은 좋은 결과,논문들을 만들어 내는 이유가 뭘까? 생각해보았다. 그냥 맘먹으면 무언가를 해낼 수 있는 사람들이 모여있기 때문인 것 같다.(즉, 좋은 사람들이 함께 모여있기 때문.) 여기에 좋은 사람들이 너무 많다. 내가 노력하면 정말 좋은 conference의 논문에 2저자 3저자로 내가 들어갈 수 있게 해줄 똑똑한 사람들, 착한 사람들, 그리고 뭔가를 독하게 해본 사람들, 좋은 조언을 해줄 수 있는 사람들이 아주 많다. 이런 분들이 많이 보여 있기 때문에 나같은 후배들이 더 빠르게 위로 올라올 수 있는 것 같고, 그렇게 빠르게 올라온 사람들은 다음에 올 아래의 사람들(후배)들을 똑같이 빠르게 끌어올려 줄 수 있는 것 같다. 이런 ‘선 순환’으로 대한민국 최고의 대학이 될 수 있지 않았나 싶다. 절대적인 공부시간은 다른 대학의 사람들과 똑같다 할지라도.
      • 따라서. 나도 할 수 있다. 여기 계신 분들이 주말에는 푹 쉬고 점심저녁에 좀 놀고 가끔은 노는 시간에..! 나는 공부하고 공부하고 노력하면, 나도 충분히 여기 계신 분들처럼 좋은 결과를 내고, 좋은 논문을 낼 수 있겠다는 자신감이 생긴다. 지금은 여기 계신 분들보다 지식은 많이 부족해도. 여기 계신 그 어떤 분보다, 노력이 부족한 사람은 되지 말자. 따라잡고 싶으면, 보다 더 해야지. 닮고 싶다면, 더 일찍 더 늦게까지 공부해야지. 당연한거다.

1. Single Shot Detector - SSD

  1. Abstract, Introduction

  2. SSD

    • each default box를 통해서 예측하는 2가지. (1) the shape offsets relative and (2) the confidences

    • In Traning, Default Box와 GT Box를 matching값을 비교한다. 아래의 사진의 빨간색, 파란색 점선처럼 Positive인 것만을 다른다. 나머지는 Negative. 이다. 이때 사용하는 Loss함수는, localization loss (e.g. Smooth L1) and confidence loss (e.g. Softmax)
      image-20210130171652887

    • Positive에 대해서는 Confidence & regressing Loss를 모두 학습시키고, Negative에 대해서는 Confidence에 대해서만 학습 시킨다.

    • Predictions of detections at multiple scale object.

    • m × n with p channels의 feature map -> 3 × 3 × p small kernel -> m × n x (class confidence score + shape offset relative(GT에 대한 Default box의 상대적 offset값)) = [(c + 4)*k] channels

    • Training

      1. Matching strategy : IOU가 0.5 이상인 것만을 Positive로 사용했다. (그 이외 자세한 내용 없음)

      2. Loss 함수 이해하기

        • image-20210130192315918

        • N : positive dafault box 갯수 = the number of matched default boxes
          N이 0이면 loss는 0이다. (최저 Loss값 따라서 학습 이뤄지지 않음)
          k : category
          x : i번재 default box, j번째 GT box에 대한 매칭 값 {1 positive,0 negativ}
          l : the predicted offset relative
          g : the ground truth box
          d : the default bounding box 
          localization : For the center (cx, cy) and r its width (w) and height (h)
          
        • sharing parameters across all object scales (가장 마지막 단의 classification, localization에 대해)
    • default boxes about scales and aspect ratios

      • 논문에 나오는 ‘s와 m’에 대한 개념은 논문 보다, a-PyTorch-Tutorial-to-Object-Detection#priors에 더 잘 나와 있다.
        image
      • 핵심은 s (Prior Sclase) are precalculated. Feature Map Dimensions에 대해 한 1 x 1 cell이 이미지에서 몇 퍼센트 비율의 receptive field를 차지하는지를 대강 계산해서 표현해 놓은 값이다.
      • 논문과 위 사이트에 있는 수식들을 정리하면 아래와 같다.
      • image-20210130223712924
    • Hard negative mining : the negatives and positives is at most 3:1 비율 학습

    • Data augmentation - 정해진 몇가지 data augmentation 사용

  3. Experimental Results

2. mmdetection for SSD

  1. init_detector를 통해서 SSD inference 되는 과정
    1. def init_detector(config, checkpoint=None, device=’cuda:0’, cfg_options=None):
    2. model = build_detector(config.model, test_cfg=config.get(‘test_cfg’))
    3. def build_detector(cfg, train_cfg=None, test_cfg=None):
    4. return build(cfg, DETECTORS, dict(train_cfg=train_cfg, test_cfg=test_cfg))
    5. def build(cfg, registry, default_args=None):
    6. return build_from_cfg(cfg, registry, default_args)
    7. from mmcv.utils import Registry, build_from_cfg
    8. def build_from_cfg(cfg, registry, default_args=None):
    9. 후.. 여기까지. 일단 패스
  2. 아래의 과정을 통해 Config과정을 통해서 SSD가 이뤄지는지 보기 위한 작업들이다.
    image-20210130153957160
  3. 위의 결과를 통해 나는 이런 결과를 낼 수 있었다. mmdetection을 가지고 모델 내부 구조 코드를 볼 생각을 하지 말자.

3. lufficc/SSD

  1. 전체를 분석하는 것은 이전 Post SSD Pytorch Research 에 잘 기록해 두었다.
  2. 이번에 다시 보는 이유는, SSD paper를 읽고, SSD에서 이해가 안됐던 내용을 코드를 통해 공부하고, 혹은 이 논문 부분을 코드로 어떻게 구현했지? 를 알아보기 위해 공부한 내용을 정리하기 위함이다.
  3. 원래 이해가 안됐다가, 이해가 된 [(1)Localization Loss function 이해하기] [(2)default boxes about scales and aspect ratios] 는 코드에서 정확히 어떻게 구현되어 있는지 공부해 보자.
  4. 이라고 생각했으나, RetinaNet의 코드가 너무 깔끔하고 이쁘다.(물론 모듈화는 SSD이 코드가 더 잘되어 있지만.. 모듈화가 많이 되었다고 좋은 건 아닌 듯 하다. 코드를 처음 보는 사람이 머리 아프다.) 위의 (1)(2) 또한RetinaNet 코드로 대강 알 수 있기 때문에 그것을 보는게 더 좋을 듯 하다.
  5. 2021-02-04 : SSD 코드를 공부했을때 모듈화가 심각해서 보기가 힘들었다. 하지만 그것은 “처음부터 끝까지 다 봐야지.” 라는 욕심때문에 보기 힘들었던 것 같다. 하지만 사실 그렇게 코드를 보는 경우는 드믄것 같다. “내가 궁금한 부분만 찾아보거나, 내가 사용하고 싶은 모듈만 찾아서 사용한다.”라는 마음으로 부분 부분 코드를 본다면, 내가 원하는 부분을 전체 코드에서 찾는 것은 그리 어렵지 않다. 라는 것을 오늘 느꼈다.

【27살】대학원과 취업 그리고 나만의 연구분야 일기

대학원과 취업 그리고 나만의 연구분야에 관한 생각나는데로 써보는 일기…

2021년 1월 27일

이전의 2년전 고민이 무색하게, 그리고 대략 6개월 전 취업준비로 고생하며 자존감이 떨어지던 시기가 무색하게 어느덧 대한민국 최고의 카이스트 비전 연구실에 와 있고, 어느덧 모비스 연구원으로 취업이 되어 있었다. 그때는 그렇게 힘들고 걱정과 고민이 많았는데 지금 이렇게 잘 된거를 생각하면 너무너무 행복하고 감사하다. 이 감사함과 행복을 잊지 않도록 노력해야겠다.

최근에 연구실에서 거의 하루 14시간을 공부하며 하루하루를 보내고 있는데, 흥미롭고 재미있지만 똑같은 일상에 지칠 수도 있겠다는 생각이 들 때도 있었다. 근데 위와 같이 다시 생각해보면, 지금 나의 상황이 얼마나 행복하고 즐거운건지를, 그리고 저렇게 생각하면 안된다는 사실을, 다시 한번 깨닫는다.

정말 가끔 블로그나 어떤 경로를 통해서 메일로 진로 상담을 요청하시는 분들이 계신다. 그 분들은 나를 엄청나게 대단한 사람으로 생각하고 자신의 고민에 대해서 말씀해 주신다. 사실은 나도 그렇게 대단한 사람도 아니다. 그저 행운이 많이 좋아서 카이스트에 올 수 있었고, 모비스에 올 수 있었던 건데 말이다. 물론 이충권 선생님이 가르쳐주신 깨달음으로 20살때 부터 항상 최선을 다해서 살아온 것은 맞다. 학점도 활동 경험도 그리고 지금의 연구실과 취업의 결과도 다 그 덕분이다. 하지만 이게 그렇게 대단한 건가? 나는 아니라고 본다. 왜냐면 나는 천재가 아니고 많이 노력파이기 때문이다. 따라서 다른 누군가가 정말 그냥 주어진 하루하루를 최선을 다해 살아가고 노력한다면 누구든 원하는 곳에 취업하고 원하는 대학원에 입학할 수 있다고 생각한다. 하지만 거기에는 ‘행운’이라는 요소가 생각보다 많이많이 필요하다.

행운은 어떻게 얻을 수 있을까? 그것에 대한 답변은 이 동영상을 통해 얻을 수 있다. 이충권-나는운이좋다 적당히 내용을 요약하자면, ‘나는 운이 좋다. 나는 운이 정말 좋다. 모든 일은 내뜻대로 된다.’라고 생각하고 행복하고 즐거운 마음으로 하루하루를 열심히 살아가는 사람에게 행운이 따라온다.라는 이야기 이다. 나는 이것을 믿는다. 책 The secret이라는 정말 소중한 책이 있다. 이 책은 내가 가장 좋아하는 책이다. 이 책에 따르면 ‘바라고 믿고 행복해져라’라고 말한다. 정말 내가 바라고 그것이 이뤄질 수 있다고, 나는 운이 좋다고, 그렇게 무조건 될거라고 생각하며 기쁨과 행복을 느끼면, 정말 내가 바라는 것이 이뤄진다는 마법같은 이야기다. 누구는 이 이야기가 ‘사이비같은 이야기다. 말도 안된다.’라고 생각하지만, 나는 그런 사람과 어울리고 싶지도 않고, 대화도 하기 싫고, 가까이 하고 싶지도 않을 정도로, 저 내용을 절실하게 믿는다. 왜냐면 내가 그 산 증인이니까. 따라서 나는 앞으로도 바라고 믿고 행복할 것이다. 나는 200% 믿는다.

그렇게 해서 나는 (사실 정말 될까? 라고 의심은 조금했었지만, 정말 마법처럼) 원하는 최고의 연구실에 왔고, 취업에 성공했다. 내 이야기가 아닐것만 같았던, 현대모비스 계약학과 장학생이 정말 나의 것이 되었다. 다시 생각해봐도 정말 감사하고 소중하고 행복 하다. 정말 감사하게 연구하고 공부해야겠다. 하루하루 최선을 다해서 꾸준히 해 나간다면, 처음에는 모르고 혹은 어렵다고 느껴질지도 몰라도, 결국에는 깨닫고 재밌어 질 것을 나는 안다. 선생님은 말씀하셨다. ‘세상에 어려운 것은 없다. 니가 모를 뿐이다. 모르면 배우면 된다. 모르면 물어보면 된다. 모르면 공부하면 된다. 우울하고 좌절할거 하나 없다.

이런 나의 긍정적인 생각과 마음이, 나의 소중하고 사랑하는 사람들에게 전해지리라고 믿고, 그리고 이 글을 읽고 있는 독자분들에게도 전해지리라고 믿는다. 내 주변 모든 사람에게 행복과 기쁨 그리고 행운이 가득하길 바라고 정말 그렇게 되리라 믿는다.

다음에 시간적 여유가 생기면, 현대모비스 계약학과 학생이 되기까지의 준비과정과 노력들에 대해서도 간략하게 적어보려고 한다. 유투브 보고 시간 버리는 시간에 재미로 작성해 볼 계획이다. 그렇게 적어놓는 것이 나에게도 좋을 것이라 생각한다. 내가 어떤 노력을 했는지 어떤 과정을 거쳤는지 기록해 놓을 수 있고, 가끔 생각날 때 읽을 수 있을 테니까.


연구분야에 대한 고민

나의 연구분야에 대해서 진지하게 고민해볼 때가 온 것 같다. 이제는 누구에게 물어보고 조언을 구해서 답변을 정해야 하는 때가 아니다. 마음이 디죽박죽이고 생각이 디죽박죽이여서 이것을 정리해 보고 싶어서 이렇게 일기를 작성한다. 아무래도 사적인 이야기보다는 공부와 연구에 관한 주제이기 때문에 블로그에 기록하는게 낫다고 생각했다. 그래야 나중에 좀 더 쉽게 찾아볼 수 있으니까.ㅎㅎ

이런 고민을 시작하게 된 이유는 다음과 같다. 최근 나는 Domain adaptation, Self-supervised learning에 관련된 공부를 하고, 이와 관련된 논문을 읽어왔다. 물론 내가 이 분야에 관심이 있어서 읽은 이유도 있지만.. 아무래도 연구실 내의 연구원분들이 최근 이 분야에 대해서 많이 연구하기기 때문에, 교수님께서 Self-supervised에 관심이 많으시기 때문에. 이의 논문들을 읽었다. 하지만 이 논문들을 읽으면 마음한 구석에 이런 생각이 들었다. ‘근데 이거 정말 내가 활용할거 맞아? 에이 설마 이 논문내용을 딱 사용하겠어? 이 논문 내용을 어떻게 실용적으로 현실적으로 사용하지?’ 라는 생각을 하였다. 뭔가 눈 앞에 떡이 있는데 먹지는 않고 바라만 보고 냄새맡고 눌러보기만 하는 느낌이었다.

오늘 새로운 논문을 읽으려는데 최근 위와 같은 생각과 느낌 때문에, 갑자기 나는 이런 생각을 했다. ‘오늘은 무슨 논문 읽지? 하 그냥 나도 내가 관심있는 분야를 딱 정해서 그거를 한번 미친듯이 파볼까? 관련된 논문을 줄구장창 읽어볼까?’ 따라서 지금 나에게 가장 중요한건 그냥 눈에 보이는데로 논문을 읽는 것 보다는 나의 흥미분야가 무엇이고, 나의 연구 스토리로 가져갈 핵심 주제를 무엇으로 할지를 정하는 것이다.

나는 관심을 가지는 연구주제가 몇가지 있긴하다. 하지만 솔직히 말해서.. 사실 나는 나의 연구주제를 확정하기 무섭다. 두렵다. 내가 정한 연구주제가 유용한 주제인지, 그리고 나중에 미래에 가서 그 지식이 쓸모가 있을지, 내가 공부한 것들이 잘 한 것이고 ‘공부하기 잘했다.’라고 생각이 들만한 것인지 확정할 수 없기 때문에… 나는 연구주제를 한가지 정해서 파는게 사실 두렵고 무섭다.

이 질문에 대해, 내가 나에게 해줄 수 있는 답변은 이와 같다. 이전의 선배님의 말씀처럼

어떤 분야를 딱 정해서 미친듯이 공부한다고 해도 공부의 왕도와 끝은 없다. 너무 걱정하고 조급해하지 말고 꾸준하게 흥미를 가지는 연구에 대해서 차곡차곡 읽어나가자. 딱 정해진 연구분야에 관련된 논문만 읽어야 하는 것은 아니다.

예를 들어서 3D-Detection, Instance Segmentation 논문을 읽다가, 중간중간 심심하면 Domain Adaptation에 관련된 논문도 읽고 Self-Supervied에 관한 논문도 읽으면 되는거다. 혹은 3D-Detection, Instance Segmentation에 관련된 논문을 1달~2달정도 매일매일 읽고 어느정도 이 분야에 대해서 도가 트이면 Domain Adaptation, Self-Supervied에 대해서도 똑같이 도가 트일 정도로 논문을 읽으면 되는거다.

the devil in the boundary논문도 그렇게 Video Panoptic Segmentation 논문도 그렇게 선배님들이 모두모두 domain-adaptation, self-supervised에 대한 연구만 하시는게 아니다. 심지어 TPLD 논문도 sementic segmentation에 대한 내용을 베이스로 깔고 있다. 이렇게 선배님들도 기본적인 recognition에 대한 논문 지식들은 모두 가지고 있는 상태에서 저러한 Hot한 주제의 내용을 가미해서 논문을 만드시는 것이라고 생각한다면, 내가 지금 당장 Object detection, Segmentation 논문들을 읽으며, ‘패러다임이 또 바뀔텐데.. 굳이? 이거 나중에 계속 쓰이려나? 이거 그냥 의미없는 SOTA싸움 아니야? 지금 핫한건 domain, self-supervise인데 ‘ 생각을 할 필요가 없다. 그냥 시간나는대로 보고 읽으면 된다.

일단 아래 방법으로 나아가 보자.

  1. Object Detection에 대해서 먼저 좀 알자 ex) Yolo_v4와 다른 논문들
  2. Instace Segmentation에 대해서도 쭉쭉 읽어나가자.
  3. 3D object detection 에 대해서 공부하지(3D-detection, 3D-detection from stereo Image)
    • 가능하면 Github로 찾아보고, paperswithcode에서 찾아서 공부하자.
    • 논문과 코드를 동시해 이해하자.
  4. 중간중간 추천이 들어오는 domain adaptation, self-supervised에 대한 논문이 있다면 그것도 또 읽자.
  5. 혹은 ‘이 분야에 대해서는 너무 심각하게 모른다.. Overview에 대한 지식이 너무 없는데?’ 라는 생각이 들면, 관련된 google 정리 post를 보거나, survey논문을 보거나, 관련 탑 티어 논문을 읽어보면 되는거다.
  6. 3번까지 어느정도 도가 트이면 domain adaptation, self-supervised 내용에 대해서도 도가 트일 수 있도록 논문읽으며 다시 집중해서 읽어보면 된다.
  7. 일주일에 한 두번씩은 한동안은 무슨 논문 읽지~ 하면서 2개,3개 정도 만 정해두고 논문을 읽다가 나오는 reference paper를 보고, 이 논문도 읽어야 겠다. 라는 생각이 들면 나중에 천천히 그것도 읽으면 되는거다.

1과 2번을 하다 보면 정말 끝도 없을 것이다. 이때 중요한 것은 왕도가 있다고 생각하지 않는 것과 끝장을 내버리고 모든것을 다~읽어버리겠다 라는 생각을 하지 않는 것이다. 항상 마음을 편하게 가지고 그냥 하루하루 끌리는 논문을 읽으면 되는거다. “나는 이걸 다 읽어야 해. 내가 읽을게 이렇게 많아? 이거 언제 다 읽지… 저 주제도 좋은 것 같으니, 저것도 해야할 것 같은데 그건 또 언제 하지” 라는 생각은 절대절대절대 할 필요가 없다. 그냥 하루하루 끌리는 주제와 논문을 꾸준히 하나씩 읽어가면 될 뿐이다. 흥미를 가지고, 꾸준히. 조급해지지 말고, 연구가 일이 되어 재미가 없어지지 않도록. 질리지 않도록.


우선 모비스 배치상담서에는 다음과 같은 내용을 기제했었다. 2021년 1월 25일의 나는 어떤 생각과 희망분야, 관심분야를 가지고 있었는지 기록해 두고자 남겨둔다.

  1. 연구실 주요 연구분야
    • 인식 안정성 확보를 위한 머신 러닝 연구 : 1) 데이터 부족 문제(Data hungry), 2) 현실 세계 일반화, 3) 인식 강건성 확보와 같은 도전과제를 해결하며, 인식 모델의 안정성을 확보하기 위한 연구. Domain adaptation, Semi-supervised Learning, Self-supervised learning, Attention module 연구
    • 딥러닝을 이용한 컴퓨터 비전 연구 : 영상 내 객체 탐지(localization)와 객체 인식(detection)을 위한 연구. Visual recognition, Image segmentation(영상 분 할), Object detection, Multi object tracking(다중 객체 추적), 3D object detection, Object depth estimation과 같은 컴퓨터 비전 딥러닝 연구
    • 인식 어플리케이션 및 지능형 로봇 개발 연구 : 카메라 영상, RGB-D 카메라, 적외선 카메라를 활용한 인식 어플리케이션 개발 연구 및 과제 수행. 인식 결과를 활용하는 지능형 로봇 개발 연구.
  2. 희망분야 / 관심분야
    • 주석 처리된 데이터 부족 문제, 도메인 변화로 인한 인식 모델 성능 하락 문제들을 해결하기 위한, 인식 모델 안정성 확보 연구 (Self-supervised learning and Domain Adaptation)
    • 다중 카메라를 활용한 3차원 객체(보행자, 주변 차량) 탐지 및 인식 연구 (Object localization and detection)
    • RGB-D 카메라 또는 적외선 카메라를 융합한 영상 분할(Instance segmentation) 연구 및 객체 탐지 연구
  3. 학위 예상 논문명
    • Robust depth completion & 3D object detection for Unsupervised Domain Adaptation (비지도 학습 도메인 적응 기법을 활용한 환경 변화에 강건한 3차원 객체 탐지 및 깊이 추론 연구)

【ClassBlance】Large-Scale Long-Tailed Recognition in an Open World = OLTR w/ advice

  • 논문 : Large-Scale Long-Tailed Recognition in an Open World - y2019-c103
  • 분류 : Unsupervised Domain Adaptation
  • 저자 : Ziwei Liu1,2∗ Zhongqi Miao2∗ Xiaohang Zhan1
  • 읽는 배경 : (citation step1) Open Componunt Domain Adaptation에서 Memory 개념이 이해가 안되서 읽는 논문.
  • 읽으면서 생각할 포인트 : 논문이 어떤 흐름으로 쓰여졌는지 파악하자. 내가 나중에 쓸 수 있도록.
  • 동영상 자료
    • image-20210126160627433
  • 질문
    • centroids메모리 M을 어떻게 학습시키는지는 아직 모르겠다. 이것은 코드를 통해서 공부하면 될듯.
      OLTR/models/MetaEmbeddingClassifier.py 파일에 forward의 input으로 centroids가 들어가는 것을 확인할 수 있다.
  • 선배님 조언
    • 외국에서 사는게 그리 좋은게 아니다. 우리나라 라는 것이 얼마나 큰 축복인지 모른다. 기회가 있다면 나가서 일하고 나중에 다시 돌아오면 된는거다. 우리나라에 대해서 감사함을 가지고 살아가도록 해야겠다.
    • 특히나 외국에서 오래 살고 오셨기 때문에, 저 진심으로 해주시는 조언이었다. 그냥 큰 환상을 가지고 거기서 살고 싶다 라는 생각을 해봤자 환상은 깨지기 마련이고, 우리나라 안에서, 우리나라가 주는 편안함과 포근함에 감사하며 살아가는게 얼마나 큰 축복인지 알면 좋겠다. 모비스와 다른 외국 기업과의 비교를 생각하며 감사할 줄 몰랐다. 하지만 감사하자. 모비스에 가서도 정말 열심히 최선을 다해, 최고가 되기 위해 공부하자. 그렇게 해야 정말 네이버든 클로버든 갈 수 있다. 그게 내가 정말 가야할 길이다. 그러다가 기회가 되어 외국 기업이 나를 부른다면, 다녀오면 된다. 그리고 또 한국이 그리워지면 다시 돌아오면 되는거다. 나의 미래를 좀 더 구체적으로 만들어 주신 선배님께 감사합니다.
    • 학교에서 너무 많은 것을 배우려고 하지 마라. 수업은 그냥 쉬운게 짱. 하고 싶은 연구하고 하고 싶은 공부하는게 최고다. 그리고 동기와 친구와 같이 수업 듣는 것을 더 추천한다.

느낀점

  1. Instruction이 개같은 논문은..
    • abstract 빠르게 읽고, Introduction 대충 읽어 넘겨야 겠다. 뭔소리하는지 도저히!!!!!! 모르겠다.
    • 지내들이 한 과정들을 요약을 해놨는데.. 나는 정확히 알지도 못하는데 요약본을 읽으려니까 더 모르겠다.
    • 따라서 그냥 abstract읽고 introduction 대충 모르는거 걍 넘어가서 읽고.
    • relative work의 새로운 개념만 빠르게 훑고, 바로 Ours Model에 대한 내용들을 먼저 깊게 읽자. 그림과 함께 이해하려고 노력하면서.
    • 그리고! Introduce을 다시 찾아가(👋) 읽으며, 내가 공부했던 내용들의 요약본을 읽자
  2. 아무리 Abstract, Instruction, Relative work를 읽어도, 이해가 되는 양도 정말 조금이고 머리에 남는 양도 얼마 되지 않는다. 지금도 위 2개에서 핵심이 뭐였냐고 물으면, 대답 못하겠다.
    • 현재의 머신러닝 논문들이 다 그런것 같다. 그냥 대충 신경망에 때려 넣으니까 잘된다.
    • 하지만 그 이유는 직관적일 뿐이다. 따라서 대충 이렇다저렇다 삐까뻔쩍한 말만 엄청 넣어둔다. 이러니 이해가 안되는게 너무나 당연하다.
    • 이런 점을 고려해서, 좌절하지 않고 논문을 읽는 것도 매우 중요한 것 같다. (👋)여기 아직 안읽었다고??? 걱정하지 마라. 핵심 Model 설명 부분 읽고 오면 더 이해 잘되고 머리에 남는게 많을거다. 화이팅.
  3. 확실히 Model에 더 집중하니까, 훨씬 좋은 것 같다. 코드까지 확인해서 공부하면 금상첨화이다. 이거 이전에 읽은 논문들은, 그 논문만의 방법론에는 집중하지 못했는데, 나중에 필요하면 꼭! 다시 읽어서 여기 처럼 자세히 정리해 두어야 겠다.
  4. 이 논문의 핵심은 이미 파악했다. 👋 읽기 싫다. 안 읽고 정리 안했으니, 나중에 필요하면 참고하자. 명심하자. 읽을 논문은 많다. 모든 논문을 다 정확하게 읽는게 중요한게 아니다.

0. Abstract

  • the present & challenges
    1. Real world data often have a long-tailed and open-ended distribution. 즉 아래의 그래프의 x축은 class종류를 데이터가 많은 순으로 정렬한 것이고, y축은 해당 클래스를 가지는 데이터 수. 라고 할 수 있다. Open Class는 우리가 굳이 Annotate 하지 않는 클래스이다.
    2. image-20210126154310688
  • Ours - 아래 내용 요약

1. Introduction

  • the past
    • 대부분의 기법들은 Head Class 인식에 집중하지만,
      최근 Tail class 문제를 해결하기 위한 방법이 존재한다. (=Few-shot Learning)for the small data of tail classes [52, 18]
  • Ours
    • 우리의 과제(with one integrated algorithm)
      1) imbalanced classification
      2) few-shot learning
      3) open-set recognition
      즉. tail recognition robustness and open-set sensitivity:

    • Open Long-Tailed Recognition(OLTR) 이 해결해야하는 문제
      1) how to share visual knowledge(=concept) between head and tail classes (For robustness)
      2) how to reduce confusion between tail and open classes (For sensitivity)

    • 해결방법

      • 2번째 페이지 We develop an OLTR 문단부터 너무 이해가 어렵다. 따라서 일단 패스하고 다시 오자. 요약본이니, 구체적으로 공부하고 나면 이해하기 쉬울 거다. 👋

      • # 이전에 정리해 놓은 자료. 나중에 와서 다시 참조.
        1 mapping(=dynamic meta-embedding) an image to a feature space  = **a direct feature** computed(embeded) from the input image from the training data   
        2) visual concepts(=visual memory feature) 이 서로서로 연관된다.(associate with) = A visual memory holds **discriminative centroids**     
        3) A summary of **memory activations** from the direct feature   
        그리고 combine into a meta-embedding that is enriched particularly for the tail class.
        
    • .

    # 2. Related Works

    image-20210126181200150

  • Imbalanced Classification

    • Classical methods - under-sampling head classes, over-sampling tail classes, and data instance re-weighting.
    • Some recent methods - metric learning, hard negative mining, and meta learning.
    • Ours
      • combines the strengths of both metric learning[24, 37] and meta learning[17, 59]
      • Our dynamic meta-embedding~~~ 👋
  • Few-Shot Learning

    • 초기의 방법들 they often suffer a moderate performance drop for head classes.
    • 새로운 시도 : The few-shot learning without forgetting, incremental few-shot learning.
    • 하지만 : 위의 모든 방법들은, the training set are balanced.
    • In comparison, ours~~~ 👋
  • Open-Set(new data set) Recognition

    • OpenMax [3] : calibrating the output logits
    • OLTR approach incorporates~~ 👋

3. Our OLTR Model

image-20210126184016363

  • 우리 모델의 핵심은 Modulated Attention 그리고 Dynamic meta-embedding 이다.
    • dynamic Embedding : visual concepts(transfers knowledge) between head and tail
    • modulated Attention : discriminates(구분한다) between head and tail
    • reachability : separates between tail and open
  • Our OLTR Model
    • We propose to map(mapping하기) an image to a feature space /such that visual concepts can easily relate to each other /based on a learned metric /that respects the closed-world classification /while acknowledging the novelty of the open world.

3-1. Dynamic Meta-Embedding

  • combines a direct image feature and an associated memory feature (with the feature norm indicating the familiarity to known classes)

    • CNN feature 추출기 가장 마지막 뒷 단이 V_direct(linear vector=direct feature)이다. (classification을 하기 직전)
    • tail classes(data양이 별로 없는 class의 데이터)에는 사실 V_direct이 충분한 feature들이 추출되어 나오기 어렵다. 그래서 tail data와 같은 경우, V_memory(memory feature) 와 융합되어 enrich(좀더 sementic한 정보로 만들기) 된다. 이 V_memory에는 visual concepts from training classes라는게 들어가 있다.
  • Learning Visual Memory (M)

    • [23] 이 논문의 class structure analysis and adopt discriminative centroids 내용을 따랐다.
    • image-20210126205303346 여기서 K는 class의 갯수이다.
    • M은 V_direct에 의해서 학습이 된다. centroids 정보가 계속적으로 Update된다고 한다. 여기서 centroids정보는 아래의 삼각형 위치이다. 아래의 작은 동그라미가 V_direct 정보이고, 그것의 중심이 centroids가 된다.
    • 이 centroids는 inter-class에 대해서 거리가 가장 가깝게, intra-class에 대해서는 거리가 최대한 멀게 설정한다.
    • image-20210126205524272
    • centroids를 어떻게 계산하면 되는지는 코드를 좀만 더 디져보면 나올 듯하다. 아래 python코드의 centroids가 핵심이다. centroids는 model의 forward 매개변수로 들어온다.
  • Memory Feature (V_memory)

    • O : V_direct와 i번째 클래스간의 상관계수(coefficients hallucinated(상관관계라고 환각이 느껴지는 단순한 Fully Conected Layer….))를 의미한다.

    • V_memory는 아래의 코드처럼 M과 O를 torch.matmul해서 만들어 낸다. image-20210126205902226

    • Github Link

      • # set up visual memory . [M 만들기]
        x_expand = x.clone().unsqueeze(1).expand(-1, self.num_classes, -1)
        centroids_expand = centroids.clone().unsqueeze(0).expand(batch_size, -1, -1)
        keys_memory = centroids.clone()
              
        # computing reachability
        dist_cur = torch.norm(x_expand - centroids_expand, 2, 2)
        values_nn, labels_nn = torch.sort(dist_cur, 1)
        scale = 10.0
        reachability = (scale / values_nn[:, 0]).unsqueeze(1).expand(-1, feat_size)
              
        # computing memory feature by querying and associating visual memory
        # self.fc_hallucinator = nn.Linear(feat_dim, num_classes)
        values_memory = self.fc_hallucinator(x.clone())
        values_memory = values_memory.softmax(dim=1)
        memory_feature = torch.matmul(values_memory, keys_memory)
        
  • V_meta

    • image-20210126212730673
    • V_meta이 정보가 마지막 classifier에 들어가게 된다.
    • image-20210126214602677
    • 왼쪽 이미지 처럼, 그냥 V_direct를 사용하면, inter-class간의 거리가 멀리 떨어지는 경우도 생긴다.
    • 오른쪽 그림은, V_meta를 확인한 것인데, inter-class간의 거리가 더 가까워진 것을 확인할 수 있다.
  • Reachability (γ)

    • closed-world class에 open-world class를 적용하는데 도움을 준다.
    • 공식은 이와 같고, image-20210126213933294
    • 이것이 의미하는 바는, class 중에서 어떤 class의 centroids와 가장 가까운지 Open-world data의 V_direct와 비교를 하는 것이다. 가장 가까운 class에 대해서(γ 작음) V_meta에 큰 값을(1/γ큼) 곱해 주게 된다.
    • 이것은, encoding open classes를 사용하는데에 더 많은 도움을 준다.
  • e (concep selector)

    • head-data의 V_direct는 이미 충분한 정보를 담고 있다. tail-data의 V_direct는 상대적으로 less sementic한 정보를 담고 있다.
    • 따라서 어떤 데이터이냐에 따라서 V_memory를 사용해야하는 정보가 모두 다르다. 이런 관점에서 e (nn.Linear(feat_dim, feat_dim)) 레이어를 하나 추가해준다.
    • 따라서 e는 다음과 같이 표현할 수 있다. image-20210126214446182
  • dynamic meta-embedding **facilitates feature sharing** between head and tail classes

3-2. Modulated Attention

  • Modulated attention : encourages different classes to use different contexts(attentions), which helps maintain the discrimination between head and tail classes.
    • image-20210126215731407
  • V_direct를 head와 tail class 사이, 그리고 intra-class사이의 차이를 더 크게 만들어 주는 모듈이다. 위의 이미지에서 f가 f^(att)가 되므로써, 좀 더 자신의 class에 sementic한 feature를 담게 된다. 이 attention모듈을 사용해서 f에 spatial and different contexts를 추가로 담게 된다.
  • 아래의 Attention 개념은 논문이나, 코드를 통해 확인
    • SA : self-correlation, contextual information [56]
    • MA : conditional spatial attention [54]
  • image-20210126223121413 여기서 f는 CNN을 통과한 classifier들어가기 바로 전.
  • 이 개념은 다른 어떤 CNN모듈에 추가해더라도 좋은 성능을 낼 수 있는 flexible한 모듈이라고 한다.

3.3 Learning

  • cosine classifier [39, 15]를 사용한다. 해당 논문 2개는 few-shot 논문이다.
  • 이 방법은 아래의 방법을 사용하는 방법이다. V_meta와 classifier의 weight까지 normalize한다.
    • image-20210126223459717
    • 이러한 normalize에 의해서, vectors of small magnitude는 더 0에 가까워지고, vectors of big magnitude는 더 1에 가까워 진다. the reachability γ 와 융합되어 시너지 효과를 낸다고 한다.

3.4 Loss function

  • image-20210126223657868
  • cross-entropy classification loss, large-margin loss
  • 내 생각. 위 식의 v^meta는 classification이 된 결과를 말하는 것일 것이다. vector_meta가 아니라.
  • 오른쪽 loss항을 통해서, the centroids {ci} K i=1 를 학습 시킨다.
  • 자세한 loss 함수는 부록 참조
    • image-20210126223905835

4. Experiments

  1. Datasets
    • Image-Net2012를 사용해서 head와 tail을 구성시킨다. 115.8k장의 이미지. 1000개의 카테고리. 1개의 카테고리에 최대 이미지 1280개, 최소 이미지 5개로 구성한다.
    • Openset은 Image-Net2010을 사용하였다.
  2. Network Architecture - ResNet 사용
  3. Evaluation Metrics
    • the closed-set (test set contains no unknown classes)
    • the open-set (test set contains unknown classes)
    • Train을 얼마나 반복해서 시켰는지에 따라서, many-shot classes / medium-shot classes / few-shot classes를 기준으로 accuracy를 비교해 보았다.
    • For the open-set setting, the F-measure is also reported for a balanced treatment of precision and recall following [3]. (혹시 내가 Open-set에 대한 accuracy 평가를 어떻게 하는지 궁금해 진다면 이 measure에 대해서 공부해봐도 좋을 듯 하다.)
  4. Ablation Study / Result Comparisons / Benchmarking results

【How-paper】Behnam Neyshabur's advice on how to write a paper.

은환이의 도움으로 아래의 트위터 글에 대해서 알 수 있었다.

https://twitter.com/bneyshabur/status/1349225440435728385

좋은 conference에 논문을 내보지 않은 학생들에게 좋은 추천을 해주는 글들이 있었다.

이 내용을 정리해 보려고 한다.

Long thread at the risk of being judged

  1. 급하게 아슬아슬하게 쓴 paper가 Top-conf에 accept가 되고 나서, 아래의 내용들을 깨달을 수 있었다.
  2. 이건 운 or 논문의 질로 설명할 수 있는게 아니다. 내가 믿기로, 현재의 학회 시스템은 많은 불필요성을 가지고 있으며 해롭고 불공평한 편향들이 존재한다. 특히 새로 이 영역에 들어오는 사람들이나 규범을 지키지 않는 다른 사람들에게는 매우 불공평하다.
  3. 이러한 문제가 있는 체계에서 나의 논문과 연구를 지키기 위해 했던 노력들을 공유합니다. 더 많은 방법이 있기는 하지만 나중에 공유하겠습니다.

Writing the paper

  1. ” Make your paper look similar to a typical ML paper.” 아무리 강조해도 지나치지 않다. Figure, table 모두 비슷해야한다. abstract, introduction, phrases, organiation 모두 모두.
  2. reviewer가 short attention span(짧은 시간의 집중) 하도록 만들어라. reviewer는 5분안에 main results를 알고 싶어 한다. 그니까 abstract 쓰는데 가장 많은 시간을 투자해라. 그리고 first figure & contribution section에 많이 투자해라. 첫인상이 가장 중요하다!
  3. reviwer들은 combination of theory + experiments을 사랑한다. 이론적인 내용을 쓰고 싶다면 실험도 꼭 추가하고, “if you are writing an empirical paper, Try to add a theoretical component
  4. cite(참고하고 인용해라) many papers! 관련된 최대한 많은 논문을 읽고, generous하고 만들어라. 많은 cite를 하고 reviewer들에게 credit을 주어라.

About rebuttal

  1. In your response to reviewers, be very nice to all of them even those who have attacked you unfairly. 공격적이지 않게, 나의 관점에서 반박된 문제에 대해 설명하고, 당신의 답변이 reviewer가 방어적인 위치에 있도록 두어서는 안됩니다.
  2. reviewer’s concern을 해소하기 위해서, 내가 추가적인 어떤 것을 했다고 보여주어라. (even if you disagree) score를 올려줄 이유를 줄것이다.
  3. 너의 답변 끝에, 어떻게 하면 접수를 올릴 수 있는지 reviewer에게 정확하게 물어봐라. 정중하고 존경스럽게 물어봐라. 분명하고 명확하게 행동하는 것이 큰 차이를 만든다.
  4. 너의 paper가 accept되지 못했다면, AC에게 너가 이 상황을 어떻게 바라보는지 적어놓아라. 만약에 리뷰어가 이 논문을 이해하지 못한것 같고 리뷰어가 unreasonable, 하다면 이 상황을 AC에게 알려라. AC로써 나는 저자로부터 오는 direct message에 많은 관심을 가진다.
  5. AC에게 글을 쓸 때, 나의 논문이 accepted되어야 한다고 설득시키듯이 메세지를 적어라. 주요 공헌을 설명하고, 나의 관점에서 논문 reviews and response에 대한 정보를 주기 위해 노력하세요.
  6. rebuttal letter, message to AC를 쓸 때, 그들의 집중가능 시간이 매우 짧다는 것을 인지하고, Try to highlight your main message first, go to details next and end with a conclusion.

느낀점

  1. 지금 당장은 필요한 내용은 아니 것 같다.
  2. 당연하면서도, 꼭 명심해야할 내용인 듯 하다.
  3. 나중에 필요하면 다시 읽어보자.
  4. 그래도! 최근 논문을 자주 cite&read하고 immitation 하고, reviewer에게 credit을 줄 수 있게 지금부터 주의하면서 논문 읽자.

【CV】Computer Vision at FastCampus3, chap11~13

  1. FastCampus 사이트의 Computer vision 강의 내용 정리
  2. 구글링을 해도 되지만은, 필요하면 강의를 찾아서 듣기
  3. FastCampus - Computer vision Lecture
  4. 이전 Post Link

chap11 - Machine Learning

  1. 머신러닝 이해하기

  2. OpenCV 머신 러닝 클래스

    • image-20210131104310345
    • 위의 어떤 방법으로 머신러닝 알고리즘 객체를 생성한 후, train(), predict() 함수를 사용하면 된다.
    • cv2.ml_StatModel.train(samples, layout, responses)
    • cv2.ml_StatModel.predict(samples, results=None, flags=None)
    • 예제코드를 통해서 공부할 예정이고, 이번 수업에서는 아래를 공부할 예정
      1. KNearest : K 최근접 이웃 알고리즘은 샘플 데이터와 인접한 K개의 학습 데이터를 찾고, 이 중 가장 많은 개수에 해당하는 클래스를 샘플 데이터 클래스로 지정
      2. SVM : 두 클래스의 데이터를 가장 여유 있게 분리하는 초평면을 구함
  3. k최근접 이웃 알고리즘

    • KNearest 이론

      • image-20210131105134458
      • 원래 파란, 빨간 백터만 있는 공간에, 초록색이 들어왔다고 가정하다.
      • 1번은 파랑 클래스, 2번은 빨강 클래스라고 정하면 될 것 같다.
      • 3번은 뭘까?? 이것을 결정하기 위해, 초록색에 대해서 가까운 k개의 백터를 찾는다. 그리고 가장 많이 뽑힌 클래스를 3번의 클래스라고 정하는 방법이다.
    • KNearest 코드

      • cv2.ml.KNearest_create() -> retval

      • # Knnplane.py 아래의 순서대로 OpenCV 사용
               
        # 이거 사용할거다. 라는 의미의 객체 생성
        knn = cv2.ml.KNearest_create()
        # 백터 저장
        knn.train(trainData, cv2.ml.ROW_SAMPLE, labelData)
        # Inference
        ret, _, _, _ = knn.findNearest(sample, k_value)
        
      • Knnplane.py 코드는 tuple(x,y,label) 의 다수 포인트를 이용해서, 2차원 평면상의 임의 포인트는 (3개의 클래스 중) 어떤 클래스를 가지는지 결정하여 색칠하는 코드이다. 어렵지 않으니 필요하면 참고
  4. KNN 필기체 숫자 인식 (KNearest 사용)

    • cv2.matchTemplate(chap8-segmentation-detection) 를 사용해서 필기체 인식을 했었다. 하지만 그 방법은 똑같은 폰트를 사용한 숫자여야하고 레이블링 후 숫자 부분영상의 정규화도 해야한다. (이전 post 참고)

    • image-20210131112211954

    • # 학습 데이터 & 레이블 행렬 생성
      digits = cv2.imread('digits.png?raw=tru', cv2.IMREAD_GRAYSCALE)
      h, w = digits.shape[:2]
           
      # 배열 분할 하기 h_split,v_split = https://rfriend.tistory.com/359
      cells = [np.hsplit(row, w//20) for row in np.vsplit(digits, h//20)]
      cells = np.array(cells) # cells: shape=(50, 100, 20, 20), dtype: uint8
           
      # 위 사진과 같이 배열 및 클래스 저장
      train_images = cells.reshape(-1, 400).astype(np.float32)
      train_labels = np.repeat(np.arange(10), len(train_images)/10)
      # train_images: shape=(5000, 400), dtype=**float32**, train_labels: shape=(5000, ), dtype=**int32**
           
      # KNN 학습
      knn = cv2.ml.KNearest_create()
      knn.train(train_images, cv2.ml.ROW_SAMPLE, train_labels)
      # Inference
      ret, _, _, _ = knn.findNearest(test_image, 5)
      
  5. SVM 알고리즘 (아주 간략히만 설명한다. 자세한 수학적 설명은 직접 찾아공부)

    • SVM : 기본적으로 두 개의 그룹(데이터)을 분리하는 방법으로 데이터들과 거리가 가장 먼 초평면(hyperplane)을 선택하여 분리하는 방법 (maximum margin classifier)
    • 아래의 1번과 2번 라인이 아닌, 3번의 라인처럼, 직선/평면과 가장 거리가 최소한 서포트 백터와의 거리가 최대maximum가 되도록 만드는 직선/평면(n차원 백터에 대해서 n-1차원 평면)을 찾는다.
    • image-20210131125416110
    • image-20210131132413371
    • 수학적 수식은 위와 같다. 자세한 내용은 생략한다. 여기서 w와 x는 백터이다. w*x + b = 0 이 n차원 백터에 대해서 n-1차원 평면식이 되겠다. 자세한 수학적 설명은 강의에서도 가르쳐주지 않으니 직접 찾아서 공부할 것.
    • 위의 백터들은 완벽하게 분류가 되어 있는데, 오차가 있는 경우의 SVM을 찾는 방법은 다른 알고리즘을 사용한다. 그 알고리즘은 Soft margin, C-SVM 이라고 부른다.
    • 하지만 SVM은 선형 분류 알고리즘이다. 백터들을 분류하기 위해 직선(선형식)으로는 분류가 안된다면 SVM을 사용할 수 없다. 물론 차원을 확장하면 선형으로 분리 가능 할 수 있다. 아래의 예제로만 알아두고 정확하게는 나중에 정말 필요하면 그때 찾아서 공부하기.
    • image-20210131132846308
    • 여기서는 z에 관한 방적식으로 차원을 확장했는데, 일반적으로 z는 조금 복잡하다. kernel trick이라는 방법을 통해서 차원 확장을 이루는데, 이것도 필요함 그때 공부.
  6. OpenCV SVM 사용하기

    • 객체 생성 : cv2.ml.SVM_create() -> retval

    • SVM 타입 지정 : cv.ml_SVM.setType(type) -> None

    • SVM 커널 지정 : cv.ml_SVM.setKernel(kernelType) -> None

    • SVM 자동 학습(k-폴드 교차 검증) : cv.ml_SVM.trainAuto(samples, layout, respo) -> retval

    • # svmplane.py
      # trains and labels 임으로 만들어 주기
      trains = np.array([[150, 200], [200, 250], [100, 250], [150, 300], [350, 100], [400, 200], [400, 300], [350, 400]], dtype=np.float32)
      labels = np.array([0, 0, 0, 0, 1, 1, 1, 1])
      # set SVM
      svm = cv2.ml.SVM_create()
      svm.setType(cv2.ml.SVM_C_SVC)
      svm.setKernel(cv2.ml.SVM_LINEAR) # 직선, 평명 찾기
      #svm.setKernel(cv2.ml.SVM_RBF) # 곡선, 곡면 찾기
           
      svm.trainAuto(trains, cv2.ml.ROW_SAMPLE, labels)
           
      print('C:', svm.getC()) # 초평면 계산 결과1
      print('Gamma:', svm.getGamma()) # 초평면 계산 결과2
           
      w, h = 500, 500
      img = np.zeros((h, w, 3), dtype=np.uint8)
      for y in range(h):
          for x in range(w):
              test = np.array([[x, y]], dtype=np.float32)
              _, res = svm.predict(test)  # predict
              ret = int(res[0, 0])
              if ret == 0: img[y, x] = (128, 128, 255) 
              else: img[y, x] = (128, 255, 128) 
      color = [(0, 0, 128), (0, 128, 0)]
      for i in range(trains.shape[0]):
          x = int(trains[i, 0])
          y = int(trains[i, 1])
          l = labels[i]
          cv2.circle(img, (x, y), 5, color[l], -1, cv2.LINE_AA)
      
    • image-20210131133359985
  7. HOG(descriptor = 특징값 vector로 추출)를 이용한, SVM 기반 필기체 숫자 인식

    • image-20210202105940306

    • 이전에는 hog.setSVMDetector를 사용했지만, hog.compute(img) 를 사용한다.

    •  # svmdigits.py 자세한 내용은 코드를 참고하기 (필요하면..)
       hog = cv2.HOGDescriptor((20, 20), (10, 10), (5, 5), (5, 5), 9)
       desc = []
       for img in cells:
       	desc.append(hog.compute(img))
       train_desc = np.array(desc).squeeze().astype(np.float32)
       train_labels = np.repeat(np.arange(10), len(train_desc)/10)
            
       # SVM 학습
       svm = cv2.ml.SVM_create()
       svm.setType(cv2.ml.SVM_C_SVC)
       svm.setKernel(cv2.ml.SVM_RBF)
       svm.setC(2.5)
       svm.setGamma(0.50625)
       svm.train(train_desc, cv2.ml.ROW_SAMPLE, train_labels)
            
       # inference
       test_image = cv2.resize(img, (20, 20), interpolation=cv2.INTER_AREA)
       test_desc = hog.compute(test_image)
       _, res = svm.predict(test_desc.T)
       print(int(res[0, 0]))
      
  8. 숫자 영상 정규화

    • 숫자 이미지는 숫자의 위치, 회전,크기 등등에 따라서 다양한 모습을 갖추기 때문에, 숫자 위치를 정규화할 필요가 있음

    • 숫자 영상의 무게 중심이 전체 영상 중앙이 되도록 위치 정규화

    • 무게 중심을 찾아주는 함수 사용 m = cv2.moments(img)

    • def norm_digit(img):
          # cv2.moments의 사용법은 아래와 같다
          m = cv2.moments(img)
          cx = m['m10'] / m['m00']
          cy = m['m01'] / m['m00']
          h, w = img.shape[:2]
          aff = np.array([[1, 0, w/2 - cx], [0, 1, h/2 - cy]], dtype=np.float32)
          dst = cv2.warpAffine(img, aff, (0, 0))
          return dst
           
      desc = []
      for img in cells:
          img = norm_digit(img)
          desc.append(hog.compute(img))
      # 나머지는 윗 코드와 같다
      
  9. k-평균 알고리즘

    • 주어진 데이터가지고, 이미지를 k개의 구역으로 나누는 군집화 알고리즘 (비지도 학습으로 고려)
    • image-20210208113107195
    • image-20210202114926500
    • 동작순서
      1. 임의의 (최대한 서로 멀리) K개 중심을 선정 (분할 평면도 대충 적용. Ex) 두 임의의 점의 중점을 지나는 수직 선)
      2. 모든 데이터에 대해서 가장 가까운 중심을 선택 (추적 때 배운 평균 이동 알고리즘과 비슷)
      3. 각 군집에 대해 중심을 다시 계산
      4. 중심이 변경되면 2번과 3번 과정을 반복
      5. 중심 변경이 적어지면 종료
    • 컬러 영상 분할
      • 컬러영상에서 대표가 되는 칼라 픽셀 값을 선택하는 알고리즘. 원본 이미지에서 위의 k-mean 알고리즘을 수행하는게 아니라, RGB&HS 공간에서 위의 알고리즘을 수행해 ‘대표필셀값’을 찾는다
      • image-20210202114559908
      • cv2.kmeans(data, K, bestLabels, criteria, attempts) -> retval, bestLabels, centers (자세한 파라메터 설정은 강의나 공식 문서 참고)
      • k-means 알고리즘을 이용한 컬러 영상 분할 예제 실행 결과 - kmeans.py 파일 참고 (코드는 매우 간단)
      • image
  10. 실전 코딩: 문서 필기체 숫자 인식

    • image
    • 앞에서 배운것 만을 잘 활용한다.
    • 순서 요약
      1. 레이블링 이용 → 각 숫자의 바운딩 박스 정보 추출
      2. 숫자 부분 영상을 정규화
      3. HOGDescriptor 로 descriptor 추출
      4. 이미 학습된 SVM으로 predict 수행

chap - 12, 13 딥러닝

  • cv2.dnn 모듈을 사용해서 합습 및 추론
  • 필요하면 그때 공부하자.

Pagination


© All rights reserved By Junha Song.