Network)などで用いられるデコーダーで畳み込みの逆処理(Convtranspose2d)を使うことがあります。このパラメーター設定についてハマったので解説します。目次エンコーダーのConv2DでダウンサンプリングConvTranspose2dのパラメーターエンコーダーのConv2Dでダウンサンプリングまず前提として、MaxPoolingなどのPoolingを使わなくても畳み込み(Conv2D)だけでダウンサンプリングはできます。GANで使われる手法ですが、CNNでも使えます。MNISTで考えましょう。14)どういう処理かというと、モノクロ(チャンネル数1)の28×28の画像を、32チャンネルの3×3の畳み込みを通して、14×14にダウンサンプリングするというものです。これを1つのConv2Dで定義するにはどうしたらよいでしょうか?答えはこうです。padding=1)これはわかりやすいと思います。PyTorchのpaddingは両側に付与するピクセル数、つまりpadding=1なら左右に1ピクセルずつ入れるということに注意してください。$$で表されます(ドキュメントにはdilationがありますが、自分は使ったことないので省略しています)。27」、strideの2で割り1を足すと14.5、小数点以下を切り捨てて「14」、ちゃんと正しく計算できていますね。計算中に端数ができていることについてですが、(エンコーダー側の)CNNの場合はkernelを奇数とすることが普通です。奇数にすると中心のピクセルが生まれ、畳込みの計算が有効に機能しやすいと言われています。ConvTranspose2dのパラメーターここからが本題です。out_channelsのほかに次のようなパラメーターがあります(dilationや解像度に関係なさそうなパラメーターは端折っています)。0公式ドキュメントよりpaddingとoutput_paddingって何が違うんやという感じはしますが、Conv2Dよりパラメーターが多いです。ちなみに解像度は次の式で表されます。これを見るとだいぶ理解できると思います。padding}$$パラメーターが多すぎるので簡略化しましょう。わかりやすいのはstrideです。エンコーダーの場合は、stride=2つまりPoolingでkernel=2と同じようにダウンサンプリングしたので、デコーダーの場合もstride=2でアップサンプリングするのが妥当でしょう。$$という関係式が追加されます。これを上の式に代入すると、いくつか解はありますが、一番わかりやすい場合は「kernel=strideとする」ことだと思います。コードで書くとこうなります。stride=2)本当にこれで合っているか検算してみましょう。1)×stride」の部分は「(14-1)×2=26」、paddingやoutput_paddingは0、これにkernel_size=2を足して28。ちなみに「元のkernel=3の畳み込みはどこに消えたの?」と思われるかもしれませんが、デコーダーの場合はstrideと異なる奇数のカーネルを代入すると、paddingに2の係数がかかっている以上、どうしても端数が出てしまいます。strideと異なるカーネルサイズを入れたいときは、デコーダーでは偶数のカーネルを使ったほうが良さそうです。エンコーダーのkernel=3の畳み込みはデコーダー側では再現しなくてもいいかなと自分は思います。GANの実装を見ていると、DiscriminatorのカーネルサイズとGeneratorのカーネルサイズが違うなんてことがよくあるので大丈夫だと思います。強引に奇数のカーネルをデコーダーで実装したい場合、output_paddingを使えば再現できますが、自分がやった限りでは変なグリッドラインが入ってしまって出力画像がおかしくなりました。画像を拡大して見ると、網目模様の灰色の線がわかると思います。output_paddingを外したら消えたのでこれが悪さをしています。自分はoutput_paddingは使わないほうがいいのではないかなと思います。paddingやoutput_paddingを使わずにstride=kernel_sizeとすることが一番わかりやすいですし、この場合は奇数の制約はありません(stride=kernel_sizeの条件があれば、奇数だろうが偶数だろうが式は成立する)。ConvTrasnpose2DはConv2Dに比べて例が少ないので苦労しましたが、参考になれば幸いです。Commentコメントをキャンセルメールアドレスが公開されることはありません。