2013-07-19 37 views
4

有没有一种方法可以加速双循环,从前一次迭代更新其值?在Python中加速双循环

在代码:

def calc(N, m): 
    x = 1.0 
    y = 2.0 
    container = np.zeros((N, 2)) 
    for i in range(N): 
     for j in range(m): 
     x=np.random.gamma(3,1.0/(y*y+4)) 
     y=np.random.normal(1.0/(x+1),1.0/sqrt(x+1)) 
     container[i, 0] = x 
     container[i, 1] = y 
    return container 

calc(10, 5) 

正如你可以看到,内循环,而外环且具有x每次一个不同的值开始更新变量x和y。我不认为这是矢量化的,但也许还有其他可能的改进。

谢谢!

+0

“第二个循环更新变量x和y,而第一个循环每次都以不同的x值开始” - 我不确定你这意味着。特别是,我不知道你的意思是“每次以不同的x值开始”,而“第一”或“第二”循环与“内部”或“外部”相比相当不清楚。我不完全确定哪个是哪个。 – user2357112

+0

对不起,我想不出比用'xrange'替换'range'更好。也许你应该在这个问题上提出一个奖励来吸引一位'numpy'专家 – inspectorG4dget

+0

抱歉。你是对的。我会改变第一个或第二个循环的事情。通过_starts每次的x值不同,我的意思是外层循环的第一次迭代以x = 1.0开始。但是,x在内部循环中被修改。因此,在外循环的第二次迭代中,x是另一个值。 –

回答

1

我不认为它会加起来任何重要的速度,但你可以保存,如果你将所有生成的γ和通常在一次分布的随机值的一些函数调用。

伽玛函数都有一个scaling property,所以,如果从伽马绘制值x(K,1)分配,然后c*x将从伽马(K,C)分布中抽取一个值。同样,对于正态分布,您可以取一个从正态(0,1)分布中抽取的值并将其转换为从正常(m,s)分布中抽取的值,该分布正在执行x*s + m。所以,你可以重写你的函数如下:

def calc(N, m): 
    x = 1.0 
    y = 2.0 
    container = np.zeros((N, 2)) 
    nm = N*m 
    gamma_vals = np.random.gamma(3, 1, size=(nm,)) 
    norm_vals = np.random.normal(0, 1, size=(nm,)) 
    for i in xrange(N): 
     for j in xrange(m): 
      ij = i*j 
      x = gamma_vals[ij]/(y*y+4) 
      y = norm_vals[ij]/np.sqrt(x+1) + 1/(x+1) 
     container[i, 0] = x 
     container[i, 1] = y 
    return container 

如果您分布的实际参数有一个更简单的表达,你可能实际上是能够使用的np.cumprod或像一些精心制作的形式,就饶了自己的循环。我无法想出这样做的方法......

+0

不幸的是,这比在内部循环中使用np.random.gamma和np.random.normal的方法慢2倍。也许有一个错误,因为它没有给出相同的结果。 –

+0

您正在绘制随机数字,因此结果不同也不足为奇。即使你接种了随机数发生器,你也是以不同的顺序使用它们,所以再次非常正常。至于性能,如果允许移除循环,这将是一个巧妙的使用方法,这对于您的问题来说似乎不可行。 – Jaime

+0

1+。你是对的。谢谢。你认为没有办法进一步优化它吗? –

0

这是行不通的吗?

for i in xrange(N): 
    # xrange is an iterator, range makes a new list. 
    # You save linear space and `malloc`ing time by doing this 

    x += m*y # a simple algebra hack. Compute this line of the loop just once instead of `m` times 
    y -= m*x 
    y *= -1 # another simple algebra hack. Compute this line of the loop just once instead of `m` times 
    container[i,0] = x 
    container[i,1] = y 
return container 
+0

谢谢你的回答。 xrange是一个不错的主意。然而,代数部分并不适用于我试图优化的真实循环(它涉及伽马函数) –

+0

@RobertSmith:对不起,我现在想不到很多 – inspectorG4dget

+0

@RobertSmith:你可以发布真实的代码? – user2357112