在Python中采用截断的整数幂律?

时间:2014-07-04 18:21:14

标签: python numpy random distribution

如果我想采样截断的整数幂律,我可以在Python中使用什么函数?

即,给定两个参数am,在x范围内生成一个随机整数[1,m),其范围遵循与1/x^a成比例的分布。

我一直在寻找numpy.random,但我还没有找到这种发行方式。

3 个答案:

答案 0 :(得分:3)

AFAIK,NumPy和Scipy都没有为您定义此发行版。但是,使用SciPy可以使用scipy.rv_discrete

轻松定义自己的离散分布函数
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt

def truncated_power_law(a, m):
    x = np.arange(1, m+1, dtype='float')
    pmf = 1/x**a
    pmf /= pmf.sum()
    return stats.rv_discrete(values=(range(1, m+1), pmf))

a, m = 2, 10
d = truncated_power_law(a=a, m=m)

N = 10**4
sample = d.rvs(size=N)

plt.hist(sample, bins=np.arange(m)+0.5)
plt.show()

enter image description here

答案 1 :(得分:3)

我不使用Python,因此我会尝试在算法上描述解决方案,而不是冒险语法错误。这是一种强力离散反演。它应该很容易翻译成Python。我假设数组的索引为0。

设定:

  1. 生成大小为cdf的数组m,其中cdf[0] = 1为第一个条目,其余条目为cdf[i] = cdf[i-1] + 1/(i+1)**a

  2. 通过将cdf[m-1]分成每个条目来缩放所有条目 - 现在它们实际上是CDF值。

  3. 用法:

    • 通过生成Uniform(0,1)和生成随机值 搜索cdf[],直到找到大于您的条目为止 制服。将索引+ 1作为x - 值返回。

    根据需要重复多个x - 值。

    例如,对于a,m = 2,10,我直接将概率计算为:

    [0.6452579827864142, 0.16131449569660355, 0.07169533142071269, 0.04032862392415089, 0.02581031931145657, 0.017923832855178172, 0.013168530260947229, 0.010082155981037722, 0.007966147935634743, 0.006452579827864143]
    

    和CDF是:

    [0.6452579827864142, 0.8065724784830177, 0.8782678099037304, 0.9185964338278814, 0.944406753139338, 0.9623305859945162, 0.9754991162554634, 0.985581272236501, 0.9935474201721358, 1.0]
    

    生成时,如果我得到0.90的统一结果,我会返回x=4因为0.918 ...是第一个大于我的制服的CDF条目。

    如果你担心速度,你可以建立一个别名表,但是几何衰减,通过阵列提前终止线性搜索的可能性非常高。例如,在给定的示例中,您将在第一眼看到几乎2/3的时间终止。

答案 2 :(得分:0)

使用numpy.random.zipf并拒绝任何大于或等于m的样本