Para alguma finalidade, eu preciso gerar números aleatórios (dados) a partir da distribuição "uniforme inclinado". A "inclinação" desta distribuição pode variar em algum intervalo razoável e, em seguida, minha distribuição deve mudar de uniforme para triangular com base na inclinação. Aqui está minha derivação:
Vamos simplificar e gerar os dados de a (azul, vermelho é distribuição uniforme). Para obter a função de densidade de probabilidade da linha azul, preciso apenas da equação dessa linha. Portanto:
e desde (foto):
Nós temos que:
Como é PDF, CDF é igual a:
Agora vamos fazer um gerador de dados. A idéia é que, se eu consertar , números aleatórios podem ser computados se obtivermos números de de uma distribuição uniforme, conforme descrito aqui . Portanto, se eu precisar de 100 números aleatórios da minha distribuição com fixo , então para qualquer da distribuição uniforme há da "distribuição inclinada" e podem ser computados como:
A partir dessa teoria, criei código em Python que se parece com:
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
Mas os números gerados rand_numb
são muito próximos de zero ou de B (que eu defini como 25). Não há variação, quando eu gero 100 números, todos eles são próximos de 25 ou todos são próximos de zero. Em uma corrida:
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]
Portanto, deve haver algo muito errado no meu código. Alguém pode me ajudar com minha derivação ou código? Estou louco por isso agora, não vejo nenhum erro. Suponho que o código R me dê resultados semelhantes.
B
theta
n
R
x<-runif(n,-1,1);x<-(ifelse(runif(n,-1,1)>theta*x,-x,x)+1)*(B/2)
Respostas:
Sua derivação está bem. Observe que para obter uma densidade positiva em , você deve restringir No seu código , você deve entre , é aí que seu código falha.(0,B)
Você pode (e deve) Evite usar um solucionador quadrático e, em seguida, selecione as raízes entre 0 e . A equação polinomial quadrática em a ser resolvida é com Pela construção e ; também aumenta em .B x
A partir disso, é fácil ver que, se , a parte da parábola em que estamos interessados faz parte do lado direito da parábola, e a raiz a manter é a mais alta das duas raízes, que é Pelo contrário, se , a parábola está de cabeça para baixo e temos interesse em sua esquerda parte. A raiz a manter é a mais baixa. Levando em consideração o sinal de , parece que essa é a mesma raiz (ou seja, aquela com ) que no primeiro caso.x = 1tanϕ>0 tanϕ<0tanϕ+√
Aqui está um código R.
E com :ϕ<0
fonte