首页 文章

使用SciPy或NumPy生成具有指定权重的离散随机变量

提问于
浏览
39

我正在寻找一个简单的函数,它可以根据相应的(也是指定的)概率生成指定随机值的数组 . 我只需要它来生成浮点值,但我不明白为什么它不能生成任何标量 . 我可以想到从现有函数构建这个函数的许多方法,但我想我可能只是错过了一个明显的SciPy或NumPy函数 .

例如 . :

>>> values = [1.1, 2.2, 3.3]
>>> probabilities = [0.2, 0.5, 0.3]
>>> print some_function(values, probabilities, size=10)
(2.2, 1.1, 3.3, 3.3, 2.2, 2.2, 1.1, 2.2, 3.3, 2.2)

注意:我找到 scipy.stats.rv_discrete 但我不明白它是如何工作的 . 具体来说,我不明白这(下面)的含义是什么,也不应该做什么:

numargs = generic.numargs
[ <shape(s)> ] = ['Replace with resonable value', ]*numargs

如果rv_discrete是我应该使用的,你能否提供一个简单的例子和对上述“形状”陈述的解释?

5 回答

  • 3

    从离散分布中绘制直接构建为numpy . 该函数被称为random.choice(在numpy文档中没有任何对离散分布的引用很难找到) .

    elements = [1.1, 2.2, 3.3]
    probabilities = [0.2, 0.5, 0.3]
    np.random.choice(elements, 10, p=probabilities)
    
  • 54

    这是一个简短的,相对简单的函数,它返回加权值,它使用NumPy的 digitizeaccumulaterandom_sample .

    import numpy as np
    from numpy.random import random_sample
    
    def weighted_values(values, probabilities, size):
        bins = np.add.accumulate(probabilities)
        return values[np.digitize(random_sample(size), bins)]
    
    values = np.array([1.1, 2.2, 3.3])
    probabilities = np.array([0.2, 0.5, 0.3])
    
    print weighted_values(values, probabilities, 10)
    #Sample output:
    [ 2.2  2.2  1.1  2.2  2.2  3.3  3.3  2.2  3.3  3.3]
    

    它的工作原理如下:

    • 首先使用 accumulate 我们创建箱子 .

    • 然后我们使用 random_sample 创建一堆随机数(在 01 之间)

    • 我们使用 digitize 来查看这些数字属于哪些箱柜 .

    • 并返回相应的值 .

  • 4

    你正朝着一个好方向前进:内置的 scipy.stats.rv_discrete() 直接创建了一个离散的随机变量 . 下面是它的工作原理:

    >>> from scipy.stats import rv_discrete  
    
    >>> values = numpy.array([1.1, 2.2, 3.3])
    >>> probabilities = [0.2, 0.5, 0.3]
    
    >>> distrib = rv_discrete(values=(range(len(values)), probabilities))  # This defines a Scipy probability distribution
    
    >>> distrib.rvs(size=10)  # 10 samples from range(len(values))
    array([1, 2, 0, 2, 2, 0, 2, 1, 0, 2])
    
    >>> values[_]  # Conversion to specific discrete values (the fact that values is a NumPy array is used for the indexing)
    [2.2, 3.3, 1.1, 3.3, 3.3, 1.1, 3.3, 2.2, 1.1, 3.3]
    

    因此,上面的分发 distrib 返回 values 列表中的索引 .

    更一般地, rv_discrete() 在其 values=(…,…) 参数的第一个元素中采用一系列整数值,并返回这些值,在这种情况下;无需转换为特定(浮点)值 . 这是一个例子:

    >>> values = [10, 20, 30]
    >>> probabilities = [0.2, 0.5, 0.3]
    >>> distrib = rv_discrete(values=(values, probabilities))
    >>> distrib.rvs(size=10)
    array([20, 20, 20, 20, 20, 20, 20, 30, 20, 20])
    

    其中(整数)输入值以所需概率直接返回 .

  • 25

    您还可以使用Lea,一个专用于离散概率分布的纯Python包 .

    >>> distrib = Lea.fromValFreqs((1.1,2),(2.2,5),(3.3,3))
    >>> distrib
    1.1 : 2/10
    2.2 : 5/10
    3.3 : 3/10
    >>> distrib.random(10)
    (2.2, 2.2, 1.1, 2.2, 2.2, 2.2, 1.1, 3.3, 1.1, 3.3)
    

    Etvoilà!

  • 15

    最简单的DIY方式是将概率总结为累积分布 . 这样,您可以将单位间隔分割为长度等于原始概率的子间隔 . 现在在[0,1)上生成一个随机数统一,并查看它所到达的间隔 .

相关问题