简体   繁体   English

用给定的概率密度函数生成随机数

[英]Generating random numbers with a given probability density function

I want to specify the probability density function of a distribution and then pick up N random numbers from that distribution in Python.我想指定分布的概率密度函数,然后在 Python 中从该分布中选取 N 个随机数。 How do I go about doing that?我该怎么做?

In general, you want to have the inverse cumulative probability density function.通常,您希望具有逆累积概率密度函数。 Once you have that, then generating the random numbers along the distribution is simple:一旦你有了它,那么沿着分布生成随机数就很简单了:

import random

def sample(n):
    return [ icdf(random.random()) for _ in range(n) ]

Or, if you use NumPy:或者,如果您使用 NumPy:

import numpy as np

def sample(n):
    return icdf(np.random.random(n))

In both cases icdf is the inverse cumulative distribution function which accepts a value between 0 and 1 and outputs the corresponding value from the distribution.在这两种情况下, icdf都是逆累积分布函数,它接受 0 到 1 之间的值并从分布中输出相应的值。

To illustrate the nature of icdf , we'll take a simple uniform distribution between values 10 and 12 as an example:为了说明icdf的性质,我们将以值 10 和 12 之间的简单均匀分布为例:

  • probability distribution function is 0.5 between 10 and 12, zero elsewhere概率分布函数在 10 到 12 之间为 0.5,其他地方为零

  • cumulative distribution function is 0 below 10 (no samples below 10), 1 above 12 (no samples above 12) and increases linearly between the values (integral of the PDF)累积分布函数是 0 低于 10(没有低于 10 的样本),高于 12(没有高于 12 的样本)并且在值之间线性增加(PDF 的积分)

  • inverse cumulative distribution function is only defined between 0 and 1. At 0 it is 10, at 12 it is 1, and changes linearly between the values逆累积分布函数仅定义在 0 和 1 之间。0 时为 10,12 时为 1,并且在值之间线性变化

Of course, the difficult part is obtaining the inverse cumulative density function.当然,难点在于获得逆累积密度函数。 It really depends on your distribution, sometimes you may have an analytical function, sometimes you may want to resort to interpolation.这真的取决于你的分布,有时你可能有一个分析函数,有时你可能想要求助于插值。 Numerical methods may be useful, as numerical integration can be used to create the CDF and interpolation can be used to invert it.数值方法可能很有用,因为数值积分可用于创建 CDF,插值可用于反转它。

This is my function to retrieve a single random number distributed according to the given probability density function.这是我的函数,用于检索根据给定概率密度函数分布的单个随机数。 I used a Monte-Carlo like approach.我使用了类似蒙特卡罗的方法。 Of course n random numbers can be generated by calling this function n times.当然调用这个函数n次可以产生n个随机数。

    """
    Draws a random number from given probability density function.

    Parameters
    ----------
        pdf       -- the function pointer to a probability density function of form P = pdf(x)
        interval  -- the resulting random number is restricted to this interval
        pdfmax    -- the maximum of the probability density function
        integers  -- boolean, indicating if the result is desired as integer
        max_iterations -- maximum number of 'tries' to find a combination of random numbers (rand_x, rand_y) located below the function value calc_y = pdf(rand_x).

    returns a single random number according the pdf distribution.
    """
    def draw_random_number_from_pdf(pdf, interval, pdfmax = 1, integers = False, max_iterations = 10000):
        for i in range(max_iterations):
            if integers == True:
                rand_x = np.random.randint(interval[0], interval[1])
            else:
                rand_x = (interval[1] - interval[0]) * np.random.random(1) + interval[0] #(b - a) * random_sample() + a

            rand_y = pdfmax * np.random.random(1) 
            calc_y = pdf(rand_x)

            if(rand_y <= calc_y ):
                return rand_x

        raise Exception("Could not find a matching random number within pdf in " + max_iterations + " iterations.")

In my opinion this solution is performing better than other solutions if you do not have to retrieve a very large number of random variables.在我看来,如果您不必检索大量随机变量,则此解决方案的性能优于其他解决方案。 Another benefit is that you only need the PDF and avoid calculating the CDF, inverse CDF or weights.另一个好处是您只需要 PDF 而避免计算 CDF、逆 CDF 或权重。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM