【问题标题】:Numpy array with the given values and the sum equal 1具有给定值且总和等于 1 的 Numpy 数组
【发布时间】:2020-08-13 03:36:56
【问题描述】:

我想创建随机 np.array,其值仅包括 [0.05, 0.1, 0.15, ... 0.9, 0.95, 1] 值的总和 = 1

我知道如何创建一个随机数组,例如 5 个元素,使总和等于 1:

array = np.random.random(5)
array /= np.sum(array)

但是我怎样才能使这个数组中的值仅来自 [0.05, 0.1, 0.15, ... 0.9, 0.95, 1]?

更新。这种方法有效,但也许有更多的pythonic方法。 100 个数组

sets = []
while len(sets) < 100:
    array = np.random.choice(np.arange(0, 1.05, 0.05), 5)
    if np.sum(array) == 1:
        sets.append(array)

【问题讨论】:

  • 您要选择固定数量的随机数吗?如果这就是您要寻找的,那么同时具有这两个条件将消除它的完全均匀随机性。
  • 你不能用所需的值和总和来随机排列数组吗?类似numpy.random.shuffle(numpy.arange(0.05, 1.05, 0.05))
  • 我想选择固定数字 [0.05, 0.1, 0.15, ... 0.9, 0.95, 1] 但以随机顺序,使总和 = 1
  • @JSer1 您生成的arr 是否可以包含给定值列表中的重复元素?
  • 是的,重复元素是可以的。

标签: python numpy random


【解决方案1】:

你的问题等价于下面的问题:

  1. [1, 20]中选择5个随机整数,总和为20,其中整数以随机顺序出现。
  2. 将所选整数除以 20。

下面的 Python 代码显示了如何实现这一点。它具有以下优点:

  • 它不使用拒绝抽样。
  • 从所有符合要求的组合中均匀随机选择。

它基于 John McClane 的算法,他将其发布为 answer to another question。我在另一个答案中describe the algorithm

import random # Or secrets

def _getSolTable(n, mn, mx, sum):
        t = [[0 for i in range(sum + 1)] for j in range(n + 1)]
        t[0][0] = 1
        for i in range(1, n + 1):
            for j in range(0, sum + 1):
                jm = max(j - (mx - mn), 0)
                v = 0
                for k in range(jm, j + 1):
                    v += t[i - 1][k]
                t[i][j] = v
        return t

def intsInRangeWithSum(numSamples, numPerSample, mn, mx, sum):
        """ Generates one or more combinations of
           'numPerSample' numbers each, where each
           combination's numbers sum to 'sum' and are listed
           in any order, and each
           number is in the interval '[mn, mx]'.
            The combinations are chosen uniformly at random.
               'mn', 'mx', and
           'sum' may not be negative.  Returns an empty
           list if 'numSamples' is zero.
            The algorithm is thanks to a _Stack Overflow_
          answer (`questions/61393463`) by John McClane.
          Raises an error if there is no solution for the given
          parameters.  """
        adjsum = sum - numPerSample * mn
        # Min, max, sum negative
        if mn < 0 or mx < 0 or sum < 0:
            raise ValueError
        # No solution
        if numPerSample * mx < sum:
            raise ValueError
        if numPerSample * mn > sum:
            raise ValueError
        if numSamples == 0:
            return []
        # One solution
        if numPerSample * mx == sum:
            return [[mx for i in range(numPerSample)] for i in range(numSamples)]
        if numPerSample * mn == sum:
            return [[mn for i in range(numPerSample)] for i in range(numSamples)]
        samples = [None for i in range(numSamples)]
        table = _getSolTable(numPerSample, mn, mx, adjsum)
        for sample in range(numSamples):
            s = adjsum
            ret = [0 for i in range(numPerSample)]
            for ib in range(numPerSample):
                i = numPerSample - 1 - ib
                # Or secrets.randbelow(table[i + 1][s])
                v = random.randint(0, table[i + 1][s] - 1)
                r = mn
                v -= table[i][s]
                while v >= 0:
                    s -= 1
                    r += 1
                    v -= table[i][s]
                ret[i] = r
            samples[sample] = ret
        return samples

例子:

weights=intsInRangeWithSum(
   # One sample
   1,
   # Count of numbers per sample
   5,
   # Range of the random numbers
   1, 20,
   # Sum of the numbers
   20)
# Divide by 100 to get weights that sum to 1
weights=[x/20.0 for x in weights[0]]

无论如何,您的代码如下:

array = np.random.random(5)
array /= np.sum(array)

...不会产生总和为 1 的数字的统一随机组合。相反,请使用以下代码代替该代码,注意统一到达是 指数 间隔的,而不是均匀间隔的. (需要明确的是,这并不能解决您问题中的问题;这只是一个观察结果。不要介意自 NumPy 1.17 以来 numpy.random.* 函数是 now legacy functions 的事实,部分原因是它们使用全局状态。)

array = np.random.exponential(5)
array /= np.sum(array)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 2021-01-01
    • 2020-04-06
    • 2013-07-16
    • 2014-11-17
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多