你忘了显示数组:
In [87]: arr1
Out[87]:
array([[0, 1],
[2, 3],
[4, 5],
[6, 7]])
In [88]: arr2
Out[88]:
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [89]: ans
Out[89]:
array([[ 8, 9, 10, 11],
[ 32, 37, 42, 47],
[ 56, 65, 74, 83],
[ 80, 93, 106, 119]])
In [90]: ans2
Out[90]:
array([[ 76, 124],
[ 98, 162]])
In [91]: ans3
Out[91]: array(238)
ans 只是普通的点,矩阵乘积:
In [92]: np.dot(arr1,arr2)
Out[92]:
array([[ 8, 9, 10, 11],
[ 32, 37, 42, 47],
[ 56, 65, 74, 83],
[ 80, 93, 106, 119]])
dot sum-of-products 在arr1 的([1],[0]) 轴1 和arr2 的轴0 上执行(常规跨列,沿行向下)。使用 2d 'sum across ...' 短语可能会令人困惑。处理 1 或 3d 数组时更清楚。这里将匹配大小的 2 个维度相加,留下 (4,4)。
ans2 反转它们,对 4 求和,产生 (2,2):
In [94]: np.dot(arr2,arr1)
Out[94]:
array([[ 76, 98],
[124, 162]])
tensordot 刚刚转置了 2 个数组并执行了常规的dot:
In [95]: np.dot(arr1.T,arr2.T)
Out[95]:
array([[ 76, 124],
[ 98, 162]])
ans3 使用转置和整形 (ravel),在两个轴上求和:
In [98]: np.dot(arr1.ravel(),arr2.T.ravel())
Out[98]: 238
一般来说,tensordot 混合使用转置和重塑来将问题简化为二维np.dot 问题。然后它可能会重塑和转置结果。
我发现einsum 的尺寸控制更清晰:
In [99]: np.einsum('ij,jk->ik',arr1,arr2)
Out[99]:
array([[ 8, 9, 10, 11],
[ 32, 37, 42, 47],
[ 56, 65, 74, 83],
[ 80, 93, 106, 119]])
In [100]: np.einsum('ji,kj->ik',arr1,arr2)
Out[100]:
array([[ 76, 124],
[ 98, 162]])
In [101]: np.einsum('ij,ji',arr1,arr2)
Out[101]: 238
随着einsum 和matmul/@ 的发展,tensordot 的必要性越来越少。它更难理解,并且没有任何速度或灵活性优势。不要担心理解它。
ans3 是其他 2 个答案的轨迹(对角线之和):
In [103]: np.trace(ans)
Out[103]: 238
In [104]: np.trace(ans2)
Out[104]: 238