2013-09-23 29 views
6

我有以下一段代码正在执行我想要的操作(它是克里金方法的一部分)。但问题是它太慢了,我想知道是否有任何选项可以将for循环压缩到numpy?如果我推出numpy.sum,并在那里使用axis参数,它会加快一点,但显然这不是瓶颈。如何我可以倒推for循环的任何想法,numpy的加快步伐,或其他方式来加快步伐?)如何将for循环推向numpy

# n = 2116 
print GRZVV.shape # (16309, 2116) 
print GinvVV.shape # (2117, 2117) 
VVg = numpy.empty((GRZVV.shape[0])) 

for k in xrange(GRZVV.shape[0]): 
    GRVV = numpy.empty((n+1, 1)) 
    GRVV[n, 0] = 1 
    GRVV[:n, 0] = GRZVV[k, :] 
    EVV = numpy.array(GinvVV * GRVV) # GinvVV is numpy.matrix 
    VVg[k] = numpy.sum(EVV[:n, 0] * VV) 

我张贴的ndarrays n矩阵的尺寸以清除一些东西出来

编辑:VV的形状是2116

+1

什么形状是' VV'? –

+0

如果'VV.shape ==(16309,)',你怎么能通过形状为'(n,)'的'EVV [:n,0]'来生成它? – askewchan

+0

也许你的循环的最后一行应该有'EVV [:n,0] * VV [k]',这似乎是@ Jaime的答案所假设的。 – askewchan

回答

5

你可以做的地方你的循环下在K(运行时〜3秒):

tmp = np.concatenate((GRZVV, np.ones((16309,1),dtype=np.double)), axis=1) 
EVV1 = np.dot(GinvVV, tmp.T) 
#Changed line below based on *askewchan's* recommendation 
VVg1 = np.sum(np.multiply(EVV1[:n,:],VV[:,np.newaxis]), axis=0) 
+1

这给出了与@ usethedeathstar的代码相同的结果,并且在我的机器上运行速度提高了15倍。 – askewchan

+1

不需要拼贴,因为'np.multiply'广播。将其更改为:'VVg1 = np.sum(np.multiply(EVV1 [:n,:],VV [:,np.newaxis]),axis = 0)'用于小加速。 – askewchan

+0

+1好电话....我编辑了上面的行...谢谢 –

3

你基本上是采取GRZVV的每一行,在末尾附加1,将它乘以GinvVV,然后将向量中的所有元素相加。

VVg = np.sum(np.dot(GinvVV[:, :-1], GRZVV.T), axis=-1) * VV 

甚至:如果你不这样做的“追加1”的东西,你可以不循环的做这一切

VVg = np.einsum('ij,kj->k', GinvVV[:, :-1], GRZVV) * VV 

我们如何处理这些额外的1?那么,来自矩阵乘法的结果向量将会增加GinvVV[:, -1]中的相应值,并且当您将它们全部相加时,值将会增加np.sum(GinvVV[:, -1])。因此,我们可以简单地计算这一次,并将其添加到在返回向量中的所有项目:

VVg = (np.einsum('ij,kj->k', GinvVV[:-1, :-1], GRZVV) + np.sum(GinvVV[:-1, -1])) * VV 

上面的代码工作,如果VV是一个标量。如果是形状(n,)的数组,然后下面的工作:

GinvVV = np.asarray(GinvVV) 
VVgbis = (np.einsum('ij,kj->k', GinvVV[:-1, :-1]*VV[:, None], GRZVV) + 
      np.dot(GinvVV[:-1, -1], VV)) 
+1

With @ usethedeathstar的编辑,'VV.shape'现在是2116,所以不会在您的解决方案中广播(因为'Wg.shape'是16309 ) – askewchan

+0

认为这是一个标量。使用完整的数组,不像Joel的答案那样将数组折叠到最后,对于大数组来说,要比上面的要快得多。 – Jaime