Saya ingin mengambil sampel dari distribusi probabilitas dengan CDF 1 - e^(-x^2)
.
Apakah ada metode di python/scipy/etc. untuk memungkinkan Anda mengambil sampel dari distribusi probabilitas hanya dengan CDF-nya?
Saya ingin mengambil sampel dari distribusi probabilitas dengan CDF 1 - e^(-x^2)
.
Apakah ada metode di python/scipy/etc. untuk memungkinkan Anda mengambil sampel dari distribusi probabilitas hanya dengan CDF-nya?
Untuk membuat kelas variabel acak khusus yang diberi CDF, Anda dapat membuat subkelas scipy.rv_continuous
dan mengganti rv_continuous._cdf
. Ini kemudian akan secara otomatis menghasilkan PDF yang sesuai dan informasi statistik lainnya tentang distribusi Anda, misalnya.
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()
Untuk menambahkan solusi Heike, Anda dapat menggunakan Inverse Transform Sampling untuk mengambil sampel melalui 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()
Saya juga sangat penasaran untuk melihat cara kerjanya di SciPy. Tampaknya ia melakukan sesuatu yang sangat mirip dengan yang di atas. Berdasarkan dokumen SciPy:
Metode default _rvs bergantung pada kebalikan dari cdf, _ppf, yang diterapkan pada variasi acak seragam. Untuk menghasilkan variasi acak secara efisien, _ppf default perlu ditimpa (misalnya jika cdf invers dapat dinyatakan dalam bentuk eksplisit) atau metode pengambilan sampel perlu diterapkan dalam metode _rvs khusus.
Dan berdasarkan kode sumber SciPy, _ppf
(yaitu kebalikan dari CDF) sebenarnya terlihat diperkirakan secara numerik jika tidak ditentukan secara eksplisit. Sangat keren!