Para algún propósito, necesito generar números aleatorios (datos) de la distribución "uniforme inclinado". La "pendiente" de esta distribución puede variar en un intervalo razonable, y luego mi distribución debería cambiar de uniforme a triangular en función de la pendiente. Aquí está mi derivación:
Hagámoslo simple y generemos datos de a (azul, rojo es distribución uniforme). Para obtener la función de densidad de probabilidad de la línea azul solo necesito la ecuación de esa línea. Así:B
y desde (foto):
Tenemos que:
Como es PDF, CDF es igual a:
Ahora hagamos un generador de datos. La idea es que si soluciono , se pueden calcular números aleatorios si obtengo números de de una distribución uniforme como se describe aquí . Por lo tanto, si necesito 100 números aleatorios de mi distribución con fijo , entonces para cualquier de distribución uniforme hay de "distribución inclinada", y puede calcularse como:x ( 0 , 1 ) φ , B t i ( 0 , 1 ) x
A partir de esta teoría, hice un código en Python que se parece a:
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
Pero los números generados rand_numb
son muy cercanos a cero o B (que configuré como 25). No hay variación, cuando genero 100 números, todos ellos están cerca de 25 o todos están cerca de cero. En una carrera:
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]
Entonces debe haber algo muy mal en mi código. ¿Alguien puede ayudarme con mi derivación o código? Estoy loco por esto ahora, no puedo ver ningún error. Supongo que el código R me dará resultados similares.
B
theta
n
R
x<-runif(n,-1,1);x<-(ifelse(runif(n,-1,1)>theta*x,-x,x)+1)*(B/2)
Respuestas:
Tu derivación está bien. Tenga en cuenta que para obtener una densidad positiva en , debe restringir En su código , debe tomar entre , ahí es donde falla su código.( 0 , B )
Usted puede (y debe) evitar el uso de un programa de solución cuadrática y, a continuación, seleccione las raíces entre 0 y . La ecuación polinómica cuadrática en a resolver es con Por construcción y ; también aumenta en .si x
A partir de esto, es fácil ver que si , la porción de parábola en la que estamos interesados es una parte del lado derecho de la parábola, y la raíz a mantener es la más alta de las dos raíces, que es Por el contrario, si , la parábola está al revés y nos interesa su izquierda parte. La raíz a mantener es la más baja. Teniendo en cuenta el signo de , parece que esta es la misma raíz (es decir, la que tiene ) que en el primer caso.tanϕ>0 tanϕ<0tanϕ
Aquí hay un código R.
Y con :ϕ<0
fuente