【问题标题】:Sampling real numbers with sum and minimum value constraints使用总和和最小值约束对实数进行采样
【发布时间】:2019-06-25 18:30:54
【问题描述】:

如何采样 N 个随机值以满足以下约束条件?

  1. N 个值加起来为 1.0
  2. 没有一个值小于 0.01(或其他一些阈值 T N)

以下过程是我的第一次尝试。

def proportions(N):
    proportions = list()
    for value in sorted(numpy.random.random(N - 1) * 0.98 + 0.01):
        prop = value - sum(proportions)
        proportions.append(prop)
    prop = 1.0 - sum(proportions)
    proportions.append(prop)
    return proportions

* 0.98 + 0.01 位旨在强制执行 ≥ 1% 的约束。这适用于边缘,但在内部不起作用 - 如果两个随机值的距离

>>> numpy.random.seed(2000)                                                                                            
>>> proportions(5)                                                                                                     
[0.3397481983960182, 0.14892479749759702, 0.07456518420712799, 0.005868759570153426, 0.43089306032910335]

有什么建议可以修复这种损坏的方法或用更好的方法代替它吗?

【问题讨论】:

  • 看看thisthis的问题;也许他们可以帮助你
  • 另外:我建议使用整数或Decimal 数字,因为浮点数会导致总和偏离很小的一部分,而且这些错误可能很难检测到。

标签: python sampling


【解决方案1】:

你可以适应Mark Dickinson's nice solution

import random

def proportions(n):
    dividers = sorted(random.sample(range(1, 100), n - 1))
    return [(a - b) / 100 for a, b in zip(dividers + [100], [0] + dividers)]

print(proportions(5))
# [0.13, 0.19, 0.3, 0.34, 0.04]
# or
# [0.31, 0.38, 0.12, 0.05, 0.14]
# etc

注意这里假设“没有一个值小于 0.01”是一个固定阈值

更新:如果我们取阈值的倒数并使用它来替换建议代码中硬编码的100 值,我们可以进行概括。

def proportions(N, T=0.01):
    limit = int(1 / T)
    dividers = sorted(random.sample(range(1, limit), N - 1))
    return [(a - b) / limit for a, b in zip(dividers + [limit], [0] + dividers)]

【讨论】:

  • 很好...一个微小的修改概括了阈值。谢谢!
  • @DanielStandage 还要注意,T 这里不仅仅是最小值,还有可能采样值之间的增量
【解决方案2】:

这个怎么样?

  • N/2 次,选择一个随机数 x 使得 1/N+x 和 1/N-x 适合您的约束;加 1/N+x & 1/N-x
  • 如果 N 是奇数,加 1/N

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 2017-06-12
    • 2016-10-11
    • 2014-05-04
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    相关资源
    最近更新 更多