基于np.random.random的结果更有效地表达if/elif语句?

nom7f22z  于 2021-07-13  发布在  Java
关注(0)|答案(4)|浏览(247)

我正在尝试加速我的代码,它有一个长的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

我试着想办法用字典来做这件事,但我想不出我该如何索引它。代码按原样工作,但是我正在尝试加速代码的这一部分,它占用了运行时的大量时间。还有别的办法吗?

jvidinwx

jvidinwx1#

您可以使用二分法来确定随机数落在哪个“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 .

ou6hu8tu

ou6hu8tu2#

我在这里看到的只有几件事:
您只需要第二个条件(第一个条件已经在前面的if中检查过了,所以您知道它的倒数是真的)
如果 if-else 链条在一个圈里,而且 a,b,c,d 在这个循环中是固定的,然后提前计算和和和除法(在进入循环之前)
更改最后一个 elifelse 导致

random = np.random.random()
tot = a + b + c + d
P1=a/tot
P2=(a+b)/tot
P3=(a+b+c)/tot

if random < P1:
   var1 += 1
elif random < P2:
   var1 -= 1
elif random < P3:
   var2 += 1
else:
   var2 -= 1

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

lskq00tm

lskq00tm3#

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

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 再说一次,如果你在这里花了大量的时间,那么你可能值得做些别的事情。e、 矢量化的东西,或依赖于一些分析统计结果,这样你就不必画那么多的样本

ryevplcw

ryevplcw4#

通过移除分区,这可能是最有效的:

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

相关问题