วิธีสุ่มตัวอย่างจากการแจกแจงที่กำหนด CDF ใน Python

ฉันต้องการดึงตัวอย่างจากการแจกแจงความน่าจะเป็นด้วย CDF 1 - e^(-x^2)

มีวิธีใน python/scipy/etc หรือไม่ เพื่อให้คุณสามารถสุ่มตัวอย่างจากการแจกแจงความน่าจะเป็นโดยให้เฉพาะ CDF เท่านั้น


person fomin    schedule 06.03.2020    source แหล่งที่มา
comment
ฉันเป็นสนิมนิดหน่อย แต่ถ้าฉันจำ CDF ได้ถูกต้องก็เป็นส่วนหนึ่งของ PDF ดูเหมือนคำถามพีชคณิต อาจจะ: wolframalpha.com/input/?i=d%2Fdx+%281+-+e%5E%28-x%5E2%29%29   -  person pinegulf    schedule 06.03.2020
comment
@pinegulf ขอบคุณ แต่คุณจะสุ่มตัวอย่างได้อย่างไร?   -  person fomin    schedule 06.03.2020
comment
เนื่องจากคุณรู้จัก CDF ที่ค่า X คุณสามารถวนซ้ำโดยทำตามขั้นตอนแล้วหาว่าค่าของ PDF เป็นเท่าใดเมื่อคุณทราบเดลต้าของ CDF   -  person pinegulf    schedule 06.03.2020


คำตอบ (2)


หากต้องการสร้างคลาสตัวแปรสุ่มที่กำหนดเองโดยกำหนด 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()

person Heike    schedule 06.03.2020
comment
ว้าว มันน่าทึ่งมาก คุณรู้ไหมว่ามันทำสิ่งนี้ได้อย่างไร (นั่นคือสร้าง PDF และยังให้วิธีการสุ่มตัวอย่าง) ภายใต้ประทุน? สมมติว่ามันไม่ได้สร้างความแตกต่างใดๆ จริงๆ มันจะต้องเป็นการประมาณตัวเลข - person fomin; 06.03.2020

การสุ่มตัวอย่างการแปลงผกผัน

หากต้องการเพิ่มโซลูชันโดย Heike คุณสามารถใช้ Inverse Transform Sampling เพื่อสุ่มตัวอย่างผ่าน 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) ที่จริงแล้วดูเหมือนว่าจะมีการประมาณเป็นตัวเลขหากไม่ได้ระบุไว้อย่างชัดเจน เจ๋งมาก!

person Jeff N    schedule 14.03.2021