Python 为什么tensordot/Reforme与kron不一致?
如果我用形状定义数组Python 为什么tensordot/Reforme与kron不一致?,python,numpy,matrix,tensor,Python,Numpy,Matrix,Tensor,如果我用形状定义数组X(2,2): 以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]]]])
X
(2,2):
以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]]]])
这与第一次输出不同。为什么会这样?我在寻找答案时发现,但我不明白为什么这个解决方案有效,或者如何推广到更高的维度。我的第一个问题是,为什么你认为它们是一样的 让我们在不改变形状的情况下执行
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=0
相当于提供此元组:
np.tensordot(X,X, axes=([],[]))
在任何情况下,从输出中可以明显看出,这个tensordot产生的数字是相同的——但布局与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
X[:,:,None,None]*X[None,None,:,:] # tensordot 0
X[:,None,:,None]*X[None,:,None,:] # kron