Developer Blog AIフレームワーク 開発ブログ

2025年11月25日 2025年11月12日

ややこしいのは仕方ないけど...

「畳込み」の続き

PremitiveConvLayerについて

先日11月12日に、現役のConvLayerに対して「何をやってるんか、分らへんかった。」という記事を書きました。その中で言及したように、その原理どうりにプログラミングすると、こうなるというのを、PrimitiveConvLayerとして新たに作り、この説明をするとともに、ufiesia0のNeuron.pyに加えました。

と、書きましたが、これは手ごわい!

そうなんです。正直に言うと、原理通りだから簡単だと言いたかったのですが、とんでもなかったのです。
まあ、ともかく作った以上、ちゃんと動くものでなければと思って現役のConvLayerとの照合を行いました。それで一発で照合OKとなるつもりだったのは、まったく読みが甘くて、ちょっとやそっとではOKにならずに思わぬ苦戦をしました。そうして、何がいけないんだろうかと、デバッグをするうち、しっかり現役のConvLayerの、いや正確には、Col2imの潜在バグを見つけてしまいました。

入力の画像が、チャネル数、縦、横、それぞれ、C、Ih、Iwで、カーネルサイズ(フィルタサイズ)が、Fh、Fw、そしてストライドがSh,、Sw、パディングがpadのときに、出力の大きさは、
Oh = (Ih - Fh + 2*pad) // Sh + 1
Ow = (Iw - Fw +2*pad) // Sw + 1
となります。
しかしこの // が曲者で、このために出力サイズから、入力サイズを復元することは出来ないのです。

そしてpyainoでは、ConvLayerから、順伝播でIm2colを、逆伝播でCol2imを呼んでいるのですが、Im2colもCol2imも、それぞれの入力のチャネル数、縦、横(C、Ih、Iw)、カーネルサイズ(Fh、Fw)、ストライド(Sh,、Sw)を変換に必要なものとして渡すようにしていたのですが、残念ながら出力の大きさは渡していませんでした。そうなんです。それで // の余りを捨てる整数の割り算で捨てられた余りの分の大きさが分からなかったのです。

初歩的なミスでまことに恥ずかしい...

ああ、何とこれまですでにいろいろと、使ってきたConvLayerにもかかわらず、こんな初歩的なミスが潜んでいたとは...
それで、とても恥ずかしいのですが、反省して、このあたりのコードを見直すことにしました。

またもや、びっくり!常識が数年でひっくり返る?!

見直す中で、このあたりのコードを書いた当時はなかった、chatGPTも使っていたのですが、そこでConvolutionの逆の処理をDeconvolutionとしたら、おっとっと、この言葉を使うことが不適切だということを指摘されてしまいました。どうやらこの3~5年の間に、私がpyainoに実装しているDeconvolutionは、ConvTransposeと呼ぶべきということなのです。これはもはや歴史的に、といっても、数年のレベルで、がらりと、常識が変わってしまう「有名な一例」らしいのです。こんなところで常識外れにされるのは不本意なので、さっそく、DeconvolutionはConvTransposeと呼び変えることとして、先の潜在バグの修正と併せてGithubに反映しました。ただし、既存のプログラムの互換性のために、元の名前も残していますが...

おまけ

この畳込み処理では、たくさんパラメータが出てきます。先のPrimitiveConvLayerの構成情報だけでも以下のとおりです。
self.config = C, Ih, Iw, M, Fh, Fw, Sh, Sw, pad, Oh, Ow
そしてこれをIm2ColやCol2imなどと受け渡したり、あるいは、自身を含むそれぞれで、これらを使っていろいろ操作したりするので、やっているうちに、ほんとうにどれがどれだか、とりちがえてしまうことしきりなのです。決して難しい数式は出てこないのですが、このパラメータの数が多いことそのものに、「やられてしまう」のです。やっているうちに、「僕はカラスより劣るのではないか?」と思えてきて、本当に情けなくなります。とほほほほ...

ブログのご感想やAIフレームワーク「ufiesia」「pyaino」に関するお問い合わせは、
問い合わせフォームからお送りください。

お問い合わせ
  • お問い合わせ内容によりましては、ご期待に添えない場合やご回答が出来ない事が有ります。