[英]How to sample from a distribution given the CDF in Python
要創建給定 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 文檔:
默認方法 _rvs 依賴於應用於統一隨機變量的 cdf 的倒數 _ppf。 為了有效地生成隨機變量,要么需要覆蓋默認的 _ppf(例如,如果逆 cdf 可以以顯式形式表示),要么需要在自定義 _rvs 方法中實現采樣方法。
並且基於SciPy 源代碼,如果沒有明確指定, _ppf
(即 CDF 的倒數)實際上看起來是在數值上近似的。 很酷!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.