【问题标题】:Truncating SciPy random distributions截断 SciPy 随机分布
【发布时间】:2012-07-15 10:01:04
【问题描述】:

有没有人有关于有效截断 SciPy 随机分布的建议。例如,如果我像这样生成随机值:

import scipy.stats as stats
print stats.logistic.rvs(loc=0, scale=1, size=1000)

如何在不改变分布的原始参数和不改变样本大小的情况下将输出值限制在 0 和 1 之间,同时最大限度地减少机器必须完成的工作量?

【问题讨论】:

    标签: python random statistics scipy


    【解决方案1】:

    您的问题更像是一个统计问题,而不是一个 scipy 问题。通常,您需要能够对您感兴趣的区间进行归一化,并通过分析计算该区间的 CDF 以创建有效的采样方法。 编辑:事实证明这是可能的(不需要拒绝采样):

    import scipy.stats as stats
    
    import matplotlib.pyplot as plt
    import numpy as np
    import numpy.random as rnd
    
    #plot the original distribution
    xrng=np.arange(-10,10,.1)
    yrng=stats.logistic.pdf(xrng)
    plt.plot(xrng,yrng)
    
    #plot the truncated distribution
    nrm=stats.logistic.cdf(1)-stats.logistic.cdf(0)
    xrng=np.arange(0,1,.01)
    yrng=stats.logistic.pdf(xrng)/nrm
    plt.plot(xrng,yrng)
    
    #sample using the inverse cdf
    yr=rnd.rand(100000)*(nrm)+stats.logistic.cdf(0)
    xr=stats.logistic.ppf(yr)
    plt.hist(xr,density=True)
    
    plt.show()
    

    【讨论】:

    • 两个问题:可以直接使用logistic.cdf而不是integrate.quad,并且可以将lst = xr[yr
    • 是的,这两点都很好,但实际上事实证明有一个更好的解决方案......请参阅编辑。
    • Logistic 对 ppf 有一个很好的表达,用 ppf 转换一个统一的随机变量要好得多,但我喜欢你在 ppf 计算成本很高的情况下拒绝抽样的方法。跨度>
    • 是否可以使用已定义的参数来做到这一点?我不明白分布的参数在哪里可以改变,就像在 delogist.rvs() 函数中一样。
    【解决方案2】:

    你想达到什么目的? Logistic distribution 根据定义具有无限范围。如果您以任何方式截断结果,它们的分布将会改变。如果你只是想随机数范围内,有random.random()

    【讨论】:

    • 我仅以逻辑为例,但在某些情况下,实际分布与理论分布几乎相同,但由于某些外部约束,实际上无法超过某个值.截断,在许多情况下只会添加一个微小的错误,这对于建模来说可以忽略不计。如果您不相信,我认为最好将其视为简单的理论练习。
    【解决方案3】:

    您可以将结果标准化为最大返回值:

    >>> dist = stats.logistic.rvs(loc=0, scale=1, size=1000)
    >>> norm_dist = dist / np.max(dist)
    

    这将使“形状”和01 之间的值保持不变。但是,如果您要从分布中重复抽取,请确保将所有抽取标准化为相同的值(所有抽取的最大值)。

    但是,如果你做的这种事情在你想要达到的目标的范围内是有意义的,你要非常小心(我没有足够的信息来评论......)

    【讨论】:

    • 非常抱歉 - 我不清楚(我更新了问题)。我不是指“形状”,而是指“原始参数”。另外,我认为这(对于某些分布)可能与更改比例参数具有相同的效果。