为什么张量点/重塑与克朗不一致?

时间:2018-09-01 05:15:30

标签: python numpy matrix tensor

如果我定义形状为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]]]])

与第一个输出不同。为什么会这样呢?我在寻找答案时发现了this,但是我不明白为什么该解决方案有效或如何将其推广到更高的维度。

1 个答案:

答案 0 :(得分:1)

我的第一个问题是,为什么您期望它们相同?

让我们做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是标量时发生的情况(这并不重要) How does numpy.tensordot function works step-by-step?

指定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]])

也就是说,我交换了中间的两个轴。

省略重塑,我得到的是与kron相同的(2,2,2,2):

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)

或者使用广播,这两种产品是:

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