Depthwise畳み込みとPointwise畳み込みについて

今回は、Depthwise畳み込みとPointwise畳み込みについて学んだことをまとめてみました。そもそも畳み込みや畳み込みニューラルネットワークって何??という方は、以下のリンクの記事で詳しく説明していますので、そちらを読んだ後にこの記事を読んでいただけると、すんなり理解できると思います。

また、動画でも解説しているので、活用してみてください!

Depthwise畳み込み・Pointwise畳み込みとは

畳み込みニューラルネットワークの計算量は膨大なので、スマートフォンやラズベリーパイなどの非力なコンピュータでは実行に時間がかかり使い物になりません。

そこで、モバイル端末や組み込み機器のような非力なコンピュータでも畳み込みニューラルネットワークを実行できるように、大幅な計算コスト減を図ることが可能なアーキテクチャが必要になりました。それが、Depthwise畳み込みとPointwise畳み込みです。

直感的な理解

この章では、Depthwise畳み込みとPointwise畳み込みを使うことで、古典的な畳み込みに比べ大幅に計算量が減らせることを図を使用して解説していきます。

古典的な畳み込みの仕組み

以下の図を見てください。背景が青色で塗られている領域が畳み込みです。

入力特徴マップとしてチャンネル数が3のRGB画像を、畳み込み実行後の出力特徴マップのチャンネル数が4つと仮定します。この場合、畳み込みフィルタは4つ、各フィルタのチャンネル数は3になります。まず、それぞれのフィルタを入力特徴マップに適用します。各々のフィルタから出力されるマップのチャンネル数は、入力される特徴マップのチャンネル数に関わらず1になります。このマップをフィルタ枚数だけチャンネル方向に重ねます。これにより、チャンネル数が4の出力特徴マップが完成します。

今説明した具体例を、文字で置き換えて一般化すると以下の図で表せます。これは以前の記事でも解説しました。

ここで、注目してほしいのは、出力特徴マップのチャンネル数が\(C^l\)なら、畳み込みフィルタの枚数が\(C^l\)必要になる点です(各フィルタはチャンネル方向にも軸が存在するため、フィルタの枚数が増えると計算コストやパラメータ数が膨大になります)。

Depthwise畳み込みとPointwise畳み込み

最初に示した図において、畳み込み層の部分をよく見ると、2つに分割できそうなことが分かります。分割したら、計算コストが大きい前半の畳み込みフィルタを1種類にしてみます。このとき、前半部分をDepthwise畳み込み、後半部分をPointwise畳み込みと名付けます。

※一般的な畳み込み層では、後半の⊕部分で係数1の加算を行いますが、ここでは重み付け和がされるように拡張して考えます。そのため、区別するために黄色で色をぬりました。

これを先ほどと同様に一般化したいと思います。特徴マップの変化を追ってみましょう。まず、入力特徴マップ\((H^{l-1}, W^{l-1}, C^{l-1})\)を考えます。これは、\((K, K, C^{l-1})\)のDepthwise畳み込みにより、\((H^l, W^l, C^{l-1})\)に変換されます。ここで、高さや幅は畳み込みを適用するストライドの程度により変化することに注意してください。次に、\(C^l\)個のPointwise畳み込みにより、深さ\(C^l\)の特徴マップ\((H^l, W^l, C^l)\)が出力されます。

今説明したことを別の図を使用して概観してみます。ここまで説明に使用した図には、特徴マップとフィルタの両方が示されていました。以下の図は、特徴マップのみが示されています。Convolution Layerを示す図からは、1つのパッチにフィルタを適用することで、1つの値に写像されることが分かります。これの特徴マップの変換を下のDepthwise Convolution(左側)とPointwise Convolution(右側)の2ステップに分割します。

Depthwise畳み込みでは空間方向に計算を行うだけで、チャンネル方向の計算を行わないため、適用前後でチャンネル数の変化はありません。Pointwise畳み込みでは別名で1×1畳み込みといわれるように、空間方向の計算は1×1であり、空間方向の計算は行われません。そのかわり、チャンネル方向の計算が行われます。

すなわち、Depthwise畳み込みとPointwise畳み込みを使用した層は、古典的な畳み込み層に比べ、チャンネル方向(深さ)の演算はそのままで、空間方向(幅や高さ)の演算を大幅に減らしていると解釈できます。

古典的な畳み込みでは出力特徴マップのチャンネル数を増減しようとしたら、Depthwise畳み込みに対応する部分も増減しなければなりませんでしたが、2分割したことで、チャンネル数の増減はPointwise畳み込みの数を増減させればよいことが分かります。

現在の一般的な画像認識タスクにおいて性能面で古典的な畳み込みに劣ることは無いため、空間方向よりもチャンネル方向の演算の方が重要なのかもしれません。

次の章では、具体的な計算式を示し、その次の章でどのくらい計算コストを下げることができるのか概観します。

数式で比較してみる

ここでは、古典的な畳み込み層の式を示し、その後にDepthwise畳み込みとPointwise畳み込みの式を示したいと思います。

ポイント

ポイントを先に示します。これを念頭にして式を追ってみてください。

  • 古典的な畳み込みの式とDepthwise畳み込み&Pointwise畳み込みの式は似ているようで異なる
  • Pointwise畳み込みの部分で、重み係数\(w_{k,m}\)が必要になる

数式化

それでは数式で表現したいと思います。まずは、入力、出力特徴マップ及び畳み込みフィルタの設定を以下に示します。

  • 入力特徴マップの形状は、channel last形式で\((H^{l-1}, W^{l-1}, C^{l-1})\)
  • 出力特徴マップの形状は、channel last形式で\((H^l, W^l, C^l)\)
  • それぞれの畳み込みフィルタの形状は\(K, K, C^{l-1}\)、ただし、\(K=2N^{l-1} + 1\)

この条件で古典的な畳み込み層の計算を式で表すと以下のようになります。

$$
I_{xym}^l=\sum_{k=1}^{C^{l-1}}\sum_{i=-N^{l-1}}^{N^{l-1}}\sum_{j=-N^{l-1}}^{N^{l-1}}I^{l-1}_{sx+i, sy+j, k}F_{i+N^{l-1}, j+N^{l-1},k,m}
$$

\(s\)はストライド、\(k\)は入力特徴マップにおいて注目しているチャンネル、\(m\)は出力特徴マップにおいて注目しているチャンネルです。1つ目の\(\sum\)はフィルタをそれぞれのチャンネルに適用した後に要素同士を加算する操作を示しており、Pointwise畳み込みにおいて重み係数をすべて1にしたときに対応します。2つ目及び3つ目の\(\sum\)は空間方向の畳み込みを示しており、のちにDepthwise畳み込みへ書き換える部分です。

それでは、Depthwise畳み込みとPointwise畳み込みの式に変換していきたいと思います。

まず、Depthwise畳み込みにおいてフィルタの種類は1つであることを思い出しましょう。すなわち、\(F_{i+N^{l-1}, j+N^{l-1},k,m}\)から\(m\)を取り除き、\(F_{i+N^{l-1}, j+N^{l-1},k}\)にします。つぎに、Pointwise畳み込みは、最適化対象のパラメータを持ってることを思い出しましょう。そして、出力特徴マップの深さ\(m\)に位置するマップを求めるには、\(m\)番目のPointwise畳み込みフィルタを使用することも重要な点です。そのため、\(m\)番目のPointwise畳み込みフィルタの\(k\)番目の重みパラメータを\(w_{k,m}\)と置くことにします。これらを踏まえてDepthwise畳み込みとPointwise畳み込みを式で表すと以下のようになります。

$$
I_{xym}^l=\sum_{k=1}^{C^{l-1}}w_{k,m}\left\{\sum_{i=-N^{l-1}}^{N^{l-1}}\sum_{j=-N^{l-1}}^{N^{l-1}}I^{l-1}_{sx+i, sy+j, k}F_{i+N^{l-1}, j+N^{l-1},k}\right\}
$$

\(\{\}\)の外がPointwise畳み込み、中がDepthwise畳み込み(正確にはDepthwise畳み込みで計算されたもののうち、\(k\)番目のチャンネルの\((x, y)\)成分)です。

(式は、何度も確認したつもりですが、もし間違っていたらコメント欄等で指摘してくれると嬉しいです)

計算コストの比較

それでは古典的な畳み込みとDepthwise畳み込み&Pointwise畳み込みの計算コストを比較していきます。

古典的な畳み込み層の計算コストおよびパラメータ数

1つのパッチに1つのフィルタを適用するとき乗算回数は\(K^2C^{l-1}\)です。ストライドが1ならば全パッチ数は\(H^{l-1}W^{l-1}\)であることと、フィルタの個数が\(C^l\)であることを考慮すると古典的な畳み込みフィルタの乗算回数は以下のようになります。

$$
K^2C^{l-1}H^{l-1}W^{l-1}×C^l
$$

そして、パラメータ数は1つのフィルタがもつパラメータ数×フィルタの個数なので

$$
K^2C^{l-1}×C^l
$$

となります。

Depthwise畳み込みの乗算回数およびパラメータ数

Depthwise畳み込みでは、畳み込みフィルタの個数は1つなので、以下の式になります。

$$
K^2C^{l-1}H^{l-1}W^{l-1}
$$

パラメータ数は

$$
K^2C^{l-1}
$$

となります。

Pointwise畳み込みの乗算回数およびパラメータ数

Pointwise畳み込みでは、1×1の畳み込みなので、以下のような式で表されます。

$$
C^{l-1}H^lW^l×C^l
$$

パラメータ数は

$$
C^{l-1}C^l
$$

となります。

それぞれを比較

先ほど求めた乗算回数とパラメータ数を表にまとめると以下の表になります。

これを使用して、一般的な畳み込み層と、Depthwise畳み込み&Pointwise畳み込みによる層において、チャンネル数\(C^{l-1}\)の特徴マップから\(C^l\)の特徴マップを出力する場合の乗算回数とパラメータ数を比較してみたいと思います。

普通の畳み込み(式内でStandard-Convと表記)、Depthwise畳み込み&Pointwise畳み込み(式内でDepth-Point-Convと表記)の乗算量及びパラメータ数の比を計算してみます。以下では計算式を簡単にするために、\(W^{l-1} = H^{l-1} = W^l = H^l = D\)と置いています。

$$
\begin{eqnarray}
\begin{array}{rcl}
&&\frac{Depth-Point-Conv\mbox{の乗算回数}}{Standard-Conv\mbox{の乗算回数}}\\
&=&\frac{K^2C^{l-1}D^2 + C^{l-1}D^2×C^l}{K^2C^{l-1}D^2×C^l}\\
&=&\frac{1}{C^l} + \frac{1}{K^2}
\end{array}
\end{eqnarray}
$$

また、パラメータ数の比較を行うと

$$
\begin{eqnarray}
\begin{array}{rcl}
&&\frac{Depth-Point-Conv\mbox{のパラメータ数}}{Standard-Conv\mbox{のパラメータ数}}\\
&=&\frac{K^2C^{l-1} + C^{l-1}C^l}{K^2C^{l-1}×C^l}\\
&=&\frac{1}{C^l} + \frac{1}{K^2}
\end{array}
\end{eqnarray}
$$

となることが分かります。両方とも比率は同じになります。Pointwise畳み込みの個数\(C^l\)の逆数とDepthwise畳み込みのカーネルサイズの2乗の逆数を線形結合したものとして表されることが分かります。

具体的に計算をしてみましょう。ILSVRCなどで使用される畳み込みニューラルネットワークは特徴マップのチャンネル数が100を超すことが多いので、第1項目\(\frac{1}{C^l}\simeq 0\)とできます。フィルタサイズを5×5にすると\(\frac{1}{K^2}=\frac{1}{25}\)になります。すなわち、古典的な畳み込みフィルタを使用するよりも、単純計算で25倍の軽量化に成功できることが分かります。

まとめ

古典的な畳み込みをDepthwise畳み込みとPointwise畳み込みに分割し、Depthwise畳み込みの部分を1種類にするとで計算コストを大幅に小さくすることに成功たこのアーキテクチャは、MobileNetを中心に使用されており、性能面でも劣らないため、組込みシステムで画像認識をする必要性がある場合は、積極的に使用していきたいですね。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です