Tensordot для векторов в NumPy - PullRequest
0 голосов
/ 10 февраля 2019

В настоящее время я пытаюсь создать тензордо, используя numpy для векторов.Например, допустим, у меня есть следующие переменные:

a = [np.array([1, 2]), np.array([3,4])] 
b = [np.array([5,6]), np.array([7,8])]

, и я хочу вычислить «тензорное произведение векторов», то есть [a [0] * b [0], a [0]* b [1], a [1] * b [0], a [1] * b [1]], что в нашем примере выдает:

a x b = [[5,12], [7,16], [15, 24], [21, 32]]

Я пробовал много комбинаций с помощью tenordototпо разным осям, но это никогда не дает мне желаемых результатов: ((

Например, я попробовал следующее:

np.tensordot(a,b)

, что дает мне array(70)

или np.tensordot(a,b, axes = 0), что дает мне

array([[[[ 5,  6],
     [ 7,  8]],

    [[10, 12],
     [14, 16]]],


   [[[15, 18],
     [21, 24]],

    [[20, 24],
     [28, 32]]]])

Я также пытался использовать разные оси, такие как np.tensordot(a,b, axes = ([0], [1])), но безуспешно ...

Может кто-нибудь помочь мне? :) Я 'Я уверен, что это довольно тривиально, но я, кажется, что-то упустил

Спасибо.

1 Ответ

0 голосов
/ 10 февраля 2019
In [663]: a = np.array([[1, 2], [3,4]]); b = np.array([[5,6], [7,8]])

Простая точка (матричное произведение) этих двух массивов:

In [664]: a.dot(b)
Out[664]: 
array([[19, 22],
       [43, 50]])

Ваш требуемый массив:

In [665]: [a[0]*b[0], a[0]*b[1], a[1]*b[0], a[1]*b[1]] 
Out[665]: [array([ 5, 12]), array([ 7, 16]), array([15, 24]), array([21, 32])]
In [666]: np.array(_)
Out[666]: 
array([[ 5, 12],
       [ 7, 16],
       [15, 24],
       [21, 32]])

np.tensordot - попытка обобщить np.dot;для 2d-массивов, подобных этому, он не может делать ничего, чего не могут сделать несколько добавленных транспонирований.

В этом смысле ваш результат не является tensordot.dot включает sum of products;Вы не делаете никаких сумм.Скорее, это больше похоже на внешний продукт, или может быть вариация на kron.

С парой испытаний я воспроизвел ваш массив с einsum:

In [673]: np.einsum('ij,kj->ikj',a,b)
Out[673]: 
array([[[ 5, 12],
        [ 7, 16]],

       [[15, 24],
        [21, 32]]])
In [674]: _.reshape(-1,2)
Out[674]: 
array([[ 5, 12],
       [ 7, 16],
       [15, 24],
       [21, 32]])

einsum какdot и tensordot построены вокруг сумм продуктов, но дают нам более точный контроль над тем, какие оси умножаются, а какие суммируются.Здесь мы не суммируем.

Я могу получить тот же массив 3d с:

In [675]: a[:,None,:]*b[None,:,:]
Out[675]: 
array([[[ 5, 12],
        [ 7, 16]],

       [[15, 24],
        [21, 32]]])

тензордот

В соответствии с документами значение по умолчанию для осей равно 2:

In [714]: np.tensordot(a,b)
Out[714]: array(70)
In [715]: np.tensordot(a,b,axes=2)
Out[715]: array(70)
  • axes = 2: (по умолчанию) тензор двойного сжатия: математика: a:b

Другими словами, умножьте массивы и суммируйте по всем осям,На мой взгляд, это яснее с einsum нотацией:

In [719]: np.einsum('ij,ij',a,b)
Out[719]: 70


In [718]: np.tensordot(a,b,axes=0).shape
Out[718]: (2, 2, 2, 2)
  • axes = 0: тензорный продукт: математика: a\\otimes b: тензорный продукт a \ otimes b
np.einsum('ij,kl',a,b)

Я вижу желаемый результат или, по крайней мере, версию Out[673] в вашем (2,2,2,2) массиве, как своего рода диагональное подмножество.

Я не использую эти скаляры, как axes режимы tensordot.В предыдущем посте или двух я озадачил их, но я не очень хорошо себя чувствую.Я очень предпочитаю ясность, если einsum.

Как функция numpy.tensordot работает пошагово?

...