AI / E資格

CNNは本当に畳み込んでいる? 数式を見ると相互相関だった

氷河期世代のエンジニア、terralienです。E資格の勉強中に「畳み込みニューラルネットワークって要するにどういうコト?」とGeminiに聞いたら、画像を小さな枠でスキャンして特徴を拾う、という説明が返ってきました。説明としては正しいのですが、そこから「で、何を畳んでいるんだろう」が気になってしまったんですよね。数式まで降りてみたら、教科書の畳み込みとPyTorchの Conv2d では、添字の符号がひとつ違っていました。

クリーム色の布を敷いた机の物撮り。3×3のマス目が彫られた木製のゴム印が彫り面をこちらに向けて置かれ、その左の紙には同じ3×3のマス目がティール色のインクで押されている。奥にインクパッドと真鍮のピンセット
彫り面と、押した跡。カーネルを裏返すかどうか、というのはつまりこの2つのどちらを見ているかの話です。

きっかけは、Geminiのわかりやすい説明でした

E資格の勉強で深層学習の用語を確認していると、CNNは何度も登場します。Geminiに素朴な質問を投げたところ、画像を小さなフィルタで端からスキャンし、エッジやパーツを段階的に拾うネットワークだと説明してくれました。

これはCNNの直感としてかなりよい説明です。全結合層のように画像を長い数値列として一気に扱うのではなく、近所の画素を見て、同じフィルタを画像の各場所で共有する。だから局所的な模様を、場所を変えて検出できます。

説明はわかった。でも「畳み込み」という名前だけ、まだわからない。

この違和感を放置したまま暗記するのも気持ちが悪いので、基礎の確認先として先に作っていた畳み込み演算の網羅ノートを参照しました。網羅ノートで定義や仕組みを押さえたうえで、この記事では同じ説明を繰り返さず、Geminiとの会話を入口に、実装で何が起きているかと実際の読み解き方へ進みます。

「畳み込み」は、カーネルを裏返してから重ねる

数学上の2次元畳み込みでは、入力画像 I とカーネル K に対して、次のようにカーネルの添字を反転させて積和します。

(I∗K)(i,j)=∑m∑nI(i−m,  j−n) K(m,n)(I * K)(i,j)=\sum_m\sum_n I(i-m,\;j-n)\,K(m,n)

この i-m、j-n のマイナスが、名前の核心です。カーネルを上下左右に裏返してから入力へ重ね、位置をずらしながら積和する。「畳み込み」という語が指しているのは、この反転そのものです。

反転にはちゃんと理由があって、これを入れると畳み込みは可換になります。つまり入力とカーネルの順番を入れ替えても結果が同じになる。信号処理では効いてくる性質ですが、ニューラルネットワークでは、この可換性を必要とする場面がありません。

演算カーネルの扱い見た目の動作
数学上の畳み込み上下左右に反転反転したカーネルをずらして積和
相互相関反転しないそのままのカーネルをずらして積和

PyTorchのConv2dは、実際には相互相関です

では、CNNのライブラリはどうでしょうか。PyTorch公式ドキュメントの Conv2d は、1行目が「Applies a 2D convolution over an input signal composed of several input planes.」で始まります。ところが、その下に置かれた式の注記にはこう書いてあります——「where ⋆ is the valid 2D cross-correlation operator」。

見出しの説明は convolution、式の中身は cross-correlation。同じページの数行違いで、名前と実際の演算がずれています。しかもそれを隠さず書いてあるので、ドキュメントのほうはむしろ正直ですね。式を書き下すと、次の形になります。

Yj(p,q)=bj+∑k=0Cin−1∑u=0Kh−1∑v=0Kw−1Xk(p+u,  q+v) Kj,k(u,v)Y_j(p,q)=b_j+\sum_{k=0}^{C_{in}-1}\sum_{u=0}^{K_h-1}\sum_{v=0}^{K_w-1} X_k(p+u,\;q+v)\,K_{j,k}(u,v)

p+u と q+v がプラスになっています(b は出力チャネルごとのバイアス、K はカーネルの重み、k は入力チャネル)。入力の窓を取り出し、カーネルをそのまま掛けて足す。CNNでよく見る「フィルタを画像の上でスライドさせる」という説明は、この相互相関の動作です。

数学上の畳み込み カーネルを180°回転させてから重ねる 1 2 3 4 5 6 7 8 9 180°回転 9 8 7 6 5 4 3 2 1 I(i − m, j − n) CNNの相互相関 向きを変えず、そのまま重ねる 1 2 3 4 5 6 7 8 9 そのまま 1 2 3 4 5 6 7 8 9 X(p + u, q + v)
違いは、カーネルを裏返すかどうか。それが添字の符号にそのまま出ます。

この点は、名前だけで判断すると落とし穴になります。E資格で問われたら、「畳み込み層だから数学上の畳み込み」と決めつけず、実装や式の添字を見るのが安全です。

それでもCNNと呼び続けて困らない理由

ここで「ではCNNは間違った名前なのか」と考えたくなりますが、実務上はそこまで困りません。理由は『Deep Learning』(Goodfellow・Bengio・Courville)の9章に書かれていて、カーネルの値が固定された画像処理フィルタではなく、学習によって決まるパラメータだからです。

反転ありの畳み込みを使うネットワークと、反転なしの相互相関を使うネットワークを考えます。片方が学習したカーネルを反転すれば、もう片方と対応する出力を作れます。学習アルゴリズムから見れば、必要な向きの重みを覚えればよいわけです。

観点固定フィルタの画像処理CNN
フィルタの値設計者が決めるデータから学習する
反転の影響結果に直接影響する学習する重みの向きで吸収できる
呼び方畳み込み・相互相関を区別しやすい慣用的にどちらもconvolutionと呼ぶ

だから「反転処理をサボった」というより、学習可能な重みを持つネットワークでは、反転を演算の中に残す必然性が薄い、と考えるほうが正確です。

名前より、CNNが持ち込んだ前提を見る

CNNの本質は、カーネルを反転するかどうかだけではありません。画像の近傍をまとめて見る局所結合、同じ重みを各位置で使う重み共有、入力をずらすと特徴も対応して移る並進同変性。この3点が、全結合層だけで画像を扱うときとの大きな違いです。

  • 局所結合:近所の画素から局所的な模様を取り出す
  • 重み共有:同じ検出器を画像の各場所で使う
  • 並進同変性:入力の移動に応じて特徴の位置も移動する

なお、プーリングなどを重ねると位置の細かさを捨てて、ずれに強い表現へ近づきます。ここで「畳み込みは並進不変性を持つ」と丸暗記すると、畳み込み単体の同変性と混ざります。E資格では、何が位置を残し、何が位置を要約するのかを分けておくと安心です。

結論:心の中では「相互相関NN」と呼んでおきます

Geminiとの会話は、「画像をフィルタでスキャンする」という直感的な説明から始まりました。そこに数式を重ねると、教科書の畳み込みはカーネルを反転し、PyTorchの Conv2d は反転しない。違いは添字の符号ひとつです。

CNNは、名前よりも「局所結合・重み共有・添字の向き」を見る。

それでも教科書もライブラリもCNNと呼びます。学習する重みの向きで差を吸収でき、名前を変えるほうが混乱するからでしょう。試験の答案では「相互相関です」と正確に書き、普段はCNNと呼ぶ。これがいちばん平和な落としどころですね。

ここまで賢そうな理由を並べた後でなんですが、単純に「畳み込んでないじゃん」という違和感が、勉強の入口になったのが面白かっただけなんですよね。こういう小さな引っかかりがあると、数式を見に行く気になる。E資格の勉強、たまには名前にツッコミを入れながら進めるくらいでちょうどよさそうです。

参考資料