Как суммировать на основе индекса вектора - PullRequest
1 голос
/ 23 апреля 2019

У меня есть 3 вектора - вектор суммы, вектор вклада и вектор значения.Я хочу суммировать векторы значений в соответствии с их вектором вклада и поместить их в соответствующий им индекс в векторе суммы.Например:

A = [0;0] (sum vector), B = [0,0,1,1] (contribution vector) C=[20,30,40,10] (value vector)

Вывод: A = [20+30;40+10]

Так, что вектор B имеет ту же длину, что и C, и соответствующий ему индекс говорит нам, какое положение вДобавить к.

Я могу добиться этого с помощью цикла for следующим образом:

for index,value in enumerate(C):
    A[B[index]]+=value

Однако, поскольку это будет частью моего прямого цикла модели NN, это вызоветзначительная проблема производительности.В частности, я искал подход сортировки векторов / матриц, который будет более эффективным.В приведенном выше примере что-то, что эффективно работало для меня, было:

A=torch.zeros(2,1)
C=C.reshape(2,2)
sum=torch.sum(C,1).reshape(2,1)
A += sum

Однако я сталкиваюсь с проблемами, поскольку не всегда бывает, что индексы A имеют одинаковый вклад.Например - случай такой, что B = [0,0,0,1,1] и C=[20,30,40,10,50].Есть ли функция или стратегический способ сделать это для общих случаев?Спасибо!

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

Вы ищете index_add_()

A.index_add_(0, B, C)

Обратите внимание, что B должен иметь тип torch.long (это индексный вектор), а C долженбыть типа torch.float, аналогично типу A.
. Кроме того, вы можете использовать первый аргумент dim для суммирования по разным измерениям в случае, если A и C являются многомернымитензоры.

0 голосов
/ 24 апреля 2019

Выполнение цикла в некоторой степени снижает производительность. Предположим, что число уникальных типов в векторе вклада намного меньше, чем длина B (или C), вы можете сделать для цикла, как показано ниже, с предположением O(num_types) << O (len_B) `: </p>


num_types = 3
B_len = 5
C_len = B_len

B = torch.randint(0, num_types, size=[B_len,])
"""
>>> B
tensor([2, 1, 1, 0, 0])
"""

C = torch.randint(0, 10, size=[C_len,])
C = C.float()
"""
>>> C
tensor([1., 5., 7., 6., 2.])
"""

# For loop here
A = [torch.sum(C * (torch.eq(B, type).float()) for type in range(num_types)]
# A = [tensor(8.), tensor(12.), tensor(1.)]

# Convert it to torch.tensor
A = torch.stack(A)
# tensor([ 8., 12.,  1.])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...