【问题标题】:Generating a mixture of binomial distributions生成二项分布的混合
【发布时间】:2013-03-03 00:39:01
【问题描述】:

我想生成二项分布的混合。为什么我需要它是因为 我想要高斯分布的正态离散混合。有没有 scipy 库可用于它,或者请您指导我的算法。

我一般都知道预定义的发行版可以使用 ppf。但为此 功能我认为没有任何直接的使用 ppf 的方法。

从每个采样并混合它们似乎也有问题,因为我不知道如何 许多实例我必须从不同的分布中进行选择。

最后我想要的是这样的:

【问题讨论】:

  • “生成混合分布”到底是什么意思?
  • 所以你想从几个高斯的加权和中抽取随机数?
  • 但是如果你每个都有 cdf-s,那么 sum 的 cdf 就是 cdf-s 的总和,不是吗?
  • 总是有拒绝抽样

标签: python statistics distribution random-sample discretization


【解决方案1】:

这是一种生成二项式(和其他)分布的任意混合的简单方法。 它依赖于一个事实,如果你想从混合物中获取样本(Nsamp) P(x)=sum(w[i]*P_i(x), i=1..Nmix),那么你可以通过采样来做到这一点 来自每个 P_i(x) 的 Nsamp。然后得到另一个随机变量的另一个 Nsamp 样本,该样本等于 i,概率为 w[i]。这个随机变量可用于选择给定样本将来自哪个 P_i(x):

import numpy as np,numpy.random, matplotlib.pyplot as plt

#parameters of the binomial distributions: pairs of (n,p)
binomsP = np.array([.5, .5, .5])
binomsCen = np.array([15, 45, 95]) # centers of binomial distributions
binomsN = (binomsCen/binomsP).astype(int)

fractions = [0.2, 0.3, 0.5]
#mixing fractions of the binomials
assert(sum(fractions)==1)

nbinoms = len(binomsN)
npoints = 10000
cumfractions = np.cumsum(fractions)
def mapper(x):
    # convert the random number between 0 and 1 to
    # the ID of the distribution according to the mixing fractions
    return np.digitize(x, cumfractions)

x0 = np.random.binomial(binomsN[None, :],
        binomsP[None, :], size=(npoints, nbinoms))

x = x0[:, mapper(np.random.uniform(size=npoints))]
plt.hist(x, bin=150, range=(0, 150))

【讨论】:

  • 我不太了解你的代码,因此我非常感谢能得到一些解释。谢谢
  • @sega_sai 为什么在将数组传递给binomial 函数时复制它们?
  • @askewchan 当底层对象是列表而不是数组时,复制是代码的残余。现已修复
  • @Naji 我已经为答案添加了更多解释
  • 这正是我为不同混合分数的更一般情况所做的。
【解决方案2】:

除非您找到一种计算逆 cdf 的聪明方法(在这种情况下请告诉我们!),否则拒绝抽样是一种万无一失的方法。 wikipedia entry 给出了一般描述。我在实践中发现,你需要对“工具”分布有点小心:特别是它不应该比目标分布衰减得快得多——如果是这样,你可能会失去尾部的贡献.

我的做法是从一个平坦的工具分布开始:生成一对统一的随机数 x 和 y,其中 y 来自 [0, 1) 和 @987654325 @ 来自[0, L),其中L 足够大。然后比较y和cdf(x),重复直到收敛。如果这行得通,你就准备好了。如果这还不够好,请使用非平坦的工具分布:如果混合物的尾部是高斯分布,那么您最好使用高斯分布。

附带说明,如果您要处理二项分布,则需要注意上溢/下溢 --- 根据参数,您可能需要使用高斯近似。

【讨论】:

    【解决方案3】:

    感谢@sega_sai、@askewchan 和@Zhenya, 我自己编写了代码,我相信由于实现,这将是最 高效的。有两个函数,第一个函数使“binoNumber”二项式分布的混合都具有相同的 N=maximum-minimum 参数和相同的 p=0.5,但根据我为它们生成的随机中心移动。

    global binoInitiated
    binoInitiated=False;
    def binoMixture(minimum,maximum,sampleSize):
        global centers
        binoNumber=10;
        if (not binoInitiated):
            centers=np.random.randint(minimum,maximum+1,binoNumber)
        sigma=maximum-minimum-2
        sam=np.array([]);
        while sam.size<sampleSize:
            i=np.random.choice(binoNumber);
            temp=np.random.binomial(sigma, 0.5,1)+centers[i]-sigma/2+1
            sam=np.append(sam,temp)
        return sam
    

    此功能是为预先制作的分布绘制一个近似的PDF。 感谢@EnricoGiampieri,我使用他的代码制作了这一部分。

    def binoMixtureDrawer(minimum,maximum):
        global binoInitiated
        global centers
        sam=binoMixture(minimum,maximum,50000)    
        # this create the kernel, given an array it will estimate the probability over that values
        kde = gaussian_kde( sam )
        # these are the values over wich your kernel will be evaluated
        dist_space = linspace( min(sam), max(sam), 500 )
        # plot the results
        fig.plot( dist_space, kde(dist_space),'g')
    

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 2013-03-12
      • 1970-01-01
      • 2018-10-19
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      相关资源
      最近更新 更多