2017-02-06 3 views
2

テンソルフローのミニバッチのサンプルに依存するフィルタを使用して2次元畳み込みを行いたいとします。ミニバッチあたりのサンプル数が分からない場合は、どのようにしてどのように行うことができますか?Tensorflow:ミニバッチの各サンプルに異なるフィルタを使用した畳み込み

MB x H x W x Channelsの入力データinpがあり、という形式のフィルタFがあります。それは

inp = tf.placeholder('float', [None, H, W, channels_img], name='img_input')ことが想定される

tf.nn.conv2d(inp, F, strides = [1,1,1,1])としますが、Fにはミニバッチディメンションを使用できないため、これは許可されていません。任意のアイデアはどのようにこの問題を解決するには?その周りに行くために

+1

おそらく 'tf.expand_dims'を使って '偽ミニバッチディメンション'を追加した後、' tf.nn.conv3d'を使うことができます。ここで、フィルタ深度はバッチサイズと一致します。可変バッチサイズでどれくらいうまくいくかはわかりません。 –

+0

@RobertLacok素晴らしいアイデアのように聞こえます。唯一の問題は、私がそれを行うと、私は新しい空間次元(ミニバッチ次元)のサイズを知らないということです。しかし、私は試してみて...多分それはとにかく動作します... –

+0

私はあなたがそれの上限を知って、その次元で重み(フィルタ)を初期化する必要があると思います。次に、実行時に、 'batch_size = tf.shape(input)[0]'のようなことを行い、ディメンションを推測し、フィルタのスライスだけを使用することができます。純粋に示唆していますが、私はそのようなことを試みたことはないので、問題を引き起こす可能性があります。 –

答えて

2

提案されたトリックは実際には正しくないと思います。 tf.conv3d()レイヤーで起こることは、入力が深度(=実際のバッチ)ディメンションで畳み込まれ、結果のフィーチャーマップに沿って合計されることです。 padding='SAME'を使用すると、結果の出力数はバッチサイズと同じになるので、だまされます。

EDIT:さまざまなミニバッチ要素に対して異なるフィルタを使用して畳み込みを行う方法として、深さ方向の畳み込みを「ハッキングする」ことが考えられます。次のようにあなたがtf.map_fnを使用することができます(と思う)場合MB

inp = tf.placeholder(tf.float32, [MB, H, W, channels_img]) 

# F has shape (MB, fh, fw, channels, out_channels) 
# REM: with the notation in the question, we need: channels_img==channels 

F = tf.transpose(F, [1, 2, 0, 3, 4]) 
F = tf.reshape(F, [fh, fw, channels*MB, out_channels) 

inp_r = tf.transpose(inp, [1, 2, 0, 3]) # shape (H, W, MB, channels_img) 
inp_r = tf.reshape(inp, [1, H, W, MB*channels_img]) 

out = tf.nn.depthwise_conv2d(
      inp_r, 
      filter=F, 
      strides=[1, 1, 1, 1], 
      padding='VALID') # here no requirement about padding being 'VALID', use whatever you want. 
# Now out shape is (1, H, W, MB*channels*out_channels) 

out = tf.reshape(out, [H, W, MB, channels, out_channels) # careful about the order of depthwise conv out_channels! 
out = tf.transpose(out, [2, 0, 1, 3, 4]) 
out = tf.reduce_sum(out, axis=3) 

# out shape is now (MB, H, W, out_channels) 

が不明で、tf.shape()を使用して動的に決定することが可能でなければなりません

+0

私はいくつかの次元/転置... – drasros

+0

...と[gist](https://gist.github.com/drasros/cf2bea04d4e7c134a90e66156c626576)のテストを私は(1d convsを使ってしかし、これは違いはありません) – drasros

2

彼らの方法は、「偽」バッチサイズを作成するために

tf.expand_dims(inp, 0) 

を使用して余分な次元を追加しています。

tf.nn.conv3d() 

操作では、フィルターの深さがバッチサイズと一致する操作を使用します。これにより、各バッチ内の1つのサンプルのみで各フィルタが畳み込まれます。

悲しいことに、この方法で可変バッチサイズの問題は解決されず、畳み込みのみが解決されます。

1

を::

inp = tf.placeholder(tf.float32, [None, h, w, c_in]) 
def single_conv(tupl): 
    x, kernel = tupl 
    return tf.nn.conv2d(x, kernel, strides=(1, 1, 1, 1), padding='VALID') 
# Assume kernels shape is [tf.shape(inp)[0], fh, fw, c_in, c_out] 
batch_wise_conv = tf.squeeze(tf.map_fn(
    single_conv, (tf.expand_dims(inp, 1), kernels), dtype=tf.float32), 
    axis=1 
) 
をバッチサイズ MBが知られていると仮定すると、

にはdtypeを指定することが重要です。基本的には、このソリューションはbatch_dim_sizeの2D畳み込み演算を定義します。

関連する問題