Transposed Convolution の直観的理解
はじめに
PyTorch の ConvTranspose についての挙動を確認します。
簡単のために 1 次元データについて示します。
ちなみに、1 次元データとは音声信号などです。
Transposed Convolution とは
Transposed Convolution は Convolution の逆の操作のことを指します。
PyTorch のソースによると、ほかにも、fractionally-strided convolution や、deconvolution と呼ばれるとのこのとです。
ただし、deconvolution は厳密には別の処理を示す単語なので注意が必要。
Transposed Convolution の挙動確認
PyTorch の ConvTranspose1d のカーネルを[1, 1, 3]に設定して、引数や入力を変えた時の出力を確かめます。
変換のカーネルを[1, 1, 3]とした理由ですが、[1, 2, 3]とすると出力された[3]が 3= 1 + 2 の 3 なのか 3=1 * 3 の 3 なのかが判然としないからです。
以降のプログラムでは先に必要なモジュールが import されていることとします。
まずは一番簡単な例として [1]を入力したときの Transposed Convolution の出力を確認。
[1, 1, 3]が出力されました。 これは感覚通りです。
イメージは下の図です。
以降、stride を考慮せずにカーネルから出力されたそのままの数値をカーネル出力とします。
私が勝手にカーネル出力と呼んでいるだけですのでご注意ください。
Stride の確認
次は stride 引数について確認します。
入力は [1, 1] とします。
最初に stride=1 のとき。
[1, 2, 4, 3] が出力されました。
イメージは下のようになります。
次に stride=4 のとき。
出力は[1, 1, 3, 0, 1, 1, 3]となりました。
イメージは下のようになります。
stride=4 では、各カーネルの出力の始まる位置が 4 つずれることに相当します。
図では、ストライドを灰色の矢印で、出力の下に示しました。
カーネルのサイズが 3 かつ、stride=4 では、重なり合わない部分ができて、0 で埋められます。
この挙動は、入力が 0 で埋められていると解釈することもできます。
次のように、入力を[1, 0, 0, 0, 1] stride=1 とすると、
予想通りに、入力[1, 1]、stride=4 と同じ出力が得られました。
このときのイメージはつぎのようになります。
図では、0 埋めした部分の出力を薄い色にしました。
Padding の確認
次に padding を確認します。
入力[1, 1] stride=4, padding=1 とします。
出力は[1, 3, 0, 1, 1, ] です。
つまり、両端が削られた出力となっています。
イメージは次のようになります。
convolution のときに padding=1 とすると、両端が 0 で埋められる。
Transposed Convolution は convolution の逆の動きをするように、引数もそろえてあります。
上の図の挙動は、padding した convolution の出力を padding した Transposed Convolution にかけることをイメージするとわかりやすいです。
Transposed Convolution の出力の両端は、本来存在しなかった信号であり、無意味なので削るイメージです。
Output_padding の確認
最後に output_padding を確認。
先ほどのプログラムに、output_padding=1 を加ます。
出力は [1, 3, 0, 1, 1, 3] でした。
イメージは次のようになります。
padding 引数により削除した信号の一部が復活する。
PyTorch のソースには、output_padding は 0 埋めとは違うから注意するようにと書かれていました。
では、padding で消し去った信号以上の数値を output_padding した時はどうなるのでしょうか?
出力は、[1, 3, 0, 1, 1, 3, 0, 0] です。
復活する信号は片側のみで、消し去った信号以上の信号を得るときは 0 で埋められています。
この output_padding は何に使うのでしょうか?
convolution は出力のサイズ計算に床関数が入っています。
つまり、stride=1 以外の時は、Convolution と同一の引数を用いた Transposed Convolution では完全には同一のサイズを復元できないことがあります。
この時に、output_padding を用いると、サイズを調整することができます。
おわりに
これで、https://github.com/slundberg/shap の Gif を見てもしっくりこなかったものが、すんなりと入ってくるようになりました。