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)
,速度更快,可能也更快。