Утворіть випадкові числа з "похилого рівномірного розподілу" з математичної теорії


9

З якоюсь метою мені потрібно генерувати випадкові числа (дані) з "похилого рівномірного" розподілу. "Нахил" цього розподілу може змінюватись в якийсь розумний інтервал, і тоді мій розподіл повинен змінюватися від рівномірного до трикутного на основі схилу. Ось моя деривація:

введіть тут опис зображення

Давайте спростимо та сформуємо дані від до (синій, червоний - рівномірний розподіл). Для отримання функції щільності ймовірності синьої лінії мені потрібно лише рівняння цієї лінії. Таким чином:0B

f(x)=tg(φ)x+Y(0)

і відтоді (фотографія):

tg(φ)=1/BY(0)B/2Y(0)=1Btg(φ)B2

У нас це є:

f(x)=tg(φ)x+(1Btg(φ)B2)

Оскільки - PDF, CDF дорівнює:f(x)

F(x)=tg(φ)x22+x(1Btg(φ)B2)

Тепер давайте зробимо генератор даних. Ідея полягає в тому, що якщо я виправляю , випадкові числа можна обчислити, якщо я отримаю числа від рівномірного розподілу, як описано тут . Таким чином, якщо мені потрібно 100 випадкових чисел з мого розподілу з фіксованим , то для будь-якого з рівномірного розподілу існує від "похилого розподілу", а можна обчислити як:φ,Bx(0,1)φ,Bti(0,1)xix

tg(φ)xi22+xi(1Btg(φ)B2)ti=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-координату з на . Наприклад, дайте будь-які значення та (реальний параметр, який при заданих значеннях від до виробляє ваші розподіли) та встановіть кількість необхідних вам випадкових значень. Ось код:ϕxBxBtheta11nRx<-runif(n,-1,1);x<-(ifelse(runif(n,-1,1)>theta*x,-x,x)+1)*(B/2)
whuber

Відповіді:


9

Ваша деривація гаразд. Зауважте, що для отримання позитивної щільності на , вам потрібно обмежити У своєму коді тож слід приймати між , саме тут ваш код виходить з ладу.(0,B)

B2tanϕ<2.
B=25ϕ±tan12625

Ви можете (і повинні) уникати використання квадратичного решателя, а потім вибрати коріння між 0 і . Квадратичне поліномне рівняння в яке потрібно розв’язати, при За побудовою і ; також збільшується на .Bx

F(x)=t
F(x)=12tanϕx2+(1BB2tanϕ)x.
F(0)=0F(B)=1F(0,B)

З цього легко зрозуміти, що якщо , частина параболи, в якій нас цікавить, є частиною правої сторони параболи, а корінь, який потрібно зберегти, є найвищим з двох коренів, є Якщо навпаки, якщо , парабола перевернута, і нас цікавить її зліва частина. Корінь, який потрібно зберегти, - найнижчий. Враховуючи знак виявляється, що це той самий корінь (тобто той, що має ), ніж у першому випадку.tanϕ>0

x=1tanϕ(B2tanϕ1B+(B2tanϕ1B)2+2tanϕt.)
tanϕ<0tanϕ+Δ

Ось декілька код 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
Я помилився, бо встановив свій кут поза межами, я це розумію. Але ваше пояснення, чому я повинен avouid, використовуючи числовий розв'язувач , для мене все ще туманне. Ви можете спробувати пояснити це, будь ласка? я люблю його отримати. F(x)
Роберт

@Robert Я думаю, що ваш код працює добре, якщо значення правильне. Однак це заважає вам зафіксувати потенційні проблеми (що робити, якщо жодного рішення немає між 0 і ? Або якщо обидва рішення є? Або якщо немає реального рішення?). Додаткова робота, щоб уникнути використання готового вирішувача, варта того. ϕB
Елвіс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.