2016-11-03 48 views
2

我有一个3D卷的输入数据,并且想要将ConvNet应用于每个切片。Tensorflow:切片数据并将卷积应用到每个切片

这是个重复的问题。可悲的是没有回答: How to slice a batch and apply an operation on each slice in TensorFlow

在凯拉斯我会用TimeDistributed图层。 在Tensorflow中我找不到直接的等价物。相反,它接合我,我不得不自己分割数据。

这是我到目前为止的代码:

x=tf.placeholder(tf.float32, shape=[None, 40, 40, 40, 1]) 
slices=tf.split(0,40, x) 

segmented_slices=[] 

for slice in slices: 
    # apply a ConvNet to each slice 
    reshaped=tf.reshape(slice, (40, 40, 1))   #<-------second error 
    # reshaped=tf.reshape(slice, (None, 40, 40, 1)) #<-------third error 

    # segmented_slice=conv2d(slice, 3,1,32)   #<-------first error 
    segmented_slice=conv2d(reshaped, 3,1,32) 
    segmented_slice=conv2d(segmented_slice, 3,32,32) 

    #... (more convolutions) 

    segmented_slices.append(segmented_slice) 

volume=tf.concat(0, segmented_slices) 

基本布局是split - > ConvNet - >concat。 但split保持维度。如果我简单地传递到slice卷积,它抱怨:

ValueError: Shape (?, 40, 40, 40, 1) must have rank 4 

所以我加了重塑。这确实减少了维度的数量。但显然它也削减了batch_size。与第一个错误消息相比,问号和前40个都不见了。

ValueError: Shape (40, 40, 1) must have rank 4 

看来我需要保持batch_size在重塑。我试图在元组中添加None。这产生了另一个错误信息:

TypeError: Expected int32, got None of type '_Message' instead. 

这是正确的方法吗? 我应该自己处理这个吗?

+0

代码顶部的tf.split指定要分割的批次维度,但它看起来像要在大小为40的一个维上进行分割。 'tf.split(1,40,x)]'''slice = [tf.squeeze(sliced,squeeze_dims = [1])''''''''''''''这给了我一个40(?,40,40,1)张量表的清单。顺便说一句,你可以通过使用'tf.shape'将形状作为张量来重塑某些东西,但保留一个或多个未知维度。 –

回答

2

如果Keras TimeDistributed层是你所需要的,让我们来看看它是如何实现的:

input_length = input_shape[1] # assume 2nd dim is the one to slice 
# ... 
# Shape: (num_samples * timesteps, ...) 
inputs = K.reshape(inputs, (-1,) + input_shape[2:]) 
y = self.layer.call(inputs) # (num_samples * timesteps, ...) 
# Shape: (num_samples, timesteps, ...) 
output_shape = self.compute_output_shape(input_shape) 
y = K.reshape(y, (-1, input_length) + output_shape[2:]) 

的基本思路是,以重塑张量以这样的方式在第一和第二尺寸(批次和切片尺寸)折叠成一个。换句话说,每个“切片”可以被认为是该批次中的附加数据点。然后对这个新的虚拟批次应用任何计算并在最后重新恢复到原始形状。 所有这些操作都可以在Tensorflow中轻松实现。