【问题标题】:Choosing n numbers with fixed sum选择 n 个总和固定的数字
【发布时间】:2011-08-03 02:48:29
【问题描述】:

在某些代码中,我想在[0,1) 中选择n 随机数,总和为1

我这样做是通过在[0,1) 中独立选择数字并通过将每个数字除以总和来标准化它们:

numbers = [random() for i in range(n)]
numbers = [n/sum(numbers) for n in numbers]

我的“问题”是,我得到的分布是相当倾斜的。选择一百万个数字而不是一个数字会超过1/2。经过一番努力,我计算出了 pdf,结果并不好。

这是我为 5 个变量得到的看起来很奇怪的 pdf:

您是否有一个好的算法来选择数字,从而产生更均匀或更简单的分布?

【问题讨论】:

标签: algorithm math random probability sample


【解决方案1】:

如果您正在寻找概率,您可能对 Dirichlet distribution 感兴趣,它用于生成总和为 1 的数量。还有一节介绍如何使用伽马分布生成它们here

【讨论】:

  • 你通常需要一些分布,而不是统一的从哪里来绘制你的数字。正如工作的回答所暗示的那样,您可以使用 alpha
  • 这篇文章有一个很好的“绘图”部分,我在其中添加了一些代码示例。我不确定参数是什么是否重要,只要它们相等?
【解决方案2】:

您正在寻找从 0 到 1 的距离。

从 0 到 1 中选择 n - 1 个数字,对它们进行排序并确定它们之间的距离。

这会将空间划分为 0 到 1,这应该会偶尔产生您没有得到的大结果。

即便如此,对于较大的 n 值,您通常可以预期您的最大值也会降低,只是没有您的方法那么快。

【讨论】:

  • 一个可爱的算法。你知道这可能导致什么分布吗?
  • 除了称它为“随机分区”之外,我不知道如何引用它。我一直从事物的分区方面来看待它,而不是从段长度的分布来看。
  • 我推导出了 cdf 1-(1-x)^n 和 pmf n(1-x)^(n-1)。与我的相比,分布接缝具有更高的小数概率(它没有接近 1/n 的峰值),因此它可能也有更多的大数。我还没有将它与 Dirichlet 分布进行比较。
  • 这是beta分布,其中最简单的情况是n个制服的最小元素的概率分布。
【解决方案3】:

另一种获取n 总和为1的随机数的方法:

import random


def create_norm_arr(n, remaining=1.0):
    random_numbers = []
    for _ in range(n - 1):
        r = random.random()  # get a random number in [0, 1)
        r = r * remaining
        remaining -= r
        random_numbers.append(r)
    random_numbers.append(remaining)
    return random_numbers

random_numbers = create_norm_arr(5)
print(random_numbers)
print(sum(random_numbers))

这使得更高的数字更有可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多