[英]Python - Numpy : 3D matrix * 2D vector fast calculation
大家好,
这是我想做的。 我有两个数组:
. 我想要(如果存在)单行numpy操作,该操作为我提供了(2,50)包含旋转矢量的数组,我们称其为 。 contains the product of the k-ith rotation matrix with the k-ith vector. 我的意思是, 的第k个元素包含第k个旋转矩阵与第k个矢量的乘积。
目前,我想出了以下循环:
for ind,elt in enumerate(np.arange(nb_of_vectors)):
rotated_vector[ind] = np.dot( rotation_matrices[:,:,ind], vectors[:,ind] )
我认为还有改进的空间。 如果您有任何建议,欢迎您。
感谢您的时间。
贾加拉尔
对于需要沿一个或多个轴对齐的缩小,可以使用np.einsum
rotated_vector = np.einsum('ijk,jk->ki',rotation_matrices,vectors)
请注意,输出的形状为(N,2)
,其中N
是向量的数量。 如果相反,您正在寻找形状为(2,N)
的输出,并且需要原始代码为: rotated_vector[:,ind] = np.dot(...)
,只需编辑输出字符串表示ik
而不是ki
。
运行时测试-
In [24]: def org_app(rotation_matrices,vectors):
...: nb_of_vectors = vectors.shape[1]
...: r = np.zeros((nb_of_vectors,2))
...: for ind,elt in enumerate(np.arange(nb_of_vectors)):
...: r[ind] = np.dot( rotation_matrices[:,:,ind], vectors[:,ind] )
...: return r
...:
In [25]: # Input arrays
...: rotation_matrices = np.random.rand(2,2,50)
...: vectors = np.random.rand(2,50)
...:
In [26]: out1 = org_app(rotation_matrices,vectors)
In [27]: out2 = np.einsum('ijk,jk->ki',rotation_matrices,vectors)
In [28]: np.allclose(out1,out2) # Verify results
Out[28]: True
In [29]: %timeit org_app(rotation_matrices,vectors)
10000 loops, best of 3: 196 µs per loop
In [30]: %timeit np.einsum('ijk,jk->ki',rotation_matrices,vectors)
100000 loops, best of 3: 5.12 µs per loop
这再次证明了为什么在NumPy中进行迭代基本上是不好的 !
您的轴处于异常状态。 首先,您需要将矩阵轴放在最后:
rotation_matrices = np.rollaxis(rotation_matrices, -1) # shape (50, 2, 2)
vectors = np.rollaxis(vectors, -1) # shape (50, 2)
这将使您使现有循环更具可读性:
for ind in np.arange(nb_of_vectors):
rotated_vector[ind] = np.dot(rotation_matrices[ind], vectors[ind])
但是,相反,您可以使用矩阵乘法运算符(或python <3.5中的np.matmul
)
rotated_vectors = (a @ vectors[...,None])[...,0]
# rotated_vectors = np.matmul(a, vectors[...,None])[...,0]
[...,None]
将向量数组(形状(n,)
转换为列矩阵(形状(n, 1)
),尾随[...,0]
将列矩阵转换回向量
这是一个明确的公式版本
result = np.array([vectors[0,:]*rotation_matrices[0,0,:] +
vectors[1,:]*rotation_matrices[0,1,:],
vectors[0,:]*rotation_matrices[1,0,:] +
vectors[1,:]*rotation_matrices[1,1,:]]).transpose()
多(14倍),比比你原来的代码,但速度较慢(2.6倍),更快的einsum
我的机器上
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.