Python - 加快查找大于阈值的集合的百分位数

Python - speed up finding percentile of set which is greater than threshold

我需要找出一组数字中哪个百分位数超过了阈值。有没有办法加快速度?我的实现对于预期的应用程序来说太慢了。万一这改变了什么,我 运行 我的程序使用 mpirun -np 100 python program.py。我不能使用 numba,因为该程序的其余部分使用 try/except 语句。

import numpy as np
my_vals = []
threshold_val = 0.065
for i in range(60000):
    my_vals.append(np.random.normal(0.05, 0.02))

for i in np.arange(0,100,0.001):
    if np.percentile(my_vals,i) > threshold_val:
        perc = 1*i
        break
else: perc = 100

由于高斯(正态)分布产生钟形曲线,您应该能够计算出最优概率最高的百分位数,然后编写代码先检查那里,然后使用修改后的二进制搜索找到最佳的最低阈值。

例如,如果您确定您的参数最有可能支持例如17.951(这只是一个例子,我实际上并没有费心计算它),然后从该点附近开始而不是从 0 开始。将其视为二进制搜索 - 从 0 开始你的下限,从 100.0 开始你的上限,并且设置将列表一分为二的点作为分布的最佳百分位数。

如果您当前的上限超过 threshold_val,请平分下半部分以找到匹配的最低此类值;如果它没有超过阈值,则将上半部分一分为二,等等。所以,例如在 0.000 到 100.000 的范围内,如果您从 17.951 开始并发现它不高于阈值,请调整到 17.952 到 100.000 的范围并尝试 58.976(中间值)。一旦找到高于阈值的值,就将该值用作上限(因为它不是最佳答案)。继续此过程,直到下限和上限相差 0.001,这将为您提供最佳答案。平均而言,您应该 运行 进行大约 17 次测试,而不是 100,000 次。

如果您的正态分布发生变化,您还可以自动计算最优值,因为该分布会产生钟形曲线,并且您将根据参数了解该钟形曲线的统计数据无论如何。

您的解决方案只需要找到百分位高于阈值的最低值,因此这种方法应该最大限度地减少您需要检查的样本数量。

还有一个提示:np.percentile 必须在您的代码中对 my_vals 进行 100,000 次排序;我不知道预先排序的列表是否有帮助,但它可能值得检查(您可能必须测试几个可能的排序参数,因为它似乎没有记录它排序的方向)。

您可以通过对值进行排序并搜索第一个超过阈值的值来直接找到解决方案。百分位数是该元素之前的数组值的分数:

import numpy as np
my_vals = []
threshold_val = 0.065
for i in range(60000):
    my_vals.append(np.random.normal(0.05, 0.02))

from bisect import bisect_right

print bisect_right(sorted(my_vals),threshold_val)/float(len(my_vals))*100