前回、cuDNNのサンプルプログラムを動かしていて、Jetson nanoでは残念ながら動かないところがある話を書きました。しかし、それ以上に分からなかったのが、サンプルプログラムの引数です。こんな感じ。
-c2048 -h7 -w7 -k512 -r1 -s1 -pad_h0 -pad_w0 -u1 -v1
まあね、これがコンボリューション・レイヤの計算のための引数であると分かっているので、cはchannel、hはheightなどと想像も多少はつくのです。しかし、何だか分からない引数もあり。多分、AIプロの人はこういう記号を見ただけで分かりあえるのかもしれません。しかし、私などは、まず記号の使い方からちゃんと調べて頭に入れて置かないとダメだな、と思い至りました。
まずはNvidia社のcuDNNのドキュメントに書かれている記号とその意味を示した表へのリンクを掲げておきます。これぞ原典、そこに書かれていることをそのまま理解すればおしまいだろ!
さて、AIのプロの人はこんな表を見なくても既に記号とその意味は血肉となっておるのでありましょう。しかし、わたくしめなどは、この表の後に Convolution Formulasということで、書かれていた式を見たとき、微かに眩暈を覚えましたです。2例をほど簡単なものを引用させていただきましょう。
プロはこれ見て分かるんだ、とちょっと愕然としました。しかし、所詮、コンピュータの計算であります。量子力学の式ではありません。見た目の読みずらさを「棚にあげて」読み取れば、理解できないこともない、と考えましたです。最初、もっとも基本の Normal Convolution の式ですが、「解読」のポイントは2つある 「x」の違いでした。微妙にフォントが違う。よく見れば、真ん中あたりのxが太くて、右の方のxが細い。真ん中あたりのxこそ CONVOLUTION TERMSにいうところの Input (image) Tensor であり、右のxは「コンボリューションの掛け算の意味」じゃないかと。すると
x n, c, p+r, q+s
は、n, c, p+r, q+s という「添字」のついたInput Tensorなんであろう。そして、演算子x記号の後の
w k,c,r,s
こそは、wが Weight Tensor であり、やはりそれに引き続く添え字がk,c,r,sの4つ。これを掛け合わせているのだから、入力のピクセル(的なもの)1個に、重み1個を掛けている!さすればΣsSは、この計算をフィルタ(重み)の横幅全てに対して積算する意味でしょうし、その外側のΣrRは縦幅で総和を求める、最も外側のΣcCこそは全入力チャネルに対して加え合わせる、ことであろうと理解できます。そしてその結果が、出力テンソル y の1要素を決めることになるのだ、と。
y n,k,p,q
なんだ、コンボリューションじゃん
凡才、ここに至りてようやく理解しました。このノーテーション。何も難しいことを書いているわけではなく、全部同じフォントでダラダラ書いているために、何か恐ろし気なものに見えていただけだ、と。
するとようやく、conv_sample に与えられている以下のような引数リストが頭に入ってくるようになったんであります。
-c2048 -h7 -w7 -k512 -r1 -s1 -pad_h0 -pad_w0 -u1 -v1
最初のcは、入力チャネル数、それが2048。コンボリューション・レイヤへの入力となる「画像」相当のものが2048個あるということ。hとwはheightとwidthだから、「画像」相当のものは縦横7x7というサイズ。そしてkは出力チャネル数、512。つまり2048個の入力にコンボリューション計算をして、512個の出力(1個1個の出力には2048個の入力がウエイトに応じて含まれている)になるので、出力数は4分の1となる。r、sはフィルタの縦と横サイズ。ともに1と最小サイズ。後のサンプル実行例では3×3といった「普通」サイズも出てくるけれども、最初は最小サイズなのですかね。その後は、-pad_h、-pad_wなどともろ文字列で書かれているので、これはパディング、ともに0、つまりパディング無し。最後のu, vはサブサンプルのストライドの縦方向と横方向、先ほどのフォーミュラからストライドを読めばは、出力の縦横位置を示す p, qに乗じられていることから、-u1 -v1ならばそのままベタに拾っていくと理解。テストスクリプトの後の方で -u2 -v2みたいな設定が現れてきますが、これこそ1個飛ばしのストライド指定でしょう。
なお1個でてこなかった記号 n は Current Batch Size だそうです。
いや~、ようやく、ほぼほぼ納得。直ぐにまた忘れそうですが。