Внешний продукт с векторной матрицей пакета Pytorch

#python #pytorch #tensor

#python #pytorch #тензор

Вопрос:

Я пытаюсь сгенерировать векторно-матричное внешнее произведение (тензор) с помощью PyTorch. Предполагая, что вектор v имеет размер p , а матрица M имеет размер qXr , результат произведения должен быть pXqXr.

Пример:

 #size: 2
v = [0, 1] 
#size: 2X3
M = [[0, 1, 2],
     [3, 4, 5]]
#size: 2X2X3
v*M = [[[0, 0, 0],
        [0, 0, 0]],
       [[0, 1, 2],
        [3, 4, 5]]]
  

Для двух векторов v1 и v2 я могу использовать torch.bmm(v1.view(1, -1, 1), v2.view(1, 1, -1)) . Это может быть легко расширено для пакета векторов. Однако я не могу найти решение для случая векторной матрицы. Кроме того, мне нужно выполнить эту операцию для пакетов векторов и матриц.

Ответ №1:

Вы можете использовать torch.einsum оператор:

 torch.einsum('bp,bqr->bpqr', v, M) # batch-wise operation v.shape=(b,p) M.shape=(b,q,r)
torch.einsum('p,qr->pqr', v, M)    # cross-batch operation
  

Комментарии:

1. Спасибо!! Это также кажется более быстрым, чем подход к изменению формы матрицы.

Ответ №2:

Я смог сделать это с помощью следующего кода.

Единый вектор и матрица

 v = torch.arange(3)
M = torch.arange(8).view(2, 4)
# v: tensor([0, 1, 2])
# M: tensor([[0, 1, 2, 3],
#            [4, 5, 6, 7]])

torch.mm(v.unsqueeze(1), M.view(1, 2*4)).view(3,2,4)                                                                                                                                                                              
tensor([[[ 0,  0,  0,  0],
         [ 0,  0,  0,  0]],

        [[ 0,  1,  2,  3],
         [ 4,  5,  6,  7]],

        [[ 0,  2,  4,  6],
         [ 8, 10, 12, 14]]])
  

Для пакета векторов и матриц его можно легко расширить с помощью torch.bmm .

 v = torch.arange(batch_size*2).view(batch_size, 2)
M = torch.arange(batch_size*3*4).view(batch_size, 3, 4)
torch.bmm(v.unsqueeze(2), M.view(-1, 1, 3*4)).view(-1, 2, 3, 4)
  

Ответ №3:

Если [batch_size, z, x, y] является формой целевой матрицы, другим решением является построение двух матриц этой формы с соответствующими элементами в каждой позиции, а затем применение поэлементного умножения. Он отлично работает с пакетами векторов:

 # input matrices
batch_size = 2
x1 = torch.Tensor([0,1])
x2 = torch.Tensor([[0,1,2],
                   [3,4,5]])
x1 = x1.unsqueeze(0).repeat((batch_size, 1))
x2 = x2.unsqueeze(0).repeat((batch_size, 1, 1))

# dimensions
b = x1.shape[0]
z = x1.shape[1]
x = x2.shape[1]
y = x2.shape[2]

# solution
mat1 = x1.reshape(b, z, 1, 1).repeat(1, 1, x, y)
mat2 = x2.reshape(b,1,x,y).repeat(1, z, 1, 1)
mat1*mat2