본문 바로가기

Programmer Jinyo/Machine Learning

Depthwise Separable Convolution 설명 및 pytorch 구현


투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)

바이낸스(₿) 수수료 평생 20% 할인받는 링크로 가입하기! 🔥 (클릭!)

Depthwise Convolution

 

우선 Depth-wise Seperable Convolution에 대한 설명을 하기에 앞서 Depth-wise Convolution에 대한 설명을 먼저 할까 한다.

 

Depth-wise Convolution

기본적인 개념은 쉽다. 위 처럼 H*W*C의 conv output을 C단위로 분리하여 각각 conv filter을 적용하여 output을 만들고 그 결과를 다시 합치면 conv filter가 훨씬 적은 파라미터를 가지고서 동일한 크기의 아웃풋을 낼 수 있다. 또한 각 필터에 대한 연산 결과가 다른 필터로부터 독립적일 필요가 있을 경우에 특히 장점이 된다.

 

이를 파이토치에서 구현하려면 다음과 같이 하면 된다.

 

class depthwise_conv(nn.Module):
    def __init__(self, nin, kernels_per_layer):
        super(depthwise_separable_conv, self).__init__()
        self.depthwise = nn.Conv2d(nin, nin * kernels_per_layer, kernel_size=3, padding=1, groups=nin)


    def forward(self, x):
        out = self.depthwise(x)
        return out

첫 칸은 in_channels 이고, 두번째 칸은 out_channels이다.

직관적으로 알 수 있듯, 하나의 레이어에서 몇개의 아웃풋을 만들 것이냐는 말로 귀결된다.

여기에서의 구현의 핵심은 groups = nin 부분인데, 입력 레이어를 nin개의 서로 다른 group으로 만들어서 해당 연산을 수행하겠다는 뜻이 된다. (반대로 생각해보면, group의 default 값이 1이라는 소리이다.)

 

 

 Pointwise Convolution

 

Point-wise Convolution

흔히 1x1 Conv라고 불리는 필터이다. 많이 볼 수 있는 트릭이고 주로 기존의 matrix의 결과를 논리적으로 다시 shuffle해서 뽑아내는 것을 목적으로 한다. 위 방법을 통해 총 channel수를 줄이거나 늘리는 목적으로도 많이 쓴다.

pytorch로 구현하면 아래와 같이 구현할 수 있다.

 

class pointwise_conv(nn.Module):
    def __init__(self, nin, nout):
        super(depthwise_separable_conv, self).__init__()
        self.pointwise = nn.Conv2d(nin, nout, kernel_size=1)

    def forward(self, x):
        out = self.pointwise(x)
        return out

 

 

 

 

Depthwise Separable Convolution

Depthwise convolution을 먼저 수행한 후 Pointwise convolution을 수행한다.

이를 통해서 3x3의 필터를 통해 conv 연산도 진행하고, 서로 다른 channel들의 정보도 공유하면서 동시에 파라미터 수도 줄일 수 있다.

 

아래와 같이 구현된다.

 

class depthwise_separable_conv(nn.Module):
    def __init__(self, nin, kernels_per_layer, nout):
        super(depthwise_separable_conv, self).__init__()
        self.depthwise = nn.Conv2d(nin, nin * kernels_per_layer, kernel_size=3, padding=1, groups=nin)
        self.pointwise = nn.Conv2d(nin * kernels_per_layer, nout, kernel_size=1)

    def forward(self, x):
        out = self.depthwise(x)
        out = self.pointwise(out)
        return out

코드 출처 : https://discuss.pytorch.org/t/how-to-modify-a-conv2d-to-depthwise-separable-convolution/15843/7