到位矩阵乘法numpy

我有一个点数组的列表,当我遍历它时,我想进行就地矩阵乘法,即我想将结果存储在同一矩阵中。

该代码本质上是:

for p in p_list:    
    # R is a 3x3 matrix
    p[:,:] = np.matmul(R,p)

此代码未显示错误,但结果不正确,就好像在数组中执行乘法并按计算结果进行替换一样,因此它创建了错误的输出矩阵。删除[:,:]可得出正确的乘法。

1)为什么会这样呢?2)我使用[:,:]的主要原因是确保将结果存储回列表p_list中。有正确的方法(不使用中间变量)吗?


元芳怎么了
浏览 164回答 3
3回答

缥缈止盈

matmul 接受一个out参数如果p_list是ndarray带形状的N, 3,那么您可以一次完成整个乘法matmul:np.matmul(p_list, R.T, out=p_list)

红糖糍粑

以@sacul的示例为例:In [59]: R.shapeOut[59]: (3, 3)In [60]: p_list.shapeOut[60]: (2, 3)In [58]: np.array([np.matmul(R,p) for p in p_list])Out[58]: array([[1.54190819, 2.86411033, 2.13484841],       [3.7506842 , 6.75463885, 4.89299192]])einsum 生成相同的(新的)数组而没有外部循环:In [61]: np.einsum('ij,kj->ki',R,p_list)Out[61]: array([[1.54190819, 2.86411033, 2.13484841],       [3.7506842 , 6.75463885, 4.89299192]])和一样ufunc,它接受一个out参数:In [63]: np.einsum('ij,kj->ki',R,p_list, out=p_list)Out[63]: array([[1.54190819, 2.86411033, 2.13484841],       [3.7506842 , 6.75463885, 4.89299192]])In [64]: p_listOut[64]: array([[1.54190819, 2.86411033, 2.13484841],       [3.7506842 , 6.75463885, 4.89299192]])我确定它使用了一个中间缓冲区,但是应该比逐行迭代要快。与使用out相比,让它返回一个新数组要慢一些。进行尺寸调整后,matmul可以在一个调用中执行整个计算(关键是将的最后一个暗角R与第二个和最后一个暗角配对p_list(已修改))。In [84]: (R@p_list[:,:,None])[:,:,0]Out[84]: array([[1.54190819, 2.86411033, 2.13484841],       [3.7506842 , 6.75463885, 4.89299192]])
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python