Как преобразовать 2D и индексные тензоры для torch.nn.utils.rnn.pack_sequence - PullRequest
0 голосов
/ 26 мая 2020

У меня есть коллекция последовательностей в следующем виде:

sequences = torch.tensor([[2,1],[5,6],[3,0])
indexes = torch.tensor([1,0,1])

то есть последовательность 0 состоит только из [5,6], а последовательность 1 состоит из [2,1] , [3,0] . Математически sequence[i] = { sequences[j] such that i = indexes[j] }

Мне нужно передать эти последовательности в LSTM . Поскольку это последовательности переменной длины, в документации pytorch указано использовать что-то вроде torch.nn.utils.rnn.pack_sequence.

К сожалению, этот метод и ему подобные хотят в качестве входных данных список тензоров, где каждый из это L x *, где L - длина единственной последовательности.

Как можно создать что-то, что можно будет передать в pytorch LSTM?

Ps на протяжении всего кода, с которым я работаю тензоры, использующие функции scatter и gather, но я не могу найти способ использовать их для достижения этой цели.

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Прежде всего, вам нужно разделить ваши последовательности. Pack_sequence принимает список тензоров, каждый из которых имеет форму L x *. Другие размеры всегда должны быть одинаковыми для всех последовательностей, но L или длина последовательности могут быть разными. Например, ваша последовательность 0 и 1 может быть упакована как:

sequences = [torch.tensor([[5,6]]), torch.tensor([[2,1],[3,0]])]
packed_seq = torch.nn.utils.rnn.pack_sequence(sequences, enforce_sorted=False)

Здесь, в последовательностях, последовательность [0] имеет форму (1,2), а последовательности [1] имеет форму (2, 2). Первое измерение представляет их длину, которая равна 1 и 2 соответственно.

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

sequences = torch.tensor([[2,1],[5,6],[3,0]])
indexes = torch.tensor([1,0,1])
num_seq = np.unique(indexes)
sequences = [sequences[indexes==seq_id] for seq_id in num_seq]

Это создает sequences=[torch.tensor([[5,6]]), torch.tensor([[2,1],[3,0]])].

0 голосов
/ 05 июня 2020

Я нашел альтернативный и более эффективный способ разделения последовательностей:

sequences = torch.tensor([[2,1],[5,6],[3,0]])
indexes = torch.tensor([1,0,1])

sorted_src = src[indexes.argsort()]
indexes_count = torch.unique(indexes, return_counts=True)[1]

splitted = torch.split(sorted_src, indexes_count.tolist(), dim=0)

Этот метод почти в 3 раза быстрее, чем тот, который предлагает @Mercury.

Измерено с использованием модуля timeit с последовательностями, являющимися тензором (5000,256), и индексами (1500)

...