I have a tensor of n-sampled predictions. In this example I sample 4 times a (10,2) result, where this results represents a batch of graphs with each graph having 3+4+3=10 nodes with 2 coordinates. I have a way to select the best sample for each graph, and I have an index telling me this (idx_test). I want to select in an efficient way the elements of the sampled tensor. The best way I have found is like this (toy code example):
rand_test = torch.randint(3, 10, (4, 10, 2))
idx_test = torch.LongTensor([0, 3, 1])
n_nodes = [3, 4, 3]
final_tensor = torch.zeros((10, 2))
accum_nodes = torch.cumsum(torch.LongTensor(n_nodes), 0)
# First iteration is done outside the for loop
final_tensor[:accum_nodes[0]] = rand_test[idx_test[0],:accum_nodes[0],:]
for i, idx in enumerate(idx_test):
final_tensor[accum_nodes[i-1]:accum_nodes[i]] = rand_test[idx,accum_nodes[i-1] :accum_nodes[i], :]
print(final_tensor)
The objective is to obtain the same final tensor without using for loops since in my model this array is large
Thanks!
Advertisement
Answer
You could create a helper tensor containing the ranges of node indices you want to index rand_test with. In your example, you have: i=0 you have 3 nodes with index value 0, i=1 has 4 with value 3, while i=2 has 3 with index value 1.
You can do so using repeat_interleave:
>>> idx_test.repeat_interleave(torch.tensor(n_nodes)) tensor([0, 0, 0, 3, 3, 3, 3, 1, 1, 1])
Then index rand_test using idx and a range:
>>> final_tensor = rand_test[idx, range(len(idx))]
tensor([[5, 5],
[7, 3],
[8, 4],
[7, 5],
[7, 6],
[7, 8],
[9, 9],
[7, 7],
[8, 7],
[3, 7]])