У меня есть некоторые последовательные данные переменной длины с фиксированной размерностью тензора.Рассмотрим список тензоров s_1, ..., s_b списка некоторых фиксированных размерных матриц [l_1, m, n], ..., [l_b, m, n].Например,
s_1 = [ [[1,2],[3,4]], [[5,6],[7,8]] ]
s_2 = [ [[9,10],[11,12]], [[13,14],[15,16]], [[17,18],[19,20]] ]
Хотя данные приведены в дополненной форме, например:
S = [ [[[1,2],[3,4]], [[5,6],[7,8]], [[0,0],[0,0]]],
[[[9,10],[11,12]], [[13,14],[15,16]], [[17,18],[19,20]]] ]
l = [2,3]
, где S
- тензор дополненных списков матриц, а l
-1-D тензор с i
-ой записью, заданной длиной последовательности i
.
Теперь я хочу извлечь тензор, заданный путем конкатенации списка матриц.Результат должен быть
[ [[1,2],[3,4]], [[5,6],[7,8]], [[9,10],[11,12]], [[13,14],[15,16]], [[17,18],[19,20]] ]
Это вычисление будет выполнено в функции для map
метода tf.data.Dataset
.
Каков правильный подход для этого в тензорном потоке?Я думал об использовании tf.boolean_mask
вместе с tf.sequence_mask
, но не могу получить желаемый результат.Может быть, какое-то умное использование tf.gather_nd
?
EDIT
tf.boolean_mask(S,tf.sequence_mask(l))
, кажется, дает правильный результат, но я могу заставить его работать только вне функциипередано методу map
tf.data.Dataset
.
def _parse_SE(in_example_proto):
S = ...
l = ... #obtain S and l from the record
return tf.tuple([S,l])
dataset = tf.data.TFRecordDataset("test.txt")
dataset = dataset.map(_parse_SE)
dataset = dataset.padded_batch(BATCH_SIZE, padded_shapes=([], [None], [], [None,n,s]))
iterator = dataset.make_initializable_iterator()
[S_bat, l_bat] = iterator.get_next()
wanted_bat = tf.boolean_mask(S_bat,tf.sequence_mask(l_bat)) # when evaluated wanted_bat stores the wanted concatenation
работает.Но если я попытаюсь внести изменения в функцию отображения, я просто получу S
снова:
def _parse_SE(in_example_proto):
S = ...
l = ... #obtain S and l from the record
wanted = tf.boolean_mask(S,tf.sequence_mask(l))
return tf.tuple([wanted,l])
dataset = tf.data.TFRecordDataset("test.txt")
dataset = dataset.map(_parse_SE)
dataset = dataset.padded_batch(BATCH_SIZE, padded_shapes=([], [None], [], [None,n,s]))
iterator = dataset.make_initializable_iterator()
[wanted_bat, l_bat] = iterator.get_next() # when evaluated wanted_bat just contains S_bat of the previous example
РЕДАКТИРОВАТЬ 2
Второй подход не будетработать как функция _parse_SE
, переданная map
, будет применена к каждому элементу пакета в данный момент, а не к целому пакету.Таким образом, мы не можем реорганизовать партию внутри _parse_SE
.