Introduction
본 논문은 pointwise group convolution과 channel shuffle을 활용하여 연산량을 줄이면서도 높은 성능을 보였다. Xception, ResNeXt의 경우 dense한 1x1 conv를 사용했기 때문에. 뿐만 아니라 이전포스트 'MobileNet'에서 보았듯이 1x1 conv를 활용하여 파라미터 수를 줄여 연산량을 줄일 수 있었지만 결과적으로 모델의 전체 연산량에서 많은 비율을 차지하는 것을 확인했다. 그리고 ResNeXt의 경우에는 3x3 conv를 하는 layer에만 group conv를 적용했는데, 이에 따라 각 residual unit에 대해 1x1 conv가 전체 연산량의 약 93%를 차지하는 것을 확인했다. 여튼, 알렉스넷보다는 13배 빠르고 모바일넷보다도 낫다고 주장하는 논문의 핵심인 channel shuffle에 대해 알아보자.
Channel Shuffle for Group Convolutions
ResNeXt나 MobileNet에서 활용된 Depthwise seperable conv에 대해 간단히 짚으면 먼저 input channel별로 n x n conv를 적용하고 여기에 filter별로 1x1 conv를 적용한 것이다. 위에서 언급했듯이 문제가 되는 것은 1x1 conv가 많은 연산량을. 차지하고 있다는 것인데 저자들은 여기서 desne하게 연결하여 연산하지 않고, 즉 1x1 conv kernel에 모든 채널을 연결시켜 연산하지 않고 channel sparse하게 연결시켜 연산하는 방법을 제안했다. 이 부분이 윗 그림의 (a)에 해당하는 부분이다. 하지만, 이 부분은 한 가지 문제점이 있는데 특정 그룹 내의 output은 오직 그 그룹의 input에만 영향을 받기 때문에 다른 채널의 정보를 받지 못해 표현력이 떨어질 수 있다는 것이다. 그래서 저자들은 각 그룹 내의 피쳐맵을 서브그룹으로 나누어 섞는 'Channel shuffle'을 한다면 인풋과 채널이 보다 dense하게 연결될 수 있음을 주장합니다. 즉, 채널별로 sparse하게 연결하여 떨어질 수 있는 표현력을 channel shuffle을 통해 보완하였다. Group conv를 하였으니 파라미터의 수가 group size만큼 줄어 연산량 또한 이에 비례해 줄어들 것이다.
ShuffleNet Unit
ShuffleNet에서는 ResNet과 유사하게 bottleneck unit을 두어 shufflenet unit을 제안했다. 먼저 (a)에서와 같이 1x1 conv -> 3x3 DW conv -> 1x1 conv를 세팅했다. 그리고 1x1 conv를 모두 1x1 group conv로 바꾸고 첫 번째 1x1 group conv 이후에는 channel shuffle을 수행하도록 했다. 이는 (b)에 해당한다. 여기까지가 일반적인 shufflenet unit이고, shufflenet에 stride를 추가하고 싶은 경우에는 (c)와 같이 shortcut path에 3x3 avg pooling을 추가하고 마지막에 element-wise하게 덧셈하는 부분을 channel concat을 통해 channel dimension을 높였다.
그러면 연산량은 실제로 얼마나 줄었을까? ResNet과 유사하게 bottleneck unit을 추가했으니 이와 비교해보자. 만약 $c \times h \times w$의 크기를 갖는 input이 들어오고 bottleneck channel의 개수는 $m$이라고 하자. 그러면 ResNet은 $hw(2cm+9m^2)$만큼 연산량이 든다. ResNeXt의 경우, bottleneck에 group conv를 적용했기 때문에 $\displaystyle hw(2cm+\frac{9m^2}{g})$만큼 연산량이 감소한다. 반면, shufflenet은 $\displaystyle hw(\frac{2cm}{g}+9m)$만큼 연산량이 든다.
구체적인 계산은 어떻게 될까? shufflenet이 resnet의 bottleneck구조를 차용하고 있기 때문에 이부터 먼저 해보자.
ResNet에서 bottleneck unit은 1x1 conv -> 3x3 conv -> 1x1 conv로 이뤄진 few stacke layer와 shortcut path로 이뤄져있다. 그러면 input이 $c \times h \times w$이고, bottlencek channel 개수는 $m$이니까 첫 번째 1x1 conv를 지날 때 $hwcm$만큼 연산량이 필요하다. (여기에는 커널 크기가 곱해져있는 것이다.) 마지막 1x1 conv에서는 input channel 개수와 output channel의 개수를 맞춰줘야 하기 때문에 output channel 개수가 $c$가 되어 1x1 conv 두 개를 지날 때는 총 $2hwmc$만큼의 연산량이 필요하다. 그리고 중간에 3x3 conv를 지날 때는 input이 $m \times h \times w$이고 bottleneck이 $m$이기 때문에 총 $9hwm^2$만큼의 연산량이 필요하다. 이 둘을 더하면 $hw(2cm+9m^2)$가 된다.
ShuffleNet에서도 1x1 conv를 사용하지만 이들이 group conv이기 때문에 위에 계산했던 것을 group size $g$로 나누어주면 된다. 그럼 1x1 conv를 사용하는 데 드는 연산량은 $\displaystyle\frac{2hwmc}{g}$가 된다. 3x3 DW conv를 하는 부분은 $9hwm$이 되는데, 이 둘을 더하면 $\displaystyle hw(\frac{2mc}{g}+9m)$이 된다.
Experiments
그룹 사이즈에 따른 classification error다. 그룹의 크기를 키우면 output channel의 수가 많아지니 표현력이 커져 에러가 줄어든다고 해석할 수 있다. shufflenet 뒤에 붙어 있는 것은 scale factor를 통해 채널 개수를 조정하여 작게 만든 모델이다.
그리고 채널 셔플을 하는 것이 안하는 것보다 좋다는 것을 모든 스케일링에 대해서 실험적으로 보였다. 그룹의 크기를 키울수록 에러 줄어드는 정도가 더 커지는 것을 확인할 수 있는데, 이는 위에서 언급한 이유와 같은 것으로 해석할 수 있다.
고정된 연산량에서 실험 시에 가장 우수한 성능을 보이고 있다
모바일넷과 비교하여 연산량을 비슷하게 가져가는 경우에도 가장 낮은 에러를 보인다. 연산량이 큰 경우에는 에러의 차이가 크지 않지만 연산량을 낮출수록 에러의 차이가 점점 커지는 것을 확인할 수 있다.
하지만, 메모리 액세스 문제 때문에 theortical speedup은 x4가 나왔음에도 불구하고 실제 가속은 최대 x2.6정도라고 한다. 이 부분에 대해 고민할 필요가 있어 보이는데, 후속 논문인 ShuffleNetV2의 모티브가 된다.