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

# 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