Transposed Convolution の直観的理解

はじめに

PyTorch の ConvTranspose についての挙動を確認します。
簡単のために1次元データについての挙動を示します。
1次元データとは信号、音声などのことです。

Transposed Convolution とは

Transposed Convolution は Convolution の逆の操作のことを指します。
PyTorchのソースによると、ほかにも、fractionally-strided convolution や、deconvolution と呼ばれるとのこのと。
ただし、deconvolution は厳密には別の処理を示す単語なので注意が必要。

Transposed Convolution の挙動確認

ここからは、1次元のTranspose Convolution を例に確認していきます。

PyTorch の ConvTranspose1d のカーネルを[1, 1, 3]に設定して、引数や入力を変えた時の出力を確かめます。
変換のカーネルを[1, 1, 3]とした理由ですが、[1, 2, 3]とすると出力された[3]が 3= 1 + 2 の3なのか 3=1 * 3 の3なのかが分かりにくいからです。

以降のプログラムでは先に必要なモジュールがimport されていることとします。

まずは一番簡単な例として [1]を入力したときの[1, 1, 3]のカーネルを持つ 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 を見てもしっくりこなかったものが、すんなりと入ってくるようになりました。

コメント

タイトルとURLをコピーしました