基于np.random.rrandom的结果来制定if/elif语句的更有效方法



我正在尝试加速我的代码,它有一个如下形式的长if/elif语句:

random = np.random.random()
tot = a + b + c + d
if random < a/tot:
var1 += 1
elif a/tot < random < (a+b)/tot:
var1 -= 1
elif (a+b)/tot < random < (a+b+c)/tot:
var2 += 1
elif (a+b+c)/tot < random < 1:
var2 -= 1

我试着用字典找到一种方法来实现这一点,但我不知道如何索引它。代码按原样运行,但我正在努力加快这段代码的速度,这段代码占用了运行时的大部分时间。还有别的办法吗?

您可以使用平分来确定;bin";你的随机数下降:

bins = np.cumsum([0., a, b, c, d])
bins /= bins.sum()
updates_var1 = [1, -1, 0, 0]
updates_var2 = [0, 0, 1, -1]
index = bisect.bisect(bins, random) - 1
var1 += updates_var1[index]
var2 += updates_var2[index]

该解决方案可以通过使用np.searchsorted而不是bisect.bisect来矢量化。

假设每个项目的可能性相等,那么这可能是值得做的:

a_b = a+b
a_b_c = a_b+c
random = np.random.random() * (a_b_c+d)
if a_b < random:
var1 += 1 if a < random else -1
else:
var2 += 1 if a_b_c < random else -1

这将导致每次迭代执行两个if语句,而您的版本只需要一个a语句,而需要四个d语句

再说一遍,如果在这里花了大量的时间,那么你可能值得做其他事情。例如,将事物矢量化,或者依赖于一些分析统计结果,这样你就不必绘制那么多样本

这可能是最有效的删除分区:

tot = a + b + c + d
random = np.random.random() * tot
if random < a:
var1 += 1
elif random < a+b:
var1 -= 1
elif random < a+b+c:
var2 += 1
else:
var2 -= 1

我在这里看到的仅有的几件事是:

  1. 你只需要第二个条件(第一个条件已经在前面的if中检查过了,所以你知道它的倒数是真的(

  2. 如果if-else链在一个循环内,而a,b,c,d在这个循环内是固定的,那么(在进入循环之前(提前计算和和和除法

  3. 通过else更改最后一个elif

导致

# if a,b,c,d,tot are FIXED inside some external loop
# you should calculate tot,P1,P2,P3 OUTSIDE the loop
tot = a + b + c + d
P1=a/tot
P2=(a+b)/tot
P3=(a+b+c)/tot
# considering a,b,c,d,tot are fixed inside the loop
# the loop should start here
random = np.random.random()
if random < P1:
var1 += 1
elif random < P2:
var1 -= 1
elif random < P3:
var2 += 1
else:
var2 -= 1

你可以尝试的另一件事是将if-else链放入函数中,并使用numba、pythran或cython为其生成编译代码

最新更新