ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 시멘틱 세그먼테이션의 시초가 된 FCN-32의 아이디어
    딥러닝/시멘틱 세그먼테이션 2022. 6. 5. 09:43

    시멘틱 세그먼테이션은 RGB 3채널인 이미지를 출력 차원으로 하는 딥러닝 모델입니다. 이러한 모델을 특히 Fully Convolutional Neural Network 구조로 바꾸어 놓은 FCN에 대해 알아보도록 하겠습니다.

     

    시멘틱 세그먼테이션

    시멘틱 세그먼테이션은 딥러닝 아키텍쳐로 보통 출력 부분이 이미지넷의 이미지 종류 개수에 맞추어  (배치 크기, 1000) 으로 해왔던 기본 CNN 과 달리 출력 부분을 원본 이미지 차원으로 바꾸어 놓은 모델을 말합니다.

     

    예를 들어 (배치 크기, 3, 224, 224) 가 될 수 있습니다.

     

    FCN-32

    모델의 첫 입력은 (224, 224, 3)으로 입력 원본 이미지와 동일합니다. 실제 코딩으로 주입할 때는 (3, 224, 224) shape으로 주입해야 하는 점 주의하세요. 

    VGG_types = {
        'VGG16' : [64,64, 'M', 128, 128, 'M', 256, 256,256, 'M', 512,512,512, 'M',512,512,512,'M'],
    }
    
    def makeVGG(self, architecture):
        layers = []
        in_channels = 3
    
        for x in architecture:
            if type(x) == int:  # int means conv layer
                out_channels = x
    
                layers += [nn.Conv2d(in_channels=in_channels, out_channels=out_channels,
                                     kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
                           nn.BatchNorm2d(x),
                           nn.ReLU()]
                in_channels = x
            elif x == 'M':
                layers += [nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))]
    
        return nn.Sequential(*layers)

    원본은 바로 채널 차원 수가 64개로 뛰게 됩니다. 계속해서 컨볼루션-BN-활성화 함수 시퀀스 그룹을 반복합니다. 어느덧 512 채널까지 증가하면 512 채널을 한동안 유지하며 시퀀스 그룹을 몇 번 더 거친 뒤 Conv 7x7을 적용합니다. 

    class FCN(nn.Module):
    
        def __init__(self, model, init_weights=True):
            super(FCN, self).__init__()
            # create conv_layers corresponding to VGG type
            self.vgg16 = self.makeVGG('VGG16')
    
            self.fcn = nn.Sequential(
                nn.Conv2d(in_channels=512, out_channels=4096,
                          kernel_size=(7, 7), stride=(1, 1), padding=0),
                nn.ReLU(),
                nn.Dropout(),

    이때의 입력 해상도는 14x14이고 패딩은 없고 커널 사이즈가 7x7이라서 XY 평면 차원 수가 많이 줄게 됩니다. 14x14에서 8x8 로 줄게 됩니다. 이게 좀 고해상도 출력과 연관성이 없다 하시는 분들은 14x14 해상도로 설계하셔도 될 거 같습니다. 이 포스팅은 아이디어와 경향만 보는 것이라서 원 논문 설계도와 일치하지 않을 수 있습니다. 흔히 FC 층을 버리고 컨볼루션 층으로 모두 구성했다는 표현을 하는데요. Conv 7x7 이후의 2개 층은 컨볼루션 층입니다. 전체 층이 컨볼루션 층으로 구성되도록 한 것인데요.

     

                nn.Conv2d(in_channels=4096, out_channels=4096,
                          kernel_size=(1, 1), stride=(1, 1), padding=0),
                nn.ReLU(),
                nn.Dropout(),
                nn.Conv2d(in_channels=4096, out_channels=21,
    
                          kernel_size=(1, 1), stride=(1, 1), padding=0),
                nn.ReLU(),
                nn.Dropout(),
                nn.Upsample(size=(224, 224), mode="bicubic"),
                nn.Conv2d(in_channels=21, out_channels=3,
                          kernel_size=(1, 1), stride=(1, 1))
            )
    
        def forward(self, x):
            x = self.vgg16(x)
            x = self.fcn(x)
            return x

     

    주의할 점은 바뀐 부분의 채널 차원이 1이 아니라는 점입니다.

     

    왜냐하면 바로 다음에 업샘플링을 하여 XY 평면 차원 수를 (224, 224)로 키우게 되는데 (1, 1)에서 평면 정보가 남아있질 않기 때문에 의미가 없게 됩니다. 그래서 (8, 8) 이라도 남겨둔 것 같습니다.

     

    업샘플링을 하는 방법은 바이리니어 인터폴레이션, 바이큐빅 인터폴레이션을 이용한 단순히 포토샵, 일러스트와 같은 프로그램에서 이미지 크기를 키우는 방법이 있어서 이번 포스팅에서는 그걸 사용한 것인데 원 논문은 transpose convolution을 사용했습니다. transpose convolution을 사용하면 한 연산으로 채널 차원 수까지 변경할 수 있습니다.  바이리니어나 바이큐빅 같은 경우는 해상도만 변경할 뿐 채널 차원 수는 변경하지 못합니다. 어떠한 방법을 사용하든 평면 차원 수를 224, 224로 키워 놓으면 됩니다.

     

    여기까지가 FCN-32입니다. skip connection을 하나도 사용하지 않은 기본 모델입니다. 

     

    skip connection을 적용한 FCN-16, FCN-8은 다음 포스팅에서 알아보도록 하겠습니다.

    '딥러닝 > 시멘틱 세그먼테이션' 카테고리의 다른 글

    U-Net  (0) 2022.06.05

    댓글

Designed by Tistory.