2016-11-03 3 views
2

У меня есть объем 3D-данных ввода и вы хотите применить ConvNet к каждому фрагменту.Tensorflow: данные среза и применить свертку к каждому фрагменту

Существует дубликат этого вопроса. К сожалению, без ответа: How to slice a batch and apply an operation on each slice in TensorFlow

В Keras я бы использовал слой 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 

Поэтому я добавил Reshape. Это действительно уменьшает количество измерений. Но, судя по всему, это тоже сокращает 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. Что-то вроде 'slices = [tf.squeeze (sliced, squeeze_dims = [1]) для нарезки в tf.split (1,40, x)]' может быть? Это дает мне список из 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.

Смежные вопросы