3

うまく機能している Theano を使用して、単純な畳み込み自動エンコーダーをトレーニングしたいと考えています。conv2dただし、サブサンプリング (ストライド) が使用されている場合にコマンドを元に戻す方法がわかりません。下の画像のように、ストライドが使用されているときに畳み込みコマンドを「反転」する効率的な方法はありますか?

http://cs231n.github.io/convolutional-networks から恥知らずに盗み出して描いた画像。

たとえば、次のように変更したい...

from theano.tensor.nnet.conv import conv2d
x = T.tensor4('x') 
y = T.tanh(  conv2d( x, W, border_mode='valid', subsample = (1,1) )  )
z = conv2d( y, Wprime, border_mode='full', subsample = (1,1)  )

... という状況にsubsample = (2,2)。最初のレイヤーは期待どおりに機能します。ただし、2番目のレイヤーは効果的に「ストライド1で畳み込みを行い、出力の半分を破棄します」。これは、私が探しているものとは明らかに異なる操作です。z長さ と同じ数のニューロンさえありませんxconv2dオリジナルを「再構築」するための 2 番目のコマンドは何xですか?

4

1 に答える 1

5

このことから、重みを結び付けようとしていると推測できます。つまり、最初の操作が との行列乗算でWある場合、出力はW.T、随伴行列で生成されます。あなたの場合、畳み込み演算子とそれに続くサブサンプリングの随伴を探します。

(編集:私は間違って推測しました。形状が正しい限り、「デコンボリューション」に任意のフィルターを使用できます。ただし、随伴について話すことは依然として有益です。後で仮定を緩和することができます。)

畳み込み演算子とサブサンプリング演算子は線形演算子であるため、それらをCおよび でそれぞれ示し、画像の畳み込み + サブサンプリングが次のようになることSを観察します。x

S C x

yと( と同じ空間に存在する)に対する随伴演算は次のS C xようになります。

C.T S.T y

y現在、ST は、正しいサイズが得られるまで のすべてのエントリの周りにゼロを追加することにより、元の画像サイズにアップサンプリングすることに他なりません。

あなたの投稿から、ストライド (1, 1) の畳み込み演算子の随伴を認識しているようです。これは、逆フィルターと逆border_modefilters.dimshuffle(1, 0, 2, 3)[:, :, ::-1, ::-1]畳み込みborder_mode='valid'ですborder_mode='full'

アップサンプリングとこの逆フィルター畳み込みを連結すると、求める随伴が得られます。

注: 勾配を利用したり、これを自動的に取得しT.gradたりする方法があるかもしれませんが、これが正確にどのように行われるかはわかりません。T.jacobian

編集:そこに、私はそれを書き留めました:)

import theano
import theano.tensor as T
import numpy as np

filters = theano.shared(np.random.randn(4, 3, 6, 5).astype('float32'))

inp1 = T.tensor4(dtype='float32')

subsampled_convolution = T.nnet.conv2d(inp1, filters, border_mode='valid', subsample=(2, 2))

inp2 = T.tensor4(dtype='float32')
shp = inp2.shape
upsample = T.zeros((shp[0], shp[1], shp[2] * 2, shp[3] * 2), dtype=inp2.dtype)
upsample = T.set_subtensor(upsample[:, :, ::2, ::2], inp2)
upsampled_convolution = T.nnet.conv2d(upsample,
     filters.dimshuffle(1, 0, 2, 3)[:, :, ::-1, ::-1], border_mode='full')

f1 = theano.function([inp1], subsampled_convolution)
f2 = theano.function([inp2], upsampled_convolution)

x = np.random.randn(1, 3, 10, 10).astype(np.float32)
f1x = f1(x)
y = np.random.randn(*f1x.shape).astype(np.float32)
f2y = f2(y)

p1 = np.dot(f1x.ravel(), y.ravel())
p2 = np.dot(x.ravel(), f2y[:, :, :-1].ravel())

print p1 - p2

p1に等しいことp2は、f2 が f1 の随伴であることを確証します

于 2015-02-26T20:24:33.360 に答える