สร้างตัวเลขสุ่มจาก“ การกระจายตัวแบบลาด” จากทฤษฎีทางคณิตศาสตร์


9

เพื่อจุดประสงค์บางอย่างฉันต้องสร้างตัวเลขสุ่ม (ข้อมูล) จากการกระจาย "ชุดลาด" "ความชัน" ของการกระจายนี้อาจแตกต่างกันไปในช่วงเวลาที่สมเหตุสมผลแล้วการกระจายของฉันควรเปลี่ยนจากเครื่องแบบเป็นสามเหลี่ยมตามความชัน นี่คือที่มาของฉัน:

ป้อนคำอธิบายรูปภาพที่นี่

มาทำให้มันง่ายและสร้างฟอร์มข้อมูล 0 ถึง B(สีน้ำเงิน, สีแดงคือการกระจายแบบสม่ำเสมอ) เพื่อให้ได้ฟังก์ชันความหนาแน่นของความน่าจะเป็นของเส้นสีฟ้าฉันต้องการเพียงสมการของเส้นนั้น ดังนั้น:

(x)=เสื้อก.(φ)x+Y(0)

และตั้งแต่ (ภาพ):

เสื้อก.(φ)=1/B-Y(0)B/2Y(0)=1B-เสื้อก.(φ)B2

เรามีสิ่งต่อไปนี้:

(x)=เสื้อก.(φ)x+(1B-เสื้อก.(φ)B2)

ตั้งแต่ (x) คือ PDF, CDF เท่ากับ:

F(x)=เสื้อก.(φ)x22+x(1B-เสื้อก.(φ)B2)

ทีนี้มาสร้าง data data กัน ความคิดคือถ้าฉันจะแก้ไขφ,Bตัวเลขสุ่ม x สามารถคำนวณได้ถ้าฉันจะรับตัวเลข (0,1)จากการกระจายชุดตามที่อธิบายไว้ที่นี่ ดังนั้นถ้าฉันต้องการ 100 ตัวเลขสุ่มจากการกระจายของฉันกับการแก้ไขφ,Bจากนั้นสำหรับใด ๆ เสื้อผม จากการกระจายสม่ำเสมอ (0,1) มี xผม จาก "การกระจายแบบลาด" และ x สามารถคำนวณได้เป็น:

เสื้อก.(φ)xผม22+xผม(1B-เสื้อก.(φ)B2)-เสื้อผม=0

จากทฤษฎีนี้ฉันทำรหัสใน Python ซึ่งมีลักษณะดังนี้:

import numpy as np
import math
import random
def tan_choice():
    x = random.uniform(-math.pi/3, math.pi/3)
    tan = math.tan(x)
    return tan

def rand_shape_unif(N, B, tg_fi):
    res = []
    n = 0
    while N > n:
        c = random.uniform(0,1)
        a = tg_fi/2
        b = 1/B - (tg_fi*B)/2
        quadratic = np.poly1d([a,b,-c])
        rots = quadratic.roots
        rot = rots[(rots.imag == 0) & (rots.real >= 0) & (rots.real <= B)].real
        rot = float(rot)
        res.append(rot)
        n += 1
    return res

def rand_numb(N_, B_):
    tan_ = tan_choice()
    res = rand_shape_unif(N_, B_, tan_)
    return res

แต่ตัวเลขที่สร้างจากrand_numbนั้นใกล้เคียงกับศูนย์มากหรือเป็น B (ซึ่งฉันตั้งไว้ที่ 25) ไม่มีความแปรปรวนเมื่อฉันสร้างหมายเลข 100 พวกเขาทั้งหมดใกล้ถึง 25 หรือทั้งหมดอยู่ใกล้ศูนย์ ในการวิ่งครั้งเดียว:

num = rand_numb(100, 25)
numb
Out[140]: 
[0.1063241766836174,
 0.011086243095907753,
 0.05690217839063588,
 0.08551031241199764,
 0.03411227661295121,
 0.10927087752739746,
 0.1173334720516189,
 0.14160616846114774,
 0.020124543145515768,
 0.10794924067959207]

ดังนั้นต้องมีบางอย่างผิดปกติในรหัสของฉัน ใครสามารถช่วยฉันด้วยรหัสที่มาหรือไม่ ตอนนี้ฉันคลั่งไคล้แล้วฉันไม่เห็นความผิดพลาดใด ๆ ฉันคิดว่ารหัส R จะให้ผลลัพธ์ที่คล้ายกัน


2
หากคุณต้องการสร้างตัวเลขสุ่มคุณไม่จำเป็นต้องคำนวณการแจกแจงเลย เพียงแค่โยนลูกดอกใส่รูปภาพของคุณและเก็บพิกัด x ไว้แต่เมื่อลูกดอกตกลงบนสามเหลี่ยมซ้ายที่ระบุว่า "φ"เปลี่ยนพิกัด x จาก x ถึง B-x. ตัวอย่างเช่นให้ค่าใด ๆ กับBและtheta(พารามิเตอร์จริงซึ่งเมื่อได้รับค่าระหว่าง-1 และ 1สร้างการแจกแจงของคุณ) และตั้งค่าnให้เป็นจำนวนค่าสุ่มที่คุณต้องการ นี่คือRรหัส:x<-runif(n,-1,1);x<-(ifelse(runif(n,-1,1)>theta*x,-x,x)+1)*(B/2)
whuber

คำตอบ:


9

การสืบทอดของคุณก็โอเค โปรดทราบว่าจะได้รับความหนาแน่นในเชิงบวก(0,B)คุณต้อง จำกัด

B2สีน้ำตาลφ<2
ในรหัสของคุณ B=25 ดังนั้นคุณควรใช้ φ ระหว่าง ±สีน้ำตาล-12625นั่นคือสิ่งที่รหัสของคุณล้มเหลว

คุณสามารถ (และควร) หลีกเลี่ยงการใช้ตัวแก้กำลังสองแล้วเลือกรากระหว่าง 0 ถึง B. สมการพหุนามกำลังสองในx ที่จะแก้ไขคือ

F(x)=เสื้อ
กับ
F(x)=12สีน้ำตาลφx2+(1B-B2สีน้ำตาลφ)x.
โดยการก่อสร้าง F(0)=0 และ F(B)=1; ด้วยF เพิ่มขึ้นเมื่อ (0,B).

จากนี้มันง่ายที่จะดูว่าถ้า สีน้ำตาลφ>0ส่วนของพาราโบลาที่เราสนใจนั้นเป็นส่วนหนึ่งของด้านขวาของพาราโบลาและรากที่ต้องเก็บคือรากที่สูงที่สุดของรากทั้งสองนั่นคือ

x=1สีน้ำตาลφ(B2สีน้ำตาลφ-1B+(B2สีน้ำตาลφ-1B)2+2สีน้ำตาลφเสื้อ.)
ในทางตรงกันข้ามถ้า สีน้ำตาลφ<0พาราโบลาคว่ำและเราสนใจส่วนที่เหลือ รูทที่จะเก็บนั้นต่ำที่สุด คำนึงถึงสัญลักษณ์ของสีน้ำตาลφ ปรากฏว่านี่เป็นรูทเดียวกัน (เช่นอันที่มี +Δ) มากกว่าในกรณีแรก

นี่คือรหัส R บางอย่าง

phi <- pi/8; B <- 2
f <- function(t) (-(1/B - 0.5*B*tan(phi)) + 
       sqrt( (1/B - 0.5*B*tan(phi))**2 + 2 * tan(phi) * t))/tan(phi)
hist(f(runif(1e6)))

ฮิสโตแกรม 1

และด้วย φ<0:

phi <- -pi/8
hist(f(runif(1e6)))

ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันทำผิดพลาดเพราะฉันตั้งมุมของฉันออกนอกขอบเขตฉันเข้าใจ แต่คำอธิบายของคุณว่าทำไมฉันควรหลีกเลี่ยงการใช้ตัวแก้ตัวเลขF(x)ยังคงมีหมอกสำหรับฉัน คุณช่วยอธิบายเพิ่มเติมได้มั้ย id รักที่จะได้รับมัน
Robert

@ Robert ฉันคิดว่ารหัสของคุณทำงานได้ดีถ้ามูลค่า φถูกต้อง. อย่างไรก็ตามมันจะป้องกันคุณจากการจับปัญหาที่อาจเกิดขึ้น (ถ้าไม่มีวิธีแก้ปัญหาอยู่ระหว่าง 0 ถึงB? หรือถ้าทั้งสองวิธีแก้ปัญหาคืออะไร? หรือถ้าไม่มีวิธีแก้ปัญหาจริง ๆ ?) งานเพิ่มเติมเพื่อหลีกเลี่ยงการใช้ตัวแก้ปัญหาสำเร็จรูปมีค่า
Elvis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.