我有一个点数组的列表,当我迭代它时,我想做就地矩阵乘法,也就是说,我希望结果存储在同一个矩阵中。
该守则实质上是:
for p in p_list:
# R is a 3x3 matrix
p[:,:] = np.matmul(R,p)这段代码没有显示错误,但是结果是不正确的,就好像乘法是在数组中执行的,并且被计算出来的一样,所以它创建了一个错误的输出矩阵。移除:,给出一个正确的乘法。
1)为什么会发生这种情况? 2)我使用的主要原因是::确保结果存储在列表p_list中。是否有正确的方法来做到这一点(不使用中间变量)?
发布于 2018-08-13 23:00:23
方法1:
如果我正确理解,您可以使用enumerate来遍历p_list的索引和值,并将matmul的结果分配给给定的索引。
例如,如果您的数据如下所示:
>>> R
array([[0.00169934, 0.66346914, 0.07109019],
[0.28354322, 0.45933175, 0.55396787],
[0.22061139, 0.18207232, 0.51669746]])
>>> p_list
array([[1., 2., 3.],
[4., 5., 6.]])然后你就可以:
for i,p in enumerate(p_list):
# R is a 3x3 matrix
p_list[i] = np.matmul(R,p)以及由此产生的p_list
>>> p_list
array([[1.54190819, 2.86411033, 2.13484839],
[3.7506842 , 6.75463886, 4.89299187]])基于@domochevski的评论编辑,这个方法可以更容易地通过列表理解来完成:
np.array([np.matmul(R,p) for p in p_list])方法2:
或者,您可以使用np.apply_along_axis,并应用一个自定义函数,该函数将matmul(R,x)返回到每一行:
def my_matmul(x):
return np.matmul(R,x)
p_list = np.apply_along_axis(my_matmul, 1, p_list)它返回相同的内容:
>>> p_list
array([[1.54190819, 2.86411033, 2.13484839],
[3.7506842 , 6.75463886, 4.89299187]])发布于 2020-03-26 16:30:52
matmul接受out参数
如果p_list是一个ndarray,具有N, 3形状,那么您可以在一个matmul中实现整个乘法。
np.matmul(p_list, R.T, out=p_list)发布于 2018-08-14 02:40:42
用@sacul的例子:
In [59]: R.shape
Out[59]: (3, 3)
In [60]: p_list.shape
Out[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_list
Out[64]:
array([[1.54190819, 2.86411033, 2.13484841],
[3.7506842 , 6.75463885, 4.89299192]])我确信它使用的是中间缓冲区,但是应该比逐行迭代更快。使用out比简单地让它返回一个新数组要慢一些。
通过调整维度,matmul可以在一个调用中执行整个calc (关键是将R的最后一个dim与p_list (修改)的第二个到最后一个dim对起来)。
In [84]: (R@p_list[:,:,None])[:,:,0]
Out[84]:
array([[1.54190819, 2.86411033, 2.13484841],
[3.7506842 , 6.75463885, 4.89299192]])https://stackoverflow.com/questions/51831561
复制相似问题