如果我想采样截断的整数幂律,我可以在Python中使用什么函数?
即,给定两个参数a
和m
,在x
范围内生成一个随机整数[1,m)
,其范围遵循与1/x^a
成比例的分布。
我一直在寻找numpy.random
,但我还没有找到这种发行方式。
答案 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()
答案 1 :(得分:3)
我不使用Python,因此我会尝试在算法上描述解决方案,而不是冒险语法错误。这是一种强力离散反演。它应该很容易翻译成Python。我假设数组的索引为0。
设定:
生成大小为cdf
的数组m
,其中cdf[0] = 1
为第一个条目,其余条目为cdf[i] = cdf[i-1] + 1/(i+1)**a
。
通过将cdf[m-1]
分成每个条目来缩放所有条目 - 现在它们实际上是CDF值。
用法:
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的样本