Почему tenordot / reshape не согласны с кроной? - PullRequest
0 голосов
/ 01 сентября 2018

Если я определю массив X с формой (2, 2):

X = np.array([[1, 2], [3, 4]])

и возьмите произведение kronecker, затем измените результат, используя

np.kron(X, X).reshape((2, 2, 2, 2))

Я получаю полученную матрицу:

array([[[[ 1,  2],
         [ 2,  4]],

        [[ 3,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 4,  8]],

        [[ 9, 12],
         [12, 16]]]])

Однако, когда я использую np.tensordot(X, X, axes=0), следующая матрица выводится

array([[[[ 1,  2],
         [ 3,  4]],

        [[ 2,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 9, 12]],

        [[ 4,  8],
         [12, 16]]]])

, который отличается от первого выхода. Почему это так? Я нашел это во время поиска ответов, однако я не понимаю, почему это решение работает или как обобщать на более высокие измерения.

1 Ответ

0 голосов
/ 01 сентября 2018

Мой первый вопрос: почему вы ожидаете, что они будут такими же?

Давайте сделаем kron без изменения формы:

In [403]: X = np.array([[1, 2],
     ...:               [3, 4]])
     ...:               
In [404]: np.kron(X,X)
Out[404]: 
array([[ 1,  2,  2,  4],
       [ 3,  4,  6,  8],
       [ 3,  6,  4,  8],
       [ 9, 12, 12, 16]])

Действие легко визуализировать.

[X*1, X*2
 X*3, X*4]

tensordot обычно рассматривается как обобщение np.dot, способное справиться с более сложными ситуациями, чем продукт с общей матрицей (то есть сумма продуктов по одной или нескольким осям). Но здесь нет суммирования.

In [405]: np.tensordot(X,X, axes=0)
Out[405]: 
array([[[[ 1,  2],
         [ 3,  4]],

        [[ 2,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 9, 12]],

        [[ 4,  8],
         [12, 16]]]])

Когда axes является целым числом, а не кортежем, действие немного сложнее понять. Документы говорят:

``axes = 0`` : tensor product :math:`a\otimes b`

Я просто пытался объяснить, что происходит, когда axes является скаляром (это не тривиально) Как работает функция numpy.tensordot шаг за шагом?

Указание axes=0 эквивалентно предоставлению этого кортежа:

np.tensordot(X,X, axes=([],[]))

В любом случае из вывода видно, что этот тензорот производит те же числа - но расположение отличается от kron.

Я могу скопировать kron макет с

In [424]: np.tensordot(X,X,axes=0).transpose(0,2,1,3).reshape(4,4)
Out[424]: 
array([[ 1,  2,  2,  4],
       [ 3,  4,  6,  8],
       [ 3,  6,  4,  8],
       [ 9, 12, 12, 16]])

То есть я меняю средние 2 оси.

И, опуская форму, я получаю то же (2,2,2,2), что вы получаете от kron:

np.tensordot(X,X,axes=0).transpose(0,2,1,3)

Мне нравится ясность np.einsum:

np.einsum('ij,kl->ijkl',X,X)    # = tensordot(X,X,0)
np.einsum('ij,kl->ikjl',X,X)    # = kron(X,X).reshape(2,2,2,2)

Или, используя трансляцию, 2 продукта:

X[:,:,None,None]*X[None,None,:,:]   # tensordot 0
X[:,None,:,None]*X[None,:,None,:]   # kron
...