产生幂律分布的随机数生成器?
Posted
技术标签:
【中文标题】产生幂律分布的随机数生成器?【英文标题】:Random number generator that produces a power-law distribution? 【发布时间】:2010-10-29 10:59:21 【问题描述】:我正在为 C++ 命令行 Linux 应用程序编写一些测试。我想生成一堆具有幂律/长尾分布的整数。意思是,我经常得到一些数字,但其中大多数相对不常见。
理想情况下,我可以将一些魔术方程式与 rand() 或 stdlib 随机函数之一一起使用。如果没有,一个易于使用的 C/C++ 块会很棒。
谢谢!
【问题讨论】:
【参考方案1】:page at Wolfram MathWorld 讨论了如何从均匀分布(这是大多数随机数生成器提供的)中获得幂律分布。
简短答案(以上链接的推导):
x = [(x1^(n+1) - x0^(n+1))*y + x0^(n+1)]^(1/(n+1))
其中y是统一变量,n是分布幂,x0和x1定义范围的分布,x 是你的幂律分布变量。
【讨论】:
额外的小细节:y 是 [0,1] 范围内的统一变量。 dmckee 的回答提供了理解 Wolfram 文章中推导所必需的缺失上下文。【参考方案2】:如果您知道所需的分布(称为概率分布函数 (PDF))并对其进行了适当的归一化,则可以对其进行积分以获得累积分布函数 (CDF),然后反转 CDF(如果可能)以获得您需要从统一的[0,1]
分发到您想要的转换。
所以你首先定义你想要的分布。
P = F(x)
(for x in [0,1]) 然后积分得到
C(y) = \int_0^y F(x) dx
如果这可以反转,你会得到
y = F^-1(C)
所以调用rand()
并将结果作为C
插入最后一行并使用y。
这个结果称为抽样基本定理。由于规范化要求和分析反转函数的需要,这很麻烦。
或者,您可以使用拒绝技术:在所需范围内统一抛出一个数字,然后抛出另一个数字并在您第一次抛出指定的位置与 PDF 进行比较。如果第二次抛出超过 PDF,则拒绝。对于具有很多低概率区域的 PDF 往往效率低下,比如那些长尾的...
一种中间方法涉及通过蛮力反转 CDF:将 CDF 存储为查找表,然后进行反向查找以获得结果。
这里真正令人讨厌的是简单的x^-n
分布在[0,1]
范围内是不可归一化的,因此您不能使用采样定理。改用 (x+1)^-n...
【讨论】:
【参考方案3】:我只是想进行一个实际的模拟,作为对(正确)接受的答案的补充。尽管在 R 中,代码是如此简单,以至于是(伪)伪代码。
接受答案中的Wolfram MathWorld formula 与其他可能更常见的方程之间的一个微小差异是 幂律指数 n
(通常表示为 alpha)确实不带有明确的负号。所以选择的 alpha 值必须是负数,通常在 2 到 3 之间。
x0
和x1
代表分布的下限和上限。
原来是这样:
set.seed(0)
x1 = 5 # Maximum value
x0 = 0.1 # It can't be zero; otherwise X^0^(neg) is 1/0.
alpha = -2.5 # It has to be negative.
y = runif(1e7) # Number of samples
x = ((x1^(alpha+1) - x0^(alpha+1))*y + x0^(alpha+1))^(1/(alpha+1))
plot(density(x), ylab="log density x", col=2)
或以对数刻度绘制:
plot(density(x), log="xy", ylab="log density x", col=2)
以下是数据摘要:
> summary(x)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.1000 0.1208 0.1584 0.2590 0.2511 4.9388
【讨论】:
不知道为什么你说指数必须在 -2 和 -3 之间(我认为自然界中观察到的许多幂律分布的 alpha 介于 1 和 2 之间)但是谢谢你的行R 代码! @SimonC。我是从page 4 left column of this paper 那里得到的。符号将始终为负(当公式带有减号时,alpha 表示为正值)。 是的,对不起,我的错,我完全同意负号,我只是问为什么将 alpha 限制为 [-2,-3]。【参考方案4】:我无法评论生成幂律分布所需的数学(其他帖子有建议),但我建议您熟悉<random>
中的 TR1 C++ 标准库随机数工具。这些提供了比std::rand
和std::srand
更多的功能。新系统为生成器、引擎和发行版指定了一个模块化 API,并提供了一堆预设。
包含的分发预设是:
uniform_int
bernoulli_distribution
geometric_distribution
poisson_distribution
binomial_distribution
uniform_real
exponential_distribution
normal_distribution
gamma_distribution
当您定义幂律分布时,您应该能够将其插入现有的发电机和引擎。 Pete Becker 所著的The C++ Standard Library Extensions一书有一个关于<random>
的精彩章节。
Here is an article 关于如何创建其他分布(包括 Cauchy、卡方、Student t 和 Snedecor F 的示例)
【讨论】:
以上是关于产生幂律分布的随机数生成器?的主要内容,如果未能解决你的问题,请参考以下文章