如何对依赖于先前行的计算进行矢量化/优化



我正在研究运行时非常重要并且我们处理的数据很大的问题,但基本上问题归结为优化x系列的求解,其中x1是已知的,x=前一行的ax+b。例如,启动状态:

a b x
1 2 3
3 1
2 2
4 8
1 9

最终状态看起来是这样的:

a b x
1 2 3
3 1 5
2 2 16
4 8 72
1 9 81

因为3*1+2=5,5*3+1=16等

我试着计算它的数学结果是:

b0 = x1
xi = sum(n=0 to i-1)(bn*product(m=n+1 to i-1)(am)

例如,对于第三排,你最终会得到:

x3 = a1*a2*b0 + b1*a2 + b2 = 3*1*3 + 2*3 + 1 = 9 + 6 + 1 = 16

但在计算上,这似乎比通过在行上循环来计算每个x更糟糕,比如

for i in range(2,len(df)):
df.x[i] = df.x[i-1]*df.a[i-1]+df.b[i-1]

有没有一种更简单的方法来解决我所缺少的问题,或者我只是在处理一个计算成本高昂的操作,我将不得不承担迭代的成本?如果a术语不存在,那么bn部分可以通过cumsum来处理,比如:

df['b_cumsum'] = x1+cumsum(df.b)

但当我试图包含一个术语时,我遇到了一堵墙,尤其是因为我们最终需要很多不同的产品集,即使在每个总和术语中也是如此。

谢谢。

您可以首先使用匹配的b'=b/cumprod(a(计算重新缩放的x

这可以通过矢量化操作来完成,从x'到x:的反向变换也是如此

ab = np.array([[1, 2],
[3, 1],
[2, 2],
[4, 8],
[1, 9]])
scale = ab.T[0].cumprod()
xp = 3+(ab.T[1]/scale).cumsum()
x = xp*scale
x
array([  5.,  16.,  34., 144., 153.])

当我遇到无法向量化但需要高效的函数时,我使用numba。它是一个即时编译(JIT(模块。大多数时候,这可能比本地熊猫的方法更快:

from numba import njit
@njit
def calculation(arr):
result = np.empty(arr.shape[0])
for idx, row in enumerate(arr):
if idx == 0:
result[idx] = row[2]
else:
row = arr[idx-1]
result[idx] = result[idx-1] * row[0] + row[1]

return result
df['x'] = calculation(df.to_numpy())
print(df)
a  b      x
0  1  2    3.0
1  3  1    5.0
2  2  2   16.0
3  4  8   34.0
4  1  9  144.0

注意:何时计时。不要在第一次运行时计时,因为它还没有编译。先跑一次,然后在第二次跑时计时。

最新更新