[英]Python Numpy vectorizing along second and third dimension
I want to vectorize the calculation along the second and third axis, but I cannot find a way to deal with the last for loop:我想将计算沿第二个和第三个轴矢量化,但我找不到处理最后一个 for 循环的方法:
n = 3000
D = 2000
delta = np.arrange(D * n).reshape(D, n)
M = np.arrange(D * n * n).reshape(D, n, n)
result = np.zeros(D, n)
for i in range(D):
result[i, :] = np.dot(delta[i, :], M[i, :, :])
Let's construct a small example (no need to use big sizes like 3000):让我们构建一个小例子(不需要使用像 3000 这样的大尺寸):
In [122]: n,D = 3,2
In [123]: delta = np.arange(D*n).reshape(D,n) # not arrange
In [124]: M = np.arange(D*n*n).reshape(D,n,n)
In [125]: result = np.zeros(D, n)
...: for i in range(D):
...: result[i, :] = np.dot(delta[i, :], M[i, :, :])
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-125-413de80d25a5> in <module>
----> 1 result = np.zeros(D, n)
2 for i in range(D):
3 result[i, :] = np.dot(delta[i, :], M[i, :, :])
4
TypeError: data type not understood
Oops, your np.zeros
call is wrong!糟糕,您的
np.zeros
调用是错误的!
In [126]: result = np.zeros((D, n),int)
...: for i in range(D):
...: result[i, :] = np.dot(delta[i, :], M[i, :, :])
...:
In [127]: result
Out[127]:
array([[ 15, 18, 21],
[150, 162, 174]])
einsum
is a handy way of matching diverse dimensions. einsum
是一种匹配不同维度的便捷方式。 Note how the i
dimension matches yours.请注意
i
维度如何与您的相匹配。
In [128]: np.einsum('ij,ijk->ik',delta, M)
Out[128]:
array([[ 15, 18, 21],
[150, 162, 174]])
Let's try the matmul/@
function which is supposed to handle 'batch' dots like yours:让我们试试
matmul/@
function 它应该可以处理像你这样的“批处理”点:
In [129]: np.matmul(delta, M)
Out[129]:
array([[[ 15, 18, 21],
[ 42, 54, 66]],
[[ 42, 45, 48],
[150, 162, 174]]])
In [130]: _.shape
Out[130]: (2, 2, 3)
Oops, too much.哎呀,太多了。 Let's add a dimension to
delta
to make it (D,1,n).让我们为
delta
添加一个维度以使其成为 (D,1,n)。 That way the D
dimension is consistently the first of 3:这样,
D
维度始终是 3 个维度中的第一个:
In [131]: np.matmul(delta[:,None,:], M)
Out[131]:
array([[[ 15, 18, 21]],
[[150, 162, 174]]])
Those are the correct values, but the shape is (2,1,3).这些是正确的值,但形状是 (2,1,3)。 We can get rid of that middle dimension with reshape or index or squeeze:
我们可以通过 reshape 或 index 或挤压来摆脱那个中间维度:
In [132]: np.matmul(delta[:,None,:], M).squeeze()
Out[132]:
array([[ 15, 18, 21],
[150, 162, 174]])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.