[英]Additional information on numpy.einsum()
我试图理解numpy.einsum()函数,但文档以及stackoverflow的这个答案仍然给我一些问题。
我们来看一下爱因斯坦和和答案中定义的矩阵。
A = np.array([0, 1, 2])
B = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
np.einsum('i,ij->i', A, B)
所以,根据我对爱因斯坦和的理解,我会将这个函数翻译成等于符号(A_i * B_ij),所以我会得到:
j = 1:A_1 * B_11 + A_2 * B_21 + A_3 * B_31
j = 2:A_1 * B_12 + A_2 * B_22 + A_3 * B_32
等等,直到j = 4.这给出了
j = 1:0 + 4 + 16
j = 2:0 + 5 + 18
根据我的理解,这将是爱因斯坦的总和。 相反,该函数不执行总和,但将单独的项存储在矩阵中,我们可以在其中发现(A_i * B_ij)的结果
0 0 0 0
4 5 6 7
16 18 20 22
这个功能实际上是如何控制的? 我觉得这是由文档中提到的输出标签控制的:
也可以通过指定输出下标标签来控制输出。 这指定了标签顺序,并允许在需要时不允许或强制求和
所以不知怎的,我假设put ->i
禁用内部总和的求和。 但这是如何工作的呢? 这对我来说并不清楚。 Put ->j
提供了预期的实际爱因斯坦和。
看来你对爱因斯坦求和的理解是不正确的。 您写出的下标操作具有正确的乘法,但总和在错误的轴上。
想想这意味着什么: np.einsum('i,ij->i', A, B)
。
A
具有形状(i,)
, B
具有形状(i, j)
。 B
的每一列乘以A
B
的第二轴上求和,即在标记为j
的轴上求和。 这给出了shape (i,) == (3,)
的输出,而你的下标符号给出了shape (j,) == (4,)
。 你在错误的轴上总结。
更多详情:
请记住,乘法总是先发生。 左侧下标告诉np.einsum
函数输入数组的哪些行/列/等要相互相乘。 此步骤的输出始终与最高维输入数组具有相同的形状。 即,在这一点上,假设的“中间”阵列具有形状(3, 4) == B.shape
。
乘法后,有求和。 这是由右侧省略的下标控制的。 在这种情况下,省略j
,这意味着沿阵列的第一轴求和。 (你是在第0次总结。)
如果您改为编写: np.einsum('i,ij->ij', A, B)
,则不会求和,因为不会省略任何下标。 这样你就得到了问题末尾的数组。
以下是几个例子:
例1:
没有省略的下标,所以没有总结。 只需将B
列乘以A
。 这是你写完的最后一个数组。
>>> (np.einsum('i,ij->ij', A, B) == (A[:, None] * B)).all()
True
例2:
与示例相同。 将列相乘,然后对输出列进行求和。
>>> (np.einsum('i,ij->i', A, B) == (A[:, None] * B).sum(axis=-1)).all()
True
例3:
你在上面写的总和。 将列相乘,然后对输出的行求和。
>>> (np.einsum('i,ij->j', A, B) == (A[:, None] * B).sum(axis=0)).all()
True
例4:
请注意,我们可以省略最后的所有轴,以获得整个数组的总和。
>>> np.einsum('i,ij->', A, B)
98
例5:
请注意,求和确实发生是因为我们重复输入标签'i'
。 如果我们为输入数组的每个轴使用不同的标签,我们可以计算类似于Kronecker产品的东西:
>>> np.einsum('i,jk', A, B).shape
(3, 3, 4)
编辑
爱因斯坦和的NumPy实现与传统定义略有不同。 从技术上讲,爱因斯坦总和没有“输出标签”的概念。 重复输入标签总是暗示这些。
从文档中可以看出: "Whenever a label is repeated, it is summed."
所以,传统上,我们写的东西就像np.einsum('i,ij', A, B)
。 这相当于np.einsum('i,ij->j', A, B)
。 重复i
,因此将其相加,只留下标记为j
的轴。 您可以考虑我们指定无输出标签的总和与仅指定输入中未重复的标签相同。 也就是说,标签'i,ij'
与'i,ij->j'
。
输出标签是在与NumPy实现的扩展或增强,其允许呼叫者迫使求和或执行关于一轴线不求和。 从文档: "The output can be controlled by specifying output subscript labels as well. This specifies the label order, and allows summing to be disallowed or forced when desired."
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.