Python `行.dot(M).dot(row.T)表示x`as native numpy中的行?
我有一个向量和矩阵计算,其工作原理如下:Python `行.dot(M).dot(row.T)表示x`as native numpy中的行?,python,numpy,Python,Numpy,我有一个向量和矩阵计算,其工作原理如下: import numpy as np r = 1 c = 13 x = np.ones((r, c)) # rxc M = np.ones((c, c)) # cxc square Z = x.dot(M).dot(x.T) # (rxr) = (rxc).(cxc).(cxr) print Z.shape def mul(a,b): return a*b assert reduce(mul,Z.shape)==r # Z should h
import numpy as np
r = 1
c = 13
x = np.ones((r, c)) # rxc
M = np.ones((c, c)) # cxc square
Z = x.dot(M).dot(x.T) # (rxr) = (rxc).(cxc).(cxr)
print Z.shape
def mul(a,b): return a*b
assert reduce(mul,Z.shape)==r # Z should have one value for each row
对于有许多行的x,我想对x的行执行相同的转换,如下所示:
r = 99
x = np.ones((r, c)) # rxc
... as above ...
这失败了,因为Z(感觉上)最终变成了(99x99)。但我想要的是一个(99x1)或(1x99),可以计算如下:
Z2 = np.array([row.dot(M).dot(row.T) for row in x])
有没有办法在numpy中更直接地计算Z2,而不是使用python迭代?这个乘法技巧可以得到您想要的结果。基本上,我们使用乘法和求和作为逐行的点积,而不是使用
dot
(x.dot(M) * x).sum(axis=1)
我在1000 x 10000阵列上进行了测试,以查看此技巧的工作速度是否更快
r = 1000
c = 10000
x = np.ones((r, c)) # rxc
M = np.ones((c, c)) # cxc square
%timeit (x.dot(M) * x).sum(axis=1)
>> 1 loop, best of 3: 1.59 s per loop
%timeit np.array([row.dot(M).dot(row.T) for row in x])
>> 1 loop, best of 3: 41.9 s per loop
这个乘法技巧可以得到你想要的结果。基本上,我们使用乘法和求和作为逐行的点积,而不是使用
dot
(x.dot(M) * x).sum(axis=1)
我在1000 x 10000阵列上进行了测试,以查看此技巧的工作速度是否更快
r = 1000
c = 10000
x = np.ones((r, c)) # rxc
M = np.ones((c, c)) # cxc square
%timeit (x.dot(M) * x).sum(axis=1)
>> 1 loop, best of 3: 1.59 s per loop
%timeit np.array([row.dot(M).dot(row.T) for row in x])
>> 1 loop, best of 3: 41.9 s per loop
你对
Z2
的定义就是Z
的对角线,你可以通过np.对角线(Z)
:
或者你也可以用很酷的方式,使用np.einsum
:
np.einsum('ij,jk,ki -> i',x,M,x.T)
请记住,np.einsum
需要解析字符串,但它会做一些其他事情,使其效率低于普通矩阵乘法,因此,如果您特别关注性能,则此方法速度较慢
另一方面,3个矩阵的乘积与
Z2
不同,因为Z2
不计算(x的第一行)。(M)。(x.t的第二列)
等条目。;这些是Z
的非对角线条目,您对Z2
的定义就是Z
的对角线,您可以使用np.diagonal(Z)
:
或者你也可以用很酷的方式,使用np.einsum
:
np.einsum('ij,jk,ki -> i',x,M,x.T)
请记住,np.einsum
需要解析字符串,但它会做一些其他事情,使其效率低于普通矩阵乘法,因此,如果您特别关注性能,则此方法速度较慢
另一方面,3个矩阵的乘积与
Z2
不同,因为Z2
不计算(x的第一行)。(M)。(x.t的第二列)
等条目。;这些是Z
np的非对角线条目。einsum
应该比np快。对角线
只计算相关项。我认为np.einsum('ij,jk,ik->I',x,M,x)
可能会更快一点,因为它不需要操纵x.t
的指针,我用更大的数组尝试过,而np.einsum
实际上要慢得多,这不是因为解析。我不知道确切的原因,但这很可能是因为操作不像通常的矩阵乘法那样简单和直接,在矩阵乘法中,NumPy使用了一个非常有效的实现。事实上,titipata的解决方案是只做(x.dot(M)*x).sum(axis=1)
,速度更快,而且可能是最快的。np.einsum
应该比np.diagonal
快,因为它只计算相关的项。我认为np.einsum('ij,jk,ik->I',x,M,x)
可能会更快一点,因为它不需要操纵x.t
的指针,我用更大的数组尝试过,而np.einsum
实际上要慢得多,这不是因为解析。我不知道确切的原因,但这很可能是因为操作不像通常的矩阵乘法那样简单和直接,在矩阵乘法中,NumPy使用了一个非常有效的实现。事实上,titipata的解决方案是只做(x.dot(M)*x.sum(axis=1)
,速度更快,可能也更快。