【Detection】Sparse R -CNN-End-to-End Object Detection with Learnable Proposals

  • 논문 : Sparse R-CNN, End-to-End Object Detection with Learnable Proposals
  • 분류 : Object Detection
  • 요즘에 계속 Transformer만을 이용하겠다고 아이디어 생각하고 그랬는데, GPU 성능을 생각하고 학습시간을 생각한다면, 다시 과거로 돌아가는 이런 아이디어도 굉장히 좋은 것 같다.

【RepVGG】 RepVGG- Making VGG style ConvNets Great Again



RepVGG

0. Abstract

  1. 3 × 3 convolution와 ReLU 만을 사용하였다.
  2. Training과 Inference과정의 Architecture를 decoupling하였다. 이를 위해서 Training parameter를 VGG구조로 바꾸기 위한 re-parameterization technique를 사용했다.
  3. RepVGG의 결과 : (1080Ti) 80% top1 accuracy. (plain model에서는 최초로) ResNet보다 83% 빠르고, ResNet 101보다 101% 빠르다.
  4. favorable accuracy-speed trade-off 를 가진 모델이다.

image-20210426163041272

PS. 여기서, full precision(fp32): half precision이 fp16(floating point)을 Training 과정에서 효율적으로 사용하고 fp32도 중간중간에 사용하는 것이라면, full precision은 항상 fp32만 사용하는 것.


1. Instruction

  1. 과거의 유명한 Backbone들 complicated ConvNets : Inception, ResNet, DensNet, EfficientNet
  2. 이런 모델들의 drawbacks
    • complicated multi-branch designs (ex, residual addition, branch-concatenation in Inception): 구현하기가 어렵다. Inference하는데 느리다. 메모리 사용을 더 많이 한다.
    • depthwise conv(inverted residual), channel shuffle: various devices에서의 사용이 힘들다.
    • 이 모델들의 FLOP(floating-point operations)과 Inference speed가 비례하지 않는다.
  3. 반면에 RepVGG는 VGG 같은 plain without any branch 모델이다. 하지만 multi-branch 들과 유사한 성능을 내기에는 매우 challenging했다.
  4. ResNet의 장점이자 단점: avoids the gradient vanishing problem을 위해서 residual Block을 사용한다. 하지만! 이 모듈은 Inference 에서 필요가 없다.
  5. 반면에 RepVGG는 Training과 Inference를 decouple했다. Training때 학습한 파라미터를 Inference모델로 ` equivalently replace하기 위해서 re-parameterization` 사용했다. 전체 구조를 미리 대강 살펴보면 아래와 같다.
  6. Only 3x3 conv and ReLU로 구성되어 있기 때문에 빠르다. 만약 하나의 유닛이 fewer operator만을 수행한다면, 더 많은 computing 유닛을 가진 GPU를 만들어 낼 수 있다. 만약 3x3-Relu만을 수행하는 GPU가 존재한다면, 엄청난 수의 Unit을 가진 GPU가 될 것이다. 이 GPU에 특화될 수 있다. (특별한 GPU만들 수 있다면 RepVGG는 개꿀 모델이다.)
  7. Contributions
    • favorable speed-accuracy trade-off
    • re-parameterization
    • effectiveness at classification and sementic segmentation

image-20210426163834045

2. Related Work

2.3. Model Re-parameterization

아래에 4.2 내용 참조

2.4 Winograd Convolution

  • RepVGG는 only 3x3 conv로만 구성되어 있는데, GPU라이브러리는 이 연산에 매우 최적화 되어있다. 위의 표에서 주목해야할 점을 기록해 놓았다.
  • Winograd Algorithm을 사용하면 3x3 conv연산을 더욱 가속할 수 있다. Original 3x3 conv연산보다 the amount of multiplications (MULs)의 양이 4/9로 줄어든다. 우리는 이 알고리즘을 통한 연산을 딥러닝 프레임워크에서 default로 사용하고 있다.
  • TFLOPS: Tera FLoating-point Operations Per Second GPU 제작사에서 사용하는 지표로써 actual running time and computational density의 정도를 의미한다. 높을수록 좋다.
  • (Table4,5에서 MULs을 기준으로 한 비교를 할 예정이다. Additions연산보다 multiplication연산이 더 많은 time-consuming이 필요하기 때문이다.)

image-20210426170022719


3. Building RepVGG

3.1. simple ConvNets의 장점

  1. Fast
    • FLOP과 Speed는 비례하지 않는다. 아래의 비교를 보면 VGG16이 FLOPs가 8배 높지만, 2배 빠르다. 즉 computational density가 대략 15배 차이 난다는 것을 의미한다.
    • Simple Conv는 FLOP이 높아도 Speed는 훨씬 빠르다. 그 이유는 (1) the memory access cost (MAC) (2) ` degree of parallelism ` 때문이다.
    • MAC는 다른 연산에 비해서 높은 time-consuming이 필요하고, degree of parallelism이 높으면 빠른 연산이 가능하다.
    • plain conv는 MAC가 거의 없고, parallelism이 매우 높다.
    • NASNET-A(the number of individual conv or pooling operations in one building block): few (paralleism을 사용한) large operators이 아닌 multiple small operators을 사용하는 정도를 의미한다. 높을 수록 degree of parallelism이 안 좋은 것이다.
  2. Memory-economica
    • multi-branch topology들은 memory-inefficient 하다. 예시는 아래의 그림에 있다.
  3. Flexible
    • multi-branch topology에는 몇가지 제약이 있다.
      1. 제약1: the last conv layers of every residual block have to produce tensors of the same shape
      2. 제약2 : channel pruning to remove some unimportant channels 사용하지 못한다. (channel pruning)
    • 반면에 RepVGG는 자유로는 shape 구성이 가능하고, channel pruning 또한 가능하다.

image-20210426170709145

3.2 Training-time Multi-branch Architecture

  • Plain conv = the poor performance. 따라서 Training과정에서는 multi-branch 모델의 장점을 최대한 이용한다.
  • ResNet의 Residual block에 의해서 implicit (sum) ensemble model이라고 할 수 있다. n개의 block은 an ensemble of 2^n models이라고 표현가능하다. RepVGG는 an ensemble of 3^n models 모델을 만들었다.
    image-20210426173456044

3.3. Re-param for Plain Inference-time Model

  • 코드를 바탕으로 제대로 다시 제대로 그려놓은 그림

image-20210426175447877

  • 하지만 굳이 논문 내용으로 이해하고 싶다면, 아래와 같이 해석할 수 있다.
  • (한 채널의 2차원 평면을 단위 행렬을 곱하여, 똑같은 2차원 평면이 나오게 만든다.)

image-20210427100758563

3.4. Architectural Specification

  • VGG에서는max pooling를 사용하지만, RepVGG에서는 최소한의 Operator만을 사용하기 위해서 사용하지 않는다.
  • 5 stage, the first layer of stage with stride=2
  • classification위해서 RepVGG를 통과한 후, Global average pooling -> fully connected layer
  • 몇가지 guidelines을 따라서 아래와 같은 Architecture models을 만들었다.
    image-20210426230732874
  • 특별히 b를 사용하는 이유는, 5 stage에 어차피 1개의 layer만을 사용하니, channel을 최대한으로 늘려도 모델 전체 파라미터 양에 큰 영향을 주지 않으므로 b를 사용한다.
  • further 파라미터를 줄이기 위해서, Groupwise conv layer를 사용한다.
    • 3rd, 5th, 7th, …, 21st layer of RepVGG-A
    • 3rd, 5th, 7th, …, 21st, 23rd, 25th and 27th layers of RepVGG-B
    • (channel을 몇등분으로 나눌지) g = 1 or 2 or 4

4. Experiments

4.1. RepVGG for ImageNet Classification

image-20210426231324078

  • data augmentation: random cropping and left-right flipping
  • batch size of 256 on 8 GPUs
  • 위의 Architecture에서 a와 b를 다르게 설정하여, middleweight and heavyweight models을 만들어 낸다.

image-20210426231653182

4.2. Structural Re-parameterization is the Key

  • Ablation studies
    image-20210426231808974
  • Re-parameterizaition 성능 비교: 각각에 대한 자세한 설명은 논문에서 잘 분류해 놓았으니 참고
    image-20210426231933911
  • 추가 실험
    1. ResNet50에서 모든 3x3 conv를 RepVGG block으로 바꾸고 학습시킨 후 re-parameterization을 통해서 다시 simple 3x3 conv로 바꿨을 때, 성능이 0.03% 상승해다. -> 강력한 plain convNet을 학습시키기 위해, 우리의 방법이 매우 유용하다!
    2. RepVGG에 추가적인 Skip-connection을 추가했을때, 성능이 0.58% 상승하였다. residual로써 ensemble 모델이 내제적으로 구현된 것이기 때문에 당연하다.
  • 보충 설명
    1. DiracNet
      • 비슷하면서 조금 다른 모듈이다.
      • RepVGG에서는 scaling vector 없음, BN 고려, Bias 고려, 1x1 conv 추가
        image-20210427102504970
      • 논문에서 이야기 하는 차이점
        1. RepVGG는 actual dataflow through a concrete structure 를 따른다. 반면에 DiracNet은 easier optimization를 위해서 ` another mathematical expression of conv kernels`을 사용했을 뿐이다.
        2. 성능이 RepVGG보다, 다른 SOTA 모델보다 떨어진다.
    2. Trivial Re-param
      • 위의 식에서 a = 1,b = 1
    3. ACB
      • 아래와 같이 3x3 conv를 more parameter를 사용하는 conv로 바꿔서 학습시킨다. 그리고 다시 3x3conv를 아래와 같이 변환한다.
        image-20210427100934484

4.3. Semantic Segmentation

  • ImageNetpretrained RepVGG 사용했다
  • PSPNet 사용
    image-20210426233353421
  • PSPNet는 stage 3,4에서 dilated conv를 적용한다. RepVGG에서도 dilated conv 구현하였지만, 속도가 많이 줄어들었다. (5*5로 padding한 conv를 사용해야하기 때문?)
  • 그래서 last 5 layers에서만 dilated conv를 적용한 것이 fast 모델이다.
  • 결과 분석
    • ResNet101과 성능이 비슷한 RepVGG-B1g2-fast의 속도가 62%나 빠르다.
    • middleweight 모델에서는 dilation이 그리 효율적이지 않다.

4.4 Limitation

  • RepVGG models은 단순 연산을 하는 unit이 많은 GPU에 매우 효율적이다.
  • 하지만 GPU가 없는 mobile-regime에서는 효율적은 모델은 아니다.
  • CPU를 위한 모델 -> MobileNet // low-power -> ShuffleNet (연산량이 매우 적다)


Code

  • Equation (3): 여기서 else가 Identity(only nn.BatchNorm2d) To W’+b’로 변환하는 코드이다.
    image-20210427095426340
    • kernel_value = np.zeros((self.in_channels, input_dim, 3, 3), dtype=np.float32)에서 self.in_channelsself.out_channels이 아닌 이유는, Skip_connection 연산은 input, output channel이 같기 때문이다.
    • 특히 kernel_value[i, i % input_dim, 1, 1] = 1 코드가 위의 나의 그림 중 노란색으로 수정한 코드부분이다.
  • Sum
    image-20210427095836596

【Python】Visualize torch.tensor or numpy.ndarray

In this short guide, you’ll see how to Visualize torch.tensor or numpy.ndarray

how to Visualize torch.tensor or numpy.ndarray

Visualize torch.tensor or numpy.ndarray

# from via import via; via(x)
import numpy as np
import torch
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

def via(arr, save_txt:bool = True, size:tuple = (20,20), 
                out:str = 'array_out.txt', Normalize:bool = False):
    dim = arr.ndim 
    if isinstance(arr, np.ndarray):
        # (#Images, #Chennels, #Row, #Column)
        if dim == 4:
            arr = arr.transpose(3,2,0,1)
        if dim == 3:
            arr = arr.transpose(2,0,1)
    if isinstance(arr, torch.Tensor):
        arr = arr.numpy()
    fig = plt.figure(figsize=size)

    if save_txt:
        with open(out, 'w') as outfile:    
            outfile.write('# Array shape: {0}\n'.format(arr.shape))
            
            if dim == 1 or dim == 2:
                np.savetxt(outfile, arr, fmt='%-7.3f')

            elif dim == 3:
                for i, arr2d in enumerate(arr):
                    outfile.write('# {0}-th channel\n'.format(i))
                    np.savetxt(outfile, arr2d, fmt='%-7.3f')

            elif dim == 4:
                for j, arr3d in enumerate(arr):
                    outfile.write('\n\n# {0}-th Image\n'.format(j))
                    for i, arr2d in enumerate(arr3d):
                        outfile.write('# {0}-th channel\n'.format(i))
                        np.savetxt(outfile, arr2d, fmt='%-7.3f')
            else:
                print("Out of dimension!")

    
    if Normalize:
        arr -= np.min(arr)
        arr /= max(np.max(arr),10e-7)
    if dim == 1 or dim == 2:
        if dim==1: arr = arr.reshape((1,-1))
        fig.suptitle('Array shape: {0}\n'.format(arr.shape), fontsize=30)
        plt.imshow(arr, cmap='jet')
        plt.colorbar()
        plt.savefig('array_out.png')

    elif dim == 3:
        x_n = int(np.ceil(np.sqrt(arr.shape[0])))
        fig.suptitle('Array shape: {0}\n'.format(arr.shape), fontsize=30)
        for i, arr2d in enumerate(arr):
            ax = fig.add_subplot(x_n,x_n,i+1)
            im = ax.imshow(arr2d, cmap='jet')
            plt.colorbar(im)
            ax.set_title('{0}-channel'.format(i))
        fig.savefig('array_out.png')

    elif dim == 4:
        img_n = arr.shape[0]
        x_n = int(np.ceil(np.sqrt(arr.shape[1])))
        outer = gridspec.GridSpec(img_n, 1)
        fig.suptitle('Array shape: {0}\n'.format(arr.shape), fontsize=30)
        for j, arr3d in enumerate(arr):
            inner = gridspec.GridSpecFromSubplotSpec(x_n, x_n, subplot_spec=outer[j],wspace=0.1,hspace=0.3)
            for i, arr2d in enumerate(arr3d):
                ax = plt.subplot(inner[i])
                im = ax.imshow(arr2d, cmap='jet')
                plt.colorbar(im)
                ax.set_title('{0}-Image {1}-channel'.format(j,i))
        
        fig.suptitle('Array shape: {0}\n'.format(arr.shape), fontsize=30)
        fig.savefig('array_out.png')

    else:
        print("Out of dimension!")

    

arr = torch.rand(2,28,35)
via(arr, size=(20,20))

How to use

from pythonfile import Visualarr; Visualarr(x)

【Transformer】DeiT-Training data-efficient image transformers & distillation



1. DeiT 논문 핵심 정리

  • ViT의 문제점 : JFT, ImageNet 매우매우 많은 데이터셋을 사용해서 학습시켜야, ImageNet SOTA를 찍을 수 있다. Transformer를 사용해서 좋은 성능이 나오려면, 일단 무조건 데이터셋이 아주아주아주 많으면 많을 수록 좋다.
  • Motivation : ImageNet 데이터셋만 가지고 학습시켜서 좋은 성능이 나오게 할 수 없을까?
  • 해결방법 : – Knowledge Distillation 을 사용하자!! Knowledge Distillation을 사용하면 Data Agumentation하기 이전의 class를 그대로 예측해야 할 필요가 없다. Teacher 또한 data augmentation한 결과를 보고 예측한 결과를 Stutent가 따라하면 되기때문에, 잘못된 모델학습이 되는 것을 막아준다. (PPT 2번 참조)
  • Transformer 만의 특장점: inductive biases가 매우 낮다. (inductive biases: [모집단(=전세계 모든)의 이미지의 centroids를 중심으로한 분포(+ decision boundary) VS 표본이미지(ImageNet)의 centroids와 분포]의 차이를 이야기 한다.) Conv와 fc에서는 weight가 Fixed되어 있지만, self-attention에서는 들어온 이미지에 대해서 서로 다른 weight[softmax(query x key) ]값을 가진다. (하지만 ImageNet에 대해서 좋은 Validation 결과가 나오려면.. inductive biases도 어느정도 필요하다.)
  • DeiT는 Hard Distillation을 사용해서 적은 데이터 만으로 빠르게 성능을 수렴시켰다.
  • 추가 기법 : Distillation Token (이거 추가해서 성능이 더 높아졌다. 아래 보충 내용 참조하기)
  • 아니그러면! Distillation Token 추가하면 Test 할 때, 뭐를 이용해서 Prediction하는가? Distillation Embeding, Class Embeding 값을 적절히 융합해서 Prediction한다. (PPT 7번 참조)
  • 실험결과를 보아 Convolution Network에 의해서 나오는 softmax결과를 Teacher로 이용했을때 가장 좋은 성능 나왔다, (inductive biases가 들어갔다!)
  • Transformer는 fc를 주력으로 이용한다. conv는 파라미터를 이용하면서 연산해야하므로, 병렬연산이 fc보단 좋지 않다. 따라서 파라미터를 BeiT가 더 많이 사용하기는 하지만, 더 빠른 인퍼런스 시간이 나온다.
  • 추가 기법들! bag of tricks :
    1. Transformer는 Initialization이 매우매우 중요하다. “The effect of initialization and architecture”, NIPS 2018 논문 내용을 사용했다.
    2. Transformer는 위에서 말했듯이, 데이터셋이 많으면 많을수록 좋기 떄문에, 여러여러여러가 data augmentation 기법을 사용했다. (그 기법들은 PPT 9번 참조)
    3. 이미지 resoltuion을 갑자기 늘려서 조금만 Fine-tuning 해주면 성능이 높아진다. resoltuion을 키우고 patch사이즈를 그대로 하면, patch의 갯수가 늘어나고, positional embeding의 갯수가 늘어나야한다. 이때 기존의 positional embedding을 interpolates으로 늘려주는데, bicubic 을 사용해야 그나마 성능이 늘어난다.

2. DeiT 보충 내용

  • Distillation token : Class token과 같은 역할을 한다. 하지만, the (hard) label predicted by the teacher 만으로 학습된다. (Its target objective is given by the distillation component of the loss) = 아래 loss함수의 (Fun) + (Fun)에서 오른쪽 항 만을 사용해서 학습시킨다.

  • Distillation token으로 만들어 지는 Distillation Embeding의 결과도 Classfication Prediction 결과가 나와야 하는데, Teacher모델이 예측하는 결과가 나오면 된다. (이미지 자체 Label에 대해서는 학습되지 않는다.)
    image-20210415204857822


3. DeiT Youtube 필기 내용

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 img31 img32

【Self】Self-Supervised-Learning & BYOL(Bootstrap Your Own Latent)

【DA】ADVENT-Entropy Minimization for DA



ADVENT

1. Conclusion, Abstract, Instruction

  • Task: unsupervised domain adaptation for semantic segmentation
  • Motivation: Real world와 비교해보면, Data distribution(데이터 분포, 이미지의 통계적 성질)의 많은 차이가 존재한다.
  • Simple observation
    • (1) Source이미지에 대해서, over-confident, low-entropy predictions
    • (2) Target이미지에 대해서, under-confident, high-entropy predictions
    • 과거에는 Pseudo label을 사용해서 Self-Training을 하는 방법, Feature output에 대해서 Adversarial Learning을 적용하는 방법을 사용했지만, 우리는 Target도 high-confident를 예측하게 만듬으로써, domain gap을 줄이는 방법을 고안했다.
      image-20210412193432212
  • 핵심 모듈
    • (1) an entropy loss: target 예측 결과가 high-confident 혹은 low-confident 가 되도록 강제한다. 에매하게 [0,1] 중간 값인 0.5 confident를 가지면 Loss를 준다.
    • (2) entropy-based adversarial training approach : AdaptSeg가 Output을 이용했다면, 여기서는 Output에 대해서 entropy를 계산한 feature map을 이용해서 Adversarial learning을 적용한다. 이로써, Target 예측결과도 Source 예측 결과처럼 적은 Entropy를 갖도록 유도한다.
    • 추가적인 성능향상을 위해서, 아래의 기법을 적용했다.
      • (i) training on specific entropy ranges (Entropy_x_target ∈ [0, 1] (H×W)
      • (ii) incorporating class-ratio priors. (그저 자주 나오는 class가 1 confident가 나와 버리는 문제를 막는다)
  • 성능
    • SOTA / Two main synthetic-2-real benchmarks / GTA5 → Cityscapes / SYNTHIA → Cityscapes.

3. Approaches

image-20210412193417344


3.0 Prerequisite

image-20210412194233568

  • 위와 같은 Segmentation Network를 Source data로 학습시킨다,

3.1.1 Direct entropy minimization

  • 위 전체 Architecture에서 상단부분에 있는 모듈이다.
  • 간접적으로는 Domain adaptation이 되도록 만들지만, 엔트로피 관점의 직접적인 최소화 과정이 수행된다.
  • Target Image에 대해서 high confidence를 추축해내는 F(Network)를 만들어내는 것이 목적이다.
  • prediction output에 대해서, the Shannon Entropy [36]라는 Entropy를 계산하는 공식을 적용해서 Entropy map을 만들어 낸다.
    image-20210412200526378
  • 계산되는 E를 구체적으로 예시를 통해서 알아보자. 아래와 같이 아에 높은 confident, 아에 낮은 confident이여야 낮은 Loss를 얻는다.
    image-20210412195920203
  • 위의 그래프에서 x값과 y값의 범위는 각각, [0,1], [0,0.16] 이다. 위 Entropy를 계산해준 후 y값을 [0,1] 사이의 값으로 정규화해준다. 즉 [0, 0.16] -> [0,1]
  • entropy loss는 soft-assignment version of the pseudo-label이다. 따라서 hard Image dataset에 대해서 좋은 성능을 보여준다. 그리고 threshold를 고르거나 One-hot encoding을 하는 a complex scheduling procedure가 필요없다.
  • 아래의 과정을 통해서 성능을 더욱 끌어올린다.

3.1.2 Self-training = Pseudo Label

image-20210412200649683


3.2 Minimizing entropy with adversarial learning

  • 3.1.1을 보면 c방향으로 sum을 해서 E (W,H)를 구하는 것을 알 수 있다. 이 sum 때문에 자칫하면, 지역에 담긴 구조적인 의존적 의미(? the structural dependencies between local semantics)를 무시할 수 있다. (?)
  • AdaptSeg가 Output을 이용했다면, 여기서는 Output의 각각의 pixel 스스로의 entropy를 계산한 map(weighted self-information space)을 이용해서 Adversarial learning을 적용한다.
  • weighted self-information space=I_x : Shape (C x H x W). image-20210412234837163 (단순하게 생각해서, 그냥 각 픽셀마다 이 연산이 수행됐다고 생각하면 되겠다.) 이것을 사용하는 장점은 아래와 같다.
    • Source에서 출력되는 I_x 와 Target에서 출력되는 I_x가 유사해지도록 만든다.
    • 간접적으로 Entropy를 낮추게 만드는 방법이라고 할 수 있다.
  • Discriminator, Adversarial Loss, Total Loss이다.
    image-20210412235416458

3.3. Incorporating class-ratio priors

  • 위의 방법들 처럼 단순하게 Entropy minimization만 하다보면 한가지 문제점이 생긴다.
  • 그 문제점은 발생 빈도가 높은 class, 쉬운 class를 우선적으로 1로 만들어 버리는 문제이다.
  • ProDA의 degeneration issue라고 생각하면 된다. 따라서 우리는 regularization 을 하는 과정이 필요하다. (ProDA의 방법이 더 좋을 거다. 아래의 방법은 구식인 것 같다)
  • 아래의 수식을 통해서, Class 발생 빈도 Histogram이 Source와 유사하도록 만든다. 여기서 Mu는 얼마나 유사하게 만들것 인가? 를 나타내는 강도 값이다. 0=약하게, 1=강하게. image-20210413000253218
  • the class-prior vector p_s: 각 클래스당 픽셀의 갯수의 L_1 histogram 이다.

4. Experiments

  • Dataset
    • Source: GTA5 or SYNTHIA
    • Traget: Cityscape
    • DA: 2, 975 unlabeled Cityscapes images are used for trainin
    • DA test: Evaluation is done on the 500 validation images
  • Network architecture
    • Deeplab-V
    • VGG-16 and ResNet101
    • Discriminator in DCGAN [28] : 4conv, leaky-ReLU laye
  • Implementation detail
    • single NVIDIA 1080TI GPU with 11 GB memory
    • discriminator: Adam optimizer [19] with learning rate 10−4 to train the discriminator
    • 나머지 모델들: SGD with learning rate 2.5 × 10-4 , momentum 0.9 and weight decay 10-4
  • Weighting factors
    • λ_ent = 0.001
    • λ_adv = 0.001


5. Results

image-20210413000352485



【Transformer+Video】VisTR & TrackFormer & 3D conv



1. VisTR 핵심 및 보충설명

1.1 논문 핵심 정리

  1. Instance segmentation은 하나의 이미지내에서 Pixel-level similarity를 찾내는 Task이다. Instance tracking는 다른 이미지에서 Instance-level similarity를 찾아내는 Task이다. Transformer는 similarity learning에 매우 특화되어 있다. (Why? softmax(Key*Query) 연산을 통해서 구해지는 Attention 값이 결국에는 query와 얼마나 유사한가를 계산하는 것이다)
  2. 전체 Architecture는 아래와 같다. 자세한 내용은 PPT에서 찾아보도록 하자.
    image-20210410222103658
    • 주의할 점으로는, instance queries가 decoder로 들어가서 나오는 최종 결과에 대해서, 각 프레임의 같은 Instance는 같은 i번쨰 query에 의해서 나와야하는 결과들이다. (corresponding indices)
  3. Sequential Network 이기 때문에 발생하는 특징
    • Temporal positional encoding (spatial positional encoding 뿐만 아니라, 이것을 3개 뭉친)
    • 3D Convolution
  4. 36개의 frame이 한꺼번에 들어가므로, 하나의 Sequence of images가 들어가서 총 연산에 걸리는 시간은 조금 걸릴지라도, FPS로 계산하면 상당히 높은 FPS가 나온다.(?)
  5. VisTR가 가지는 특장점들
    • instances overlapping를 매우 잘 잡는다 (DETR에서 코끼리 성능 결과 처럼)
    • changes of relative positions에도 강하다. (카메라가 고정되지 않아도 된다)
    • confusion by the same category instances (비슷한 고릴라, 코끼리 2개 붙어있어도.. 잘 분류하는 편이다)
    • instances in various poses 에 대해서 강하다. (사람이 무슨 포즈를 취하든..)
  6. Summary
    • a much simpler and faster
    • Vedio에 대한 Tracking은 Detection과 Tracking이 따로 진행되기 때문에 이음새가 반듯이 필요한데, VisTR은 seamlessly and naturally 한 모델이다.

1.2. 보충 내용

  • 3D conv란 ??
    image-20210412141401875
  • Dice Loss란? (mask loss를 Focal Loss와 Dice Loss의 합으로 계산된다.)
    image-20210412141200111
  • 굳이 Hungarian Loss?? -> 논문을 봐도 내가 생각한게 맞는 것 같다. 최적의 Assignment를 찾기 위해서 Hungarian algorithm을 쓰고, 찾아진 최적의 matching에 대해서만 Loss를 계산하고 backpro 하는 것이다.
  • Train/Inference Setting
    • AdamW, learning rate 10−4, trained for 18 epochs (by 10x at 12 epochs 마다 decays 되는 비율로)
    • initialize our backbone networks with the weights of DETR
    • 8 V100 GPUs of 32G RAM
    • frame sizes are downsampled to 300×540
  • Faster ??
    • 8개 V100 GPU
    • ResNet-101 backbone -> 27.7 FPS, Image Process 작업 제외하면 57.7 FPS
    • 높은 FPS 원인 (1) data loading을 쉽게 병렬화 처리 할 수 있고 (2) parallel decoding의 가능하고 (3) no post-processing

1.3 코드로 공부해야 할 것들

  • Temporal Positional Encoding
  • Mask를 생성하기 위한, the self-attention module.
  • Self-attetion(O,E)가 B와 Fusion 될때의 연산
  • Deform_conv

2. VisTR PPT 공부자료

img img img img img img img img img img img img img img img img img img img img

3. TrackFormer 핵심 및 보충설명

3.1 논문 핵심 정리

image-20210412155207024

  • Key Idea는 track query embeddings을 적용해서, 위의 그림처럼 auto-regressive manner을 사용하는 것이다.
  • Transformer의 수학적 수식은 위 VisTR 논문 내용과 같다.
  • 전체 순서
    1. DETR을 그대로 사용해서, 첫번째 Frame에 대해서 Object Detection을 수행한다.
    2. 첫번째 Frame에 대해, Object query에 의해서 나온 Object decoder output 중 object로 판정되는 output을, 다음 Frame의 Object query로 사용한다. (N_track) 뿐만 아니라, 추가적인 N_object query도 당연히 추가한다.
    3. 새로운 Frame에 대해서 2번 과정을 반복 수행한다.
    4. 학습은 2개의 Frame씩만 묶어서 학습한다.
  • Track query attention block(= a separate self-attention block) 은 Track queries 끼리 서로 소통하게 만드는 모듈이다. (위 이미지 아래 모듈) 이 모듈을 통해서 t-1 Frame의 Object 위치와 구조에 대한 정보를 그대로 사용하는게 아니게 만들어서, 새로운 Frame에 대한 적응을 좀더 잘하게 만들어 주었다.
  • 신박한 학습 기법들
    1. t-1 Frame을 t 주변의 아무 다른 Frame으로 대체해서 학습시킨다. 객체의 포즈나 위치가 확확 바뀌는 상황에도 잘 적응하게 만들기 위함이다.
    2. 어떠한 query type(track, object)에서도 잘 반응할 수 있게 만들기 위해서, 가끔 track query를 제거해서 다음 Frame Decoder에 넣어준다. 학습 밸런싱을 맞추는 과정이다. 새로 나타난 객체에 대해서도 잘 Detecion 하게 만들어 주는 방법이다.
    3. Track queries에 Background에 대한 output도 넣어준다. (내 생각으로 이 과정을 통해서, Track query attention block 과정을 통해서 object occlusion의 문제점을 완화시켜준다.)
  • DETR에서 Panoptic Sementation 구조를 그대로 차용해서 Instance에 대한 Mask 예측도 수행하고, MOTS 결과도 출력해보았다.

3.2. 보충 내용

image-20210412163825650

  1. Bipartite track query matching에 대한 부분
  2. MOT dataset, Environment Setting에 대해서는 추후에 필요하면 공부해보자.

4. TrackFormer PPT 공부자료

img img img img img img img img img img img img img

【DA】AdaptSegNet-Learning to Adapt Structured Output Space



AdaptSegNet

  • Deeplab V2를 사용했다고 한다. V2의 architecture 그림은 없으니 아래의 V3 architecture 그림 참조
    image-20210410152157113

  • AdaptSegNet 전체 Architecture
    image-20210410152244470

  • 코드를 통해 배운, 가장 정확한 학습과정 그림은 해당 나의 포스트 참조.


1. Conclusion, Abstract

  • DA semantic segmentation Task를 풀기 위해, adversarial learning method을 사용한다.
  • 방법1 : Adversarial learning을 사용한다. in the output space(last feature map, not interval feature map)
  • 방법2 : 위의 그림과 같이 a multi-level에 대해서 adversarial network 을 사용한다. multi-level을 어떻게 사용하는지에 대해서는 위의 Deeplab V3 architecture를 참조할 것.
  • 방법1의 Motivation : 아래 그림과 같이, 이미지 사이에는 많은 차이가 있지만, CNN을 모두 통과하고 나온 Output feature map은 비슷할 것이다.
    • 따러서 Sementic segmentation의 예측결과 output을 사용하여, Adversarial DA과정을 진행함으로써, 좀더 효과적으로 scene layout과 local contect를 align할 수 있다.
      image-20210410152644326

2. Instruction, Relative work

  • pass

3. Method

  • the discriminator D_i (level i): source 이미지로 부터온 prediction Ps인지 Target, 이미지로 부터온 prediction Pt인지 구별한다.
  • target prediction에 대한 Adversarial loss를 적용해서, G(Generator=Feature encoder)가 similar segmentation distribution를 생성하게 만든다.
  • Output Space Adaptation에 대한 Motivation
    1. 과거의 Adversarial 방법들은, 그냥 feature space(맨 위 이미지에서 빨간색 부분=complex representations)를 사용해서 Adversarial learning을 적용했다.
    2. 반면에, segmentation outputs(맨위 이미지에서, hard labeling 작업 이전의 최종 예측 결과값)은low-dimension이지만 rich information을 담고 있다.
    3. 우리의 직관으로 이미지가 source이든 target이든 상관없이, segmentation outputs은 굉장히 강한 유사성을 가지고 있을 것이다.
    4. 따라서 우리는 이러한 직관과 성질을 이용해서, low-dimensional softmax outputs을 사용한 Adversarial Learning을 사용한다.
  • Single-level Adversarial Learning: 아래 수식들에 대해서 간단히 적어보자
    1. Total Loss
    2. Discriminator Loss: Discriminator 만들기
    3. Sementic segmentation prediction network
    4. Adversarial Loss: Generator(prediction network)가 target 이미지에 대해서도 비슷한 출력이 나오게 만든다
      image-20210410155549796
  • Multi-level Adversarial Learning
    • Discriminator는 feature level마다 서로 다른 Discriminator를 사용한다
    • i level feature map에 대해서 ASPP module(pixel-level classification model)을 통과시키고 나온 output을 위 이미지의 (2),(3),(4)를 적용한다.
      image-20210410161814692
  • Network Architecture and Training
    1. Discriminator
      • all fully-convolutional layers, convolution layers with kernel 4 × 4 and stride of 2, channel number is {64, 128, 256, 512, 1},
      • leaky ReLU parameterized by 0.2
      • do not use any batch-normalization layers: small batch size를 놓고 각 source batch, target batch 번갈아가면서 사용했기 때문이다.
    2. Segmentation Network
      • e DeepLab-v2 [2] framework with ResNet-101 [11] model
      • modify the stride of the last two convolution layers from 2 to 1 함으로써, 최종결과가 이미지 H,W 각각이 H/8, W/8이 되도록 만들었다.
      • an up-sampling layer along with the softmax output
    3. Multi-level Adaptation Model
      • we extract feature maps from the conv4 layer and add an ASPP module as the auxiliary classifier
      • In this paper, we use two levels.
      • 위 그림을 보면 이해가 쉽니다.
    4. Network Training(학습 과정)
      1. (Segmentation Network와 Discriminators를 효율적으로 동시에 학습시킨다.)
      2. 위의 Segmentation Network에 Source 이미지를 넣어서 the output Ps를 생성한다.
      3. L_seg를 계산해서 Segmentation Network를 Optimize한다.
      4. Segmentation Network에 Target 이미지를 넣어서 the output Pt를 생성한다.
      5. Optimizing L_d in (2). 위에서 만든 Ps, Pt를 discriminator에 넣고 학습시킨다.
      6. Adversarial Learning : Pt 만을 이용해서 the adversarial loss를 계산하여, Segmentation Network를 Adaptation 시킨다.
    5. Hardware
      • a single Titan X GPU with 12 GB memory
      • the segmentation network
        • Stochastic Gradient Descent (SGD) optimizer
        • momentum is 0.9 and the weight decay is 5×10−4
        • initial learning rate is set as 2.5×10−4
      • the discriminator
      • Adam optimizer
      • learning rate as 10−4 and the same polynomial decay
      • The momentum is set as 0.9 and 0.99

4. Results

  • 성능 결과 및 Ablation study에 대한 내용은 Pass
    image-20210410163443274

【Pytorch】 mmclassification teardown reports & Ubuntu re-install

Ubuntu re-install & mmclassification teardown reports

1. New ubuntu setting List

  1. 우분투 설치
  2. gpu graphic driver 설치
  3. docker, docker-nvidia 설치
  4. Vscode 설치
  5. anaconda 설치
  6. docker image, container 필요한거 다운 및 설치 (MLworkspace, pytorch-cuda)
  7. dataset 다운로드 (coco, imagenet)

2. Docker setting

  • Docker hub naming (참고 사이트)

    • devel : 속편하지만 용량이 너무 큼
    • base : 가장 낮은 용량
    • runtime : 사용하기에 적절한 용량
    • 이유는 모르겠지만 pytorch-1.5.1-cuda10.1-runtime에서는 cat /usr/local/cuda/version.txt가 동작하지 않는다. 그럼에도 불구하고 예전에 detr을 cuda로 돌렸었다. mmclf에서는 cuda문제가 발생했으므로 속편하게 pytorch-1.5.1-cuda10.1-devel 사용해야겠다.
  • docker run –shm-size

    • shared memory 사용 공간 ML-workspace에서 512MB를 주니, 대충 그정도 사용하면 될 듯하다.
  • docker run

    • detr에서 준 dockerfile을 build해서 사용했다. 하지만 cuda 문제가 발생했다.
    • detr에서 준 docker image 부터가 잘못 됐다. 재설치 필요
    • docker hub - pytorch 1.5.0 - devel 을 사용한다. runtime에는 cat /usr/local/cuda/version.txt 가 동작하지 않는다. 맘편하게 devel사용한다.
    • 아래와 같이 -v를 2번 가능하다. <my path>/<container path> 에서, <container path>는 path가 존재하지 않으면 자동으로 mkdir된다.
    $ sudo docker run -d -it      \
    --gpus all         \
    --restart always     \
    -p 8000:8080         \
    --name "mmcf"          \
    --shm-size 2G      \
    -v ./home/junha/docker/mmclf/mmclassification   \ # 가능하면 무조건 절대경로 사용할 것
    -v /hdd1T:/dataset   \
    pytorch/pytorch:1.5.1-cuda10.1-cudnn7-devel
      
    $ sudo docker run -d -it      \
    --gpus all         \
    --restart always     \
    -p 8080:8080         \
    --name "mmcl"          \
    --shm-size 2G      \
    -v /home/junha/docker:/workspace  \
    -v /hdd1T:/dataset   \
    sb020518/mmcl:0.1
    

3. mm installation

  • mmcv installation

    $ apt-get update
    $ apt-get install ffmpeg libsm6 libxext6  -y
    $ pip install mmcv-full==1.3.0 -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.5.0/index.html
    
  • mmclasification install

    $ git clone https://github.com/open-mmlab/mmclassification.git
    $ cd mmclassification
    $ pip install -e .  # or "python setup.py develop"
    
  • 이런 식으로 install하면, 이 공간의 mmcls 파일을 수정하면, import mmcls.util.collect_env 이것을 새로운 py파일에 적든, 터미널에서 python을 실행해서 적든, 모두 수정된 코드 내용이 적용 된다.

  • mmclasification install Test

    python demo/image_demo.py \
    /workspace/checkpoints/dog.jpg  \
    /workspace/configs/resnet/resnet50_b32x8_imagenet.py  \
    /workspace/checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth 
    

4. 코드 공부 흐름 필수

  1. Github 패키지 이곳저곳 돌아다니면서, 전체적인 구조 눈으로 익히기(좌절하기 말기. 핵심만 파악하려 노력하기)
  2. Interence 흐름 따라가기
  3. Tranin 흐름 따라가기
  4. Dataloader 공부하기
  5. Loss, Optimizer, Scheduler 분석하기
  6. Model save load, check point 분석하기
  7. Batch 구성방법, GPU 분산학습 분석하기

[코드에서 다 봐야하는 것] (순서대로 보지 말고. 코드 따라가면서 눈에 보이는 것 부터 부셔버리기)

  • Github로 전체적인 구조 눈으로 익히기
  • Interence 흐름 따라가기
  • Tranin 흐름 따라가기
  • Dataloader 공부하기
  • Loss, Optimizer, Scheduler 분석하기
  • Model save load, check point 분석하기
  • Batch 구성방법, GPU 분산학습 분석하기

5. mmclassification github

  1. Python argparse 사용법

    • parser.add_argument에 대해서, –가 붙여 있는 것은 optional 이다. –가 없는 것은 필수입력인자(positional) 이다.
    • add_argument()에 들어가는 인자가 많다.
    • 그 인자 중, type= 설정해주지 않으면 str이 default
    • 그 인자 중, default= 값이 지정되지 않았을 때, 사용할 디폴트값
  2. config 파일 분석하기 (아래 팁 참조)

    • configs/resnet/resnet50_b32x8_imagenet.py에는 또 다른 config 파일의 path만 기록 되어 있다.
    • 어려울 거 없이, 그 path의 config 파일만 다~ 모아서 cfg에 저장된다.
    • 이쁘게 출력해보고 싶으면, print(f'Config:\n{cfg.pretty_text}')
  3. test.py이든 train.py이든 핵심 호출법은 아래와 같다.

    • model: model = build_classifier(cfg.model)
    • dataset: dataset = build_dataset(cfg.data.test), datasets = [build_dataset(cfg.data.train)]

6. mmclassification/getting_started.md

  • Prepare datasets
    • ImageNet 다운로드. 각 클래스는 같은 폴더에 넣어주기 위한 sh 실행 (참조사이트).
    • MNIST, CIFAR10 and CIFAR100와 같은 데이터 셋은, 만약 데이터셋이 없다면 자동으로 다운 받아진다.
  • Inference a dataset
    • Inference는 이미지를 모델이 넣고 나오는 결과를 직접 눈으로 확인해보는게 목적이다.
    • mmclassification에서는 inference.py 파일 없다.
    • 굳이 하고 싶다면, demo/image_demo.py를 이용하자.
  • Test a datatset
    • Test는 val_img들에 대해서 예측결과를 추론해보는 것이 목표이다.
    • tools/test.py, tools/dist_test.sh
    • dist_test.sh는 결국 tools/test.py 실행한다.
    • $ python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [--out ${RESULT_FILE}] 이거로 먼저 debuging하고 그 다음에 dist_test.sh 파일을 이용해서 multi-gpu testing을 진행하자.
    • $ python tools/test.py configs/resnet/resnet50_b32x8_imagenet.py checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth --out result/imagenet-val.json
  • Train a dataset
    • $ python tools/train.py configs/resnet/resnet50_b32x8_imagenet.py --load-from checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth
      image-20210415100049662

7. tools/test.py 디버깅

  • 이제부터 아래의 과정은 디버깅을 통해 알아낸 내용이다,
  • [Vscode Debugging] : tools/test.py + "args" : ["configs/resnet/resnet50_b32x8_imagenet.py", "checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth "], or "args" : ["configs/resnet/resnet50_b32x8_imagenet.py", "checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth", "--metrics", "mAP", "CP", "CR"]
  • [Terminal] : python tools/test.py configs/resnet/resnet50_b32x8_imagenet.py checkpoints/resnet50_batch256_imagenet_20200708-cfb998bf.pth --out ./result/imagenet-val-resnet50.json --metrics "accuracy" "precision" "recall" "f1_score" "support"
  1. build_dataset/classifier 호출 순서

    # 아래로 내려갈 수록 define으로 들어가는 것
       
    ## 1. dataset
    from mmcls.datasets import build_dataloader, build_dataset
    from mmcv.utils import Registry, build_from_cfg
    return <class 'mmcls.datasets.imagesnet.ImagesNet'> # cfg.dataset_type 에 적힌 class
    # return이 완벽하게 되기 이전에 __init__ 가 실행되면서, 맴버 변수가 채워진다. 이때 pipeline(augmentation)이 정의된다.
       
    ## 2. classifier
    from mmcls.models import build_classifier
    from mmcv.utils import build_from_cfg
    return <class 'mmcls.models.classifiers.image.ImageClassifier'> # cfg.model.type 에 적힌 class
    # return이 완벽하게 되기 이전에 __init__ 가 실행되면서, 맴버 변수가 채워진다. 이떄 backbone, neck, head가 정의된다. 
    
  2. model.eval() 하고, 테드스 결과 뽑아내기

    # tools/test.py
    model = MMDataParallel(model, device_ids=[0])
    outputs = single_gpu_test(model, data_loader)
    
    • mmcv/paralled/MMDataParalle == from torch.nn.parallel import DataParallel
    • 여기서 model = <class 'mmcv.paralled.MMDataParalled' object> 로 바뀐다.
    • dataloader = <class 'torch.utils.data.dataloader.DataLoader' object>
  3. result 결과 뽑기

    # from mmcls.apis import single_gpu_test
    for i, data in enumerate(data_loader):
            with torch.no_grad():
                result = model(return_loss=False, **data)
                   
    """
    type(result) = list 
    len(result) = 32 = batch size = cfg.data.samples_per_gpu
    type(result[0]) = numpy.ndarray
    result[0].shape = (1000,)
    """
    

8.tools/train.py 디버깅

  1. argparse, config 읽고, 에러 미리 확인.

  2. build_ 수행하기

    model = build_classifier(cfg.model)
    datasets = [build_dataset(cfg.data.train)]
    # cpu worker 처리만 해주고
    train_model(
            model,
            datasets,
            cfg,
            distributed=distributed,
            validate=(not args.no_validate),
            timestamp=timestamp,
            meta=meta)
    
  3. from mmcls.apis import train_model

    # /mmcls/apis/train_model
    """
    1. dataloader = `<class 'torch.utils.data.dataloader.DataLoader' object>
    2. model = `<class 'mmcv.paralled.MMDataParalled' object>
    """
    runner = build_runner(
            cfg.runner,
            default_args=dict(
                model=model,
                batch_processor=None,
                optimizer=optimizer,
                work_dir=cfg.work_dir,
                logger=logger,
                meta=meta))
       
    runner.run(data_loaders, cfg.workflow)
    
  4. from mmcv.runner import epoch_based_runner

    • 아래 코드는, 아래로 차근차근 내려가면서 실행된다고 보면 된다.
    # /mmcls/runner/epoch_based_runner
    class EpochBasedRunner(BaseRunner):
        def run(self, data_loaders, workflow, max_epochs=None, **kwargs): # kwargs = {None}, self.model 이미 저장되어있음
            epoch_runner = getattr(self, mode) 
        	epoch_runner(data_loaders[i], **kwargs) 
            # == self.train(data_loaders[i], **kwargs)
        def train()
            for i, data_batch in enumerate(self.data_loader):
                self.run_iter(data_batch, train_mode=True)
        def run_iter(self, data_batch, train_mode, **kwargs):
             outputs = self.model.train_step(data_batch, self.optimizer, **kwargs)
                   
    """
    여기서 model은 
    <class 'mmcls.models.classifiers.image.ImageClassifier' object> 이자
    <class 'mmcv.paralled.MMDataParalled' object> 이다. 
    따라서 아래의 파일에 들어가면 ""train_step"" 함수 찾기 가능!
    """   
    
  5. mmclassification/mmcls/models/classifiers/base.py

    # mmclassification/mmcls/models/classifiers/base.py
    class BaseClassifier(nn.Module, metaclass=ABCMeta):
        def train_step(self, data, optimizer):
            losses = self(**data) #== BaseClassifier.fowerd 실행!
            outputs = dict(loss=loss, log_vars=log_vars, num_samples=len(data['img'].data))
        def forward(self, img, return_loss=True, **kwargs):
            if return_loss:
                return self.forward_train(img, **kwargs)
           
    def forward_train(self, imgs, **kwargs):
    	pass
        # 즉! torch.nn.Module.forward 그대로 실행된다.
    

중요하지만, 사소한 추가 팁들 모음

1. config 파일 넌 무엇인가?!

# test.py에서 디버깅 하면서, cfg파일 읽어보기 
print(f'Config:\n{cfg.pretty_text}')

########## 예를 들어서 이 파일을 봐보자. configs/resnet/resnet50_b32x8_imagenet.py  ##########
_base_ = [
    '../_base_/models/resnet50.py', '../_base_/datasets/imagenet_bs32.py',
    '../_base_/schedules/imagenet_bs256.py', '../_base_/default_runtime.py'
]
########## '../_base_/models/resnet50.py'  ##########
model = dict(
    type='ImageClassifier',
    backbone=dict(
        type='ResNeSt',
        depth=50,
        num_stages=4,
        out_indices=(3, ),
        style='pytorch'),
    neck=dict(type='GlobalAveragePooling'),
    head=dict(
        type='LinearClsHead',
        num_classes=1000,
        in_channels=2048,
        loss=dict(type='CrossEntropyLoss', loss_weight=1.0),
        topk=(1, 5),
    ))


########## '../_base_/datasets/imagenet_bs32.py'  ##########
dataset_type = 'ImageNet'
img_norm_cfg = dict(
    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
# 원하는 Transformer(data agumentation)은 아래와 같이 추가하면 된다.
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='RandomResizedCrop', size=224),
    dict(type='RandomFlip', flip_prob=0.5, direction='horizontal'),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='ImageToTensor', keys=['img']),
    dict(type='ToTensor', keys=['gt_label']),
    dict(type='Collect', keys=['img', 'gt_label'])
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='Resize', size=(256, -1)),
    dict(type='CenterCrop', crop_size=224),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='ImageToTensor', keys=['img']),
    dict(type='Collect', keys=['img'])
]
# 위에 내용은 이 아래를 정의하기 위해서 사용된다. cfg.data.test, cfg.data.val 이 사용된다.
data = dict(
    samples_per_gpu=32,
    workers_per_gpu=2,
    train=dict(
        type=dataset_type,
        data_prefix='data/imagenet/train',
        pipeline=train_pipeline),
    val=dict(
        type=dataset_type,
        data_prefix='data/imagenet/val',
        ann_file='data/imagenet/meta/val.txt',
        pipeline=test_pipeline),
    test=dict(
        # replace `data/val` with `data/test` for standard test
        type=dataset_type,
        data_prefix='data/imagenet/val',
        ann_file='data/imagenet/meta/val.txt',
        pipeline=test_pipeline))
 evaluation = dict(interval=1, metric='accuracy')


########## '../_base_/schedules/imagenet_bs256.py'  ##########
optimizer = dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
# learning policy
lr_config = dict(policy='step', step=[30, 60, 90])
runner = dict(type='EpochBasedRunner', max_epochs=100)


########## '../_base_/default_runtime.py'  ##########
# checkpoint saving
# 1번 epoch씩 모델 파라미터 저장
checkpoint_config = dict(interval=1)
# yapf:disable
# 100번 iteration에 한번씩 log 출력 
log_config = dict(
    interval=100,
    hooks=[
        dict(type='TextLoggerHook'),
        # dict(type='TensorboardLoggerHook')
    ])
# yapf:enable
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)] # [('train', 2), ('val', 1)] means running 2 epochs for training and 1 epoch for validation, iteratively.

2. Registry는 모두 안다. 난 고르기만 하면 된다.

  1. mmcv.utils.Registry 사실 맴버 변수는 2개 뿐이다,

  2. self._name = ‘backbone’

  3. self._module_dict = 아래 그림 4번처럼 모든 backbone을 다 알고 있다!! 어떻게 알지??

  4. 아래 그림 2번과 같이 정의된 class를 모두 담고 있는 것이다.
    image-20210413222450328

  5. @BACKCONES.register_modules()* 은 언제 실행되는 것 일까? 초반에 import할때 모두 실행된다. 여기*에다가 Breakpoint 걸고 디버깅한 결과는 아래와 같다.

    # test.py
    import mmcls.models
    import mmcls.models.__init__
    import mmcls.models.backbone.__init__
    from .regnet import RegNet
    

3. checkpoint = load_checkpoint(model, args.checkpoint) 결과는?

  • type( checkpoint ) = dictionary
  • Netron 이용해서 Visualization 하자

image-20210414120459711

4. 모델 파라미터 가져오기 - “어차피 텐서다 쫄지말자”

image

  • How to load part of pre trained model?

    pretrained_dict = ...
    model_dict = model.state_dict()
      
    # 1. filter out unnecessary keys
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
    # 2. overwrite entries in the existing state dict
    model_dict.update(pretrained_dict) 
    # 3. load the new state dict
    model.load_state_dict(pretrained_dict)
    

5. mmcls/models/backbones/ResNet.py forward 를 실행하기 까지의 과정은?

  • tools/test.py의 가장 마지막이, single_gpu_test 함수에 들어가는 것이었다.
  • mmcls/models/backbones/ResNet.py 에다가 breakpoint 걸어서 디버깅 해본 결과, 아래와 같은 코드 흐름을 확인할 수 있었다.
  • 알아만 두자.
    image-20210415092626508

6. python getattr()

# mmcv.runner.epoch_based_runner.py
# ** 아래의 2 코드는 같은 말이다. ** if mode == str('train') **
epoch_runner = getattr(self, mode) 
epoch_runner = self.train()
  • 따라서 디버깅으로 EpochBasedRunner을 확인해보면 train 맴버함수 (Github link)를 가지고 있는 것을 알 수 있다.

Pagination


© All rights reserved By Junha Song.