计算 - numpy python bug

时间:2011-07-20 16:09:23

标签: python matlab numpy bug-tracking

我正在使用NumPy通过大盒子和小盒子之间的光圈来寻找Y截距。我在大盒子里有超过100,000颗颗粒,在小盒子里有大约1000颗颗粒。这需要花费大量时间。所有self.YD,self.XD都是非常大的数组,我正在成倍增加。

PS:ind是需要乘以的值的索引。我的代码中该行之前有一个非零条件。

我是如何以更简单的方式进行此计算的?

YD_zero = self.oldYD[ind] - ((self.oldYD[ind]-self.YD[ind]) * self.oldXD[ind])/(self.oldXD[ind]-self.XD[ind])

谢谢!

更新

使用乘法,除法,减法和Numpy的所有东西。让它更快? 或者,如果我分开计算。例如。

首先执行此操作:

    YD_zero = self.oldYD[ind] - ((self.oldYD[ind]-self.YD[ind])*self.oldXD[ind])

然后下一行是:

    YD_zero /= (self.oldXD[ind]-self.XD[ind])

有什么建议吗?!

更新2

我一直试图解决这个问题,但现在已经有了很多进步。我担心的是分母:

    self.oldXL[ind]-self.XL[ind] == 0

我得到了一些奇怪的结果。

另一件事是非零功能。我已经测试了一段时间了。任何人都可以告诉我它与Matlab中的find几乎相同

3 个答案:

答案 0 :(得分:3)

也许我有错误的结局,但在Numpy你可以进行矢量化计算。删除封闭的while循环,然后运行此...

YD_zero = self.oldYD - ((self.oldYD - self.YD) * self.oldXD) / (self.oldXD - self.XD)

应该快得多。

更新:使用Newton-Raphson方法进行迭代根查找...

unconverged_mask = np.abs(f(y_vals)) > CONVERGENCE_VALUE:
while np.any(unconverged_mask):
    y_vals[unconverged_mask] = y_vals[unconverged_mask] - f(y_vals[unconverged_mask]) / f_prime(y_vals[unconverged_mask])
    unconverged_mask = np.abs(f(y_vals)) > CONVERGENCE_VALUE:

此代码仅是说明性的,但它显示了如何使用向量化代码将迭代过程应用于任何函数f,您可以找到f_prime的导数。 unconverged_mask表示当前迭代的结果仅适用于那些尚未收敛的值。

请注意,在这种情况下,不需要迭代,Newton-Raphson会在第一次迭代中给出正确的答案,因为我们正在处理直线。你所拥有的是一个精确的解决方案。

第二次更新

好的,所以你没有使用Newton-Raphson。要一次性计算YD_zero(y截距),您可以使用

YD_zero = YD + (XD - X0) * dYdX

其中dYdX是渐变,在您的情况下似乎是

dYdX = (YD - oldYD) / (XD - oldXD)

我假设XDYD是粒子的当前x,y值,oldXDoldYD是粒子的先前x,y值, X0是光圈的x值。

仍然不完全清楚为什么你必须遍历所有粒子,Numpy可以同时对所有粒子进行计算。

答案 1 :(得分:2)

由于所有计算都是按元素完成的,因此在Cython中重写表达式应该很容易。这将避免在执行oldYD-YD等时创建的所有非常大的临时数组。

另一种可能性是numexpr

答案 2 :(得分:0)

我肯定会去numexpr。我不确定numexpr可以处理索引,但我敢打赌以下(或类似的东西)可以工作:

import numexpr as ne

yold = self.oldYD[ind]
y = self.YD[ind]
xold = self.oldXD[ind]
x = self.XD[ind]
YD_zero = ne.evaluate("yold - ((yold - y) * xold)/(xold - x)")