【问题标题】:vectorized/broadcasted Dot product of numpy arrays with different dimensions具有不同维度的numpy数组的矢量化/广播点积
【发布时间】:2017-11-06 22:43:24
【问题描述】:

问题:

我想计算一组非常大的数据的点积。我可以在嵌套的 for 循环中执行此操作,但这太慢了。 这是一个小例子:

import numpy as np

points = np.array([[0.5, 2, 3, 5.5, 8, 11], [1, 2, -1.5, 0.5, 4, 5]])
lines = np.array([[0, 2, 4, 6, 10, 10, 0, 0], [0, 0, 0, 0, 0, 4, 4, 0]])
x1 = lines[0][0:-1]
y1 = lines[1][0:-1]
L1 = np.asarray([x1, y1])

# calculate the relative length of the projection
# of each point onto each line
a = np.diff(lines)
b = points[:,:,None] - L1[:,None,:]
print(a.shape)
print(b.shape)

[rows, cols, pages] = np.shape(b)
Z = np.zeros((cols, pages))
for k in range(cols):
    for l in range(pages):
        Z[k][l] = a[0][l]*b[0][k][l] + a[1][l]*b[1][k][l]

N = np.linalg.norm(a, axis=0)**2
relativeProjectionLength = np.squeeze(np.asarray(Z/N))

在此示例中,a 和 b 的前两个维度表示我需要用于点积的 x 和 y 坐标。 a的形状是(2,7),b的形状是(2,6,7)。由于点积减少了第一个维度,我希望结果是形状 (6,7)。如果没有慢速循环,我该如何计算?

我尝试过的:

我认为正确广播的 numpy.dot 可以完成这项工作,但是我无法正确设置尺寸。

a = a[:, None, :]
Z = np.dot(a,b)

这给了我以下错误:

形状 (2,1,7) 和 (2,6,7) 未对齐:7 (dim 2) != 6 (dim 1)

【问题讨论】:

  • +* 等元素明智操作一起使用的广播不适用于np.dot。它有自己的坐标轴匹配规则。

标签: python numpy


【解决方案1】:

你可以使用np.einsum -

np.einsum('ij,ikj->kj',a,b)

解释:

  • 保持两个输入的最后一个轴对齐。

  • 从这些中减去第一个。

  • 让剩下的留下,也就是b的第二轴。

Usual rules on whether to use einsum or stick to a loopy-dot based method apply here.

【讨论】:

  • 您好,谢谢您的回答。它完美地完成了这项工作。我发现 np.einsum 的符号非常直观,因为可以直接看到哪些维度减少了!不同方法的运行时分析也会出现在我的书签中。
【解决方案2】:

numpy.dot 不会减少第一个维度。来自文档:

对于 N 维,它是 a 的最后一个轴和 b 的倒数第二个轴的和积:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])

这正是错误告诉您的内容:它试图将第一个向量中的轴 2 与第二个向量中的轴 1 匹配。

您可以使用numpy.rollaxis 或更好的numpy.moveaxis 来解决此问题。而不是a = a[:, None, :],做

a = np.movesxis(a, 0, -1)
b = np.moveaxis(b, 0, -2)
Z = np.dot(a, b)

更好的是,您可以构建数组以预先设置正确的形状。例如,转置lines 并做a = np.diff(lines, axis=0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多