簡體   English   中英

如何從 Python 中給定 CDF 的分布中采樣

[英]How to sample from a distribution given the CDF in Python

我想從CDF 1 - e^(-x^2)的概率分布中抽取樣本。

python/scipy/etc 中有沒有方法? 使您能夠從僅給定 CDF 的概率分布中進行采樣?

要創建給定 CDF 的自定義隨機變量類,您可以子類化scipy.rv_continuous並覆蓋rv_continuous._cdf 然后,這將自動生成相應的 PDF 和有關您的分布的其他統計信息,例如

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

class MyRandomVariableClass(stats.rv_continuous):
    def __init__(self, xtol=1e-14, seed=None):
        super().__init__(a=0, xtol=xtol, seed=seed)

    def _cdf(self, x):
        return 1-np.exp(-x**2)


if __name__ == "__main__":
    my_rv = MyRandomVariableClass()

    # sample distribution
    samples = my_rv.rvs(size = 1000)

    # plot histogram of samples
    fig, ax1 = plt.subplots()
    ax1.hist(list(samples), bins=50)

    # plot PDF and CDF of distribution
    pts = np.linspace(0, 5)
    ax2 = ax1.twinx()
    ax2.set_ylim(0,1.1)
    ax2.plot(pts, my_rv.pdf(pts), color='red')
    ax2.plot(pts, my_rv.cdf(pts), color='orange')

    fig.tight_layout()
    plt.show()

逆變換采樣

要添加 Heike 的解決方案,您可以使用逆變換采樣通過 CDF 進行采樣:

import math, random
import matplotlib.pyplot as plt

def inverse_cdf(y):
    # Computed analytically
    return math.sqrt(math.log(-1/(y - 1)))

def sample_distribution():
    uniform_random_sample = random.random()
    return inverse_cdf(uniform_random_sample)

x = [sample_distribution() for i in range(10000)]
plt.hist(x, bins=50)
plt.show()

SciPy 是如何做到的

我也很好奇這在 SciPy 中是如何工作的。 它實際上看起來與上面的非常相似。 基於SciPy 文檔

默認方法 _rvs 依賴於應用於統一隨機變量的 cdf 的倒數 _ppf。 為了有效地生成隨機變量,要么需要覆蓋默認的 _ppf(例如,如果逆 cdf 可以以顯式形式表示),要么需要在自定義 _rvs 方法中實現采樣方法。

並且基於SciPy 源代碼,如果沒有明確指定, _ppf (即 CDF 的倒數)實際上看起來是在數值上近似的。 很酷!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM