子数组的 numpy 点积?

numpy dot product of sub array?

我有两个类似的ndarray

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

虽然可以使用 np.dot(n1, n2) 轻松计算它们的点积,但正确答案为 30。如果我需要在 n1 和 n2 的两个子数组上操作点怎么办,例如

np.dot(np.array([1,2]), np.array([1,2]))  # first two elements from arrays
np.dot(np.array([3,4]), np.array([3,4]))  # last two elements

给出 [5, 25]。我可以通过手动拆分数组和 for 循环来完成。但是想知道是否有更多 pythonic 和 numpy 的方法来做到这一点?

这是一种方法:

In [124]: n1 = np.array([1,2,3,4])
     ...: n2 = np.array([1,2,3,4])
     ...: 

整形将数组拆分为所需的块:

In [125]: n1.reshape(2,2)
Out[125]: 
array([[1, 2],
       [3, 4]])

现在将所有元素相乘 - 并在右轴上求和(有时我猜测轴)。

In [126]: (n1.reshape(2,2)*n2.reshape(2,2)).sum(axis=1)
Out[126]: array([ 5, 25])

乘积之和也可以用 einsum 来表示——不过不用担心语法太新:

In [127]: np.einsum('ij,ij->i',n1.reshape(2,2), n2.reshape(2,2))
Out[127]: array([ 5, 25])

重塑为两个两列数组,因为我们想要每个长度为 2 的子数组,然后使用 np.einsum 进行总和缩减 -

a = n1.reshape(-1,2)
b = n2.reshape(-1,2)

out = np.einsum('ij,ij->i',a,b)

另一种方法是进行逐元素乘法,然后使用一次整形,最后对每一行求和以获得紧凑的解决方案 -

out = (n1*n2).reshape(-1,2).sum(1) # 2 is subarray length

您可以通过手动对数组进行乘法和加法来执行点运算。如果您使用 np.add's reduceat 方法,您可以灵活地对完全任意的区间求和:

n = np.add.reduceat(n1 * n2, [0, 2])

如果你想得到前三个和最后一个元素的总和,你只需为索引(第二个参数)传递 [0, 3]

如果您对任意长度的间隔不感兴趣,请改用其他答案。