畳み込みニューラルネットワークは深層学習技術において非常に有名な手法ですが、畳み込みにもいろいろな手法があることはご存知でしょうか。今回は畳み込みニューラルネットワークについて、基礎的なものから応用的な畳み込み手法であるグループ化畳み込みなどまで解説します。
本記事は基本的なニューラルネットワークや深層学習の知識はある人を読者として想定しています。
Contents
畳み込み層とは
まずは基本的な畳み込みニューラルネットワークで用いられる、通常の畳み込み層について説明します。畳み込み処理は以下の画像のように、フィルタのような重み行列を入力画像上で移動させて加重和を計算するのでした。また、このフィルタのことをカーネルと呼びます。このあたりのより詳しい説明はこちらの記事を参照してください。
ここで、一応確認しておきますが、注意点として通常の畳み込み層において、カーネルのサイズが(K, K, C)、その数がMであり、入力画像が(H, W, C)であるとき、以下の図のような演算を行った結果出力のサイズは(H, W, M)となります。
このようになるのは、サイズ(K, K, C)のカーネルをMセット用意して、それらMセット全てについて畳み込み演算をして最終的にまとめたものが出力となるからです。
例えばPyTorchでは畳み込み層の実装について次のような書き方をしますよね。
conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=2, padding=1)
上の例では、入力チャンネル数が3チャンネルで、出力後に16チャンネルになります。このようにチャンネル数が変わるのは上述した演算を行っているためです。
ちなみに、Mセットのカーネルを用意したら(H, W, C)の画像がMセットできるのではないかと思われるかもしれませんが、畳み込み層における処理ではMセット毎にC方向の和を取ります。よって結果的に、M枚の画像をまとめて出力サイズは(H, W, M)になります。
特殊な畳み込み
グループ化畳み込み (Grouped convolutions)
グループ化畳み込み(Grouped convolutions)はAlexNet(Krizhevsky et al., 2012, “ImageNet Classification with Deep Convolutional Neural Networks”)やResNext(Xie et al., 2017, “Aggregated Residual Transformations for Deep Neural Networks”)において用いられていることで有名な畳み込み演算です。
この手法では、下図のように入力特徴マップをチャンネル方向についていくつかのグループに分割し、それぞれのグループに対して割り当てられた異なるカーネルを用いて畳み込みを行い、最後にチャンネル方向に結合します。
普通の畳み込みでは前述した通り全てのチャンネルに対しカーネル数分の計算処理が必要ですが、グループ化畳み込みでは並列化により計算量を削減することができます。例えばチャンネル数が4でカーネル数がM=16の場合には通常は4×16=64回の計算処理が必要ですが、グループ化畳み込みで入力画像をチャンネル方向に4グループに分割すると、(4/4)×16=16回と、1/4倍に削減できます。
上の図でもチャンネルを4つのグループに分割し、それらのグループに並列に畳み込み処理を行っています。ここで、各カーネルのチャンネル方向のサイズはM/4であり、処理後の画像のサイズは通常の畳み込みと同じで(H×W×M)であることに注意してください。また、グループ化畳み込みでは入力チャンネル数と出力チャンネル数がいずれもグループ数で割り切れる数でなければならないことも重要です。
PyTorchでは、グループ化畳み込みは以下のようにグループ数を指定するだけで簡単に実装することができます。
group_conv = nn.Conv2d(in_channels=3, out_channels=15, groups=3)
点単位畳み込み (Point-wise Convolution)
次に紹介するチャンネル別畳み込みを理解するためには、点単位畳み込み(Point-wise Convolution)について知る必要があります。
点単位畳み込みは、カーネルのサイズが(1, 1, C)である畳み込みです。これはつまり、画素ごとに、チャンネル方向のみの畳み込み演算を行い、周辺の画素の情報は用いないということです。イメージとしては、以下の図のようになります。入力画像(H, W, C)に対して(1, 1, C)×Mの点単位畳み込みを適用すると、出力画像サイズは(H, W, M)となります。
なぜ画素ごとにチャンネル方向の畳み込みなんて行うのか、それでは空間的な特徴を抽出する畳み込み演算の意味がないではないかと思われるかもしれません。
この点単位畳み込み演算は、画素ごとにおけるチャンネル方向での全結合層、とイメージするとわかりやすいです。つまり空間方向ではなくチャンネル方向の特徴を抽出しているということです。また、チャンネル方向の次元削減にも用いられます。例えばResNetやGoogLeNetのようなモデルでは、点単位畳み込みを使って層の出力次元を削減したりしています。空間的な解像度を変えることなく、チャンネル方向の次元を調整できるというのは大きな利点なのです。
ちなみに、PyTorchにおける実装ではそのままカーネルサイズを1にするだけです。
pointwise_conv = nn.Conv2d(in_channels=128, out_channels=64, kernel_size=1)
チャンネル別畳み込み (Channel-wise Separable Convolution)
チャンネル別畳み込み(Channel-wise Convolution または Channel-wise Separable Convolution)は深さ単位分離可能畳み込み(Depth-wise Separable Convolution)とも呼ばれ、空間方向の畳み込みを行った後、チャンネル方向の畳み込みを行う手法です。この手法はSeparable Convolution(Sifre, Mallat, 2014, “Rigid-motion scattering for texture classification”)の一部です。
この畳み込みは通常の畳み込みを空間方向、チャンネル方向に分離させたものです。こんなことをするのは、主に二つに分割して計算したほうが計算効率が良くなり、表現能力も向上するためです。
では、詳しく見ていきます。まず、以下の図のように全てのチャンネルに対して空間方向に2次元の畳み込みを行います(深さ方向畳み込み)。ここで用いるカーネルのサイズは(K, K, 1)でチャンネル方向の次元は1であり、各チャンネル毎にそれぞれ別のカーネルを用意してあげる必要があります。すなわち、各チャンネルに対し1枚しかカーネルを用意しません。よって、入力サイズが(H, W, C)のとき、この時点の出力も(H, W, C)となります。
ここで、各チャンネルに対し1枚カーネルを用意しているということは、グループ化畳み込みにおいてグループ数がチャンネル数に等しい場合と同じことを意味します。つまり、チャンネル別畳み込みというのはグループ化畳み込みの特殊な場合のことです。
話を戻しますと、次に先ほど説明した点単位畳み込み演算を行います。この処理におけるカーネルのサイズは(1×1×C)であり、それを出力画像チャンネル数M個分用意します。すなわち、画像の各画素に対してチャンネル方向に畳み込み処理を行います。
まとめると、通常畳み込みにおけるカーネルのサイズは(K×K×C)×Mですが、チャンネル別畳み込みではこれをカーネルのサイズが(K×K×1)×Cの処理と(1×1×C)×Mの処理に分割しているということになります。
PyTorchにおける実装でも、グループ化畳み込みと点単位畳み込みの組み合わせで実装することが可能です。
import torch
import torch.nn as nn
class DepthwiseSeparableConv(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1):
super(DepthwiseSeparableConv, self).__init__()
# Depthwise Convolution: 深さ方向畳み込み(グループ数が入力チャンネル数に等しい)
self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size=kernel_size,
stride=stride, padding=padding, groups=in_channels)
# Pointwise Convolution: 点単位畳み込み
self.pointwise = nn.Conv2d(in_channels, out_channels, kernel_size=1)
def forward(self, x):
x = self.depthwise(x)
x = self.pointwise(x)
return x
まとめ
今回は、グループ化畳み込みとチャネル別畳み込みについて簡単に解説しました。いずれも重要なところなのでわからないところがある場合はよく復習しておきましょう。