scipy.stats.rv_continuous的子类化

时间:2017-03-02 09:55:51

标签: python scipy

关于scipy.stats.rv_continuous的子类化我有3个问题。 我的目标是编码截断正态分布,截断指数分布和2个均匀分布的统计混合模型。

1)为什么通过mm_model.rvs(size = 1000)绘制随机变量这么慢?我在纪录片中读到了一些关于性能问题的内容,但我真的很惊讶。

2)通过mm_model.rvs(size = 1000)绘制随机变量后,我得到了这个IntegrationWarning?

IntegrationWarning:已实现最大细分数(50)。   如果增加限制没有产生任何改善,建议分析   被积函数以确定困难。如果一个位置   可以确定局部困难(奇点,不连​​续性)   可能从分割间隔和调用积分器中获益   关于子范围。也许应该使用专用集成商。   warnings.warn(msg,IntegrationWarning)

3)我在纪录片中读到我可以通过"形状"将参数传送到pdf。参数。我试着调整我的pdf并设置形状参数,但它没有用。有人可以解释一下吗?

感谢您的帮助。

def trunc_norm(z,low_bound,up_bound,mu,sigma):
    a = (low_bound - mu) / sigma
    b = (up_bound - mu) / sigma
    return stats.truncnorm.pdf(z,a,b,loc=mu,scale=sigma)



def trunc_exp(z,up_bound,lam):
    return stats.truncexpon.pdf(z,b=up_bound*lam,scale=1/lam)



def uniform(z,a,b):
    return stats.uniform.pdf(z,loc=a,scale=(b-a))


class Measure_mixture_model(stats.rv_continuous):

    def _pdf(self,z):

        z_true = 8
        z_min = 0
        z_max = 10
        p_hit = 0.7
        p_short = 0.1   
        p_max = 0.1
        p_rand = 0.1
        sig_hit = 1
        lambda_short = 0.5

        sum_p = p_hit + p_short + p_max + p_rand

        if sum_p < 0.99 or 1.01 < sum_p:
            misc.eprint("apriori probabilities p_hit, p_short, p_max, p_rand have to be 1!")
            return None

        pdf_hit = trunc_norm(z,z_min,z_max,z_true,sig_hit)
        pdf_short = trunc_exp(z,z_true,lambda_short)
        pdf_max = uniform(z,0.99*z_max,z_max)
        pdf_rand = uniform(z,z_min,z_max)

        pdf = p_hit * pdf_hit + p_short * pdf_short + p_max * pdf_max + p_rand * pdf_rand

        return pdf




#mm_model = Measure_mixture_model(shapes='z_true,z_min,z_max,p_hit,p_short,p_max,p_rand,sig_hit,lambda_short')
mm_model = Measure_mixture_model()


z = np.linspace(-1,11,1000)

samples = mm_model.pdf(z)
plt.plot(z,samples)
plt.show()


rand_samples = mm_model.rvs(size = 1000)


bins = np.linspace(-1, 11, 100)
plt.hist(rand_samples,bins)
plt.title("measure mixture model")
plt.xlabel("z: measurement")
plt.ylabel("p: relative frequency")
plt.show()

1 个答案:

答案 0 :(得分:0)

(1)和(2)可能是相关的。您要求scipy仅根据您提供的密度生成随机样本。

我真的不知道scipy会做什么,但我怀疑它整合了密度(&#34; pdf&#34;)以获得概率函数(&#34; cdf&#34;)然后反转它将统一样本映射到您的分布。这在数字上是昂贵的,因为您经历了容易出错。

为了加快速度,您可以直接实施_rvs来帮助实现目标。只需绘制一个制服来决定要选择混合的哪个子模型,然后调用所选子模型的rvs。与您可能需要的其他功能类似。

以下是有关如何实现矢量化rvs的一些提示:

批量选择子模型。由于您的子模型数量很少np.digitize应该足够好。如果可能,请为子模型使用rv_frozen个实例;它们非常方便,但我似乎记得你不能将所有可选参数传递给它们,所以你可能需要单独处理它们。

self._bins = np.cumsum([p_hit, p_short, p_max])
self._bins /= self._bins[-1] + p_rand

submodel = np.digitize(uniform.rvs(size=size), self._bins)

result = np.empty(size)
for j, frozen in enumerate((frz_trunc_norm, frz_trunc_exp, frz_unif_1, frz_unif_2)):
    inds = np.where(submodel == j)
    result[inds] = frozen.rvs(size=inds.shape)
return result

Re(3)这是scipy docs所说的。

  

关于形状的注释:子类不需要明确指定它们。在这种情况下,将从被覆盖的方法(pdf,cdf等)的签名中自动推导出形状。如果由于某种原因,您希望避免依赖内省,则可以明确指定形状作为实例构造函数的参数。

所以通常的方法是在你的方法中加入一些参数。