Как получить длину последовательности из дополненных пакетов из tf.data.Dataset? - PullRequest
2 голосов
/ 29 мая 2020

Например, представьте, что я использую набор данных Librispeech через TFDS (или любой другой набор данных, включая последовательности данных различной длины), а затем использую padded_batch для создания пакетов, например это:

import tensorflow_datasets as tfds

dataset = tfds.load(name="librispeech", split="train_clean100")
dataset = dataset.shuffle(1024)
dataset = dataset.padded_batch(32)

Теперь при итерации по результирующему набору данных, то есть по (дополненным) пакетам, как я могу узнать длину исходной последовательности в дополненном пакете? Или эта информация сейчас потеряна? Как мне расширить конвейер, чтобы включить его? Есть ли специальный набор данных вроде AddSeqLengthInfoDataset или около того? Это должно было бы запускать перед padded_batch, верно? (Это в основном эквивалент моего вопроса для TF PaddingFIFOQueue, но для tf.data.Dataset.)

Есть какой-нибудь пример? (Мне немного интересно, что я ничего об этом не нашел. Я предполагаю, что это довольно стандартное требование, когда вы работаете с последовательностями, что вам нужна информация об исходной длине последовательностей, или нет?)

1 Ответ

2 голосов
/ 29 мая 2020

Вы можете просто добавить новое поле в набор данных, содержащее размер последовательности, например, так:

import tensorflow as tf

# Make a dataset with variable-size data
def generate_data():
    for i in range(10):
        yield {'id': i, 'data': range(i % 5)}
ds = tf.data.Dataset.from_generator(generate_data,
                                    {'id': tf.int32, 'data': tf.int32},
                                    {'id': [], 'data': [None]})
# Add field with size of data
ds = ds.map(lambda item: {**item, 'size': tf.shape(item['data'])[0]})
# Padded batch
ds = ds.padded_batch(3)
# Show dataset
for batch in ds:
    tf.print(batch)

Вывод:

{'data': [[0 0]
 [0 0]
 [0 1]], 'id': [0 1 2], 'size': [0 1 2]}
{'data': [[0 1 2 0]
 [0 1 2 3]
 [0 0 0 0]], 'id': [3 4 5], 'size': [3 4 0]}
{'data': [[0 0 0]
 [0 1 0]
 [0 1 2]], 'id': [6 7 8], 'size': [1 2 3]}
{'data': [[0 1 2 3]], 'id': [9], 'size': [4]}

Затем вы можете использовать для пример tf.sequence_mask со значением этого поля для маскировки значений заполнения.

Другой вариант - просто передать некоторые специальные padding_values в padded_batch, которые не может появиться в фактических данных, например, -1 или nan, но это зависит от того, действительно ли это недопустимые значения для вашей проблемы.

...