¿Alguien puede decirme cómo simular , donde , usando un lanzamiento de monedas (tantas veces como sea necesario) con ?
Estaba pensando en usar muestras de rechazo, pero no pude precisarlo.
¿Alguien puede decirme cómo simular , donde , usando un lanzamiento de monedas (tantas veces como sea necesario) con ?
Estaba pensando en usar muestras de rechazo, pero no pude precisarlo.
Respuestas:
Debido a que hay innumerables soluciones, encontremos una eficiente .
La idea detrás de esta comienza con una forma estándar de implementar una variable de Bernoulli: compare una variable aleatoria uniforme con el parámetro . Cuando , devuelve ; de lo contrario, devuelve .a / b U < a / b 1 0
Podemos usar el -coin como un generador uniforme de números aleatorios . Para generar un número uniformemente dentro de cualquier intervalo , lanza la moneda. Cuando se trata de cabezas, genera de forma recursiva un valor uniforme en la primera parte del intervalo; cuando es cruz, genera recursivamente desde la última parte de del intervalo. En algún momento, el intervalo objetivo se volverá tan pequeño que realmente no importa cómo elija un número: así es como comienza la recursión. Es obvio que este procedimiento genera variaciones uniformes (hasta cualquier precisión deseada), como se demuestra fácilmente por inducción.[ x , y ) X p X 1 - p
Esta idea no es eficiente, pero conduce a un método eficiente. Dado que en cada etapa va a dibujar un número de un intervalo dado , ¿por qué no verifica primero si necesita dibujarlo? Si su valor objetivo se encuentra fuera de este intervalo, ya conoce el resultado de la comparación entre el valor aleatorio y el objetivo. Por lo tanto, este algoritmo tiende a terminar rápidamente. (Esto podría interpretarse como el procedimiento de muestreo de rechazo solicitado en la pregunta).
Podemos optimizar este algoritmo aún más. En cualquier etapa, en realidad tenemos dos monedas que podemos usar: al volver a etiquetar nuestra moneda podemos convertirla en una que tenga cara con la posibilidad . Por lo tanto, como una precomputación, podemos elegir recursivamente cualquier reetiquetado que conduzca al menor número esperado de volteos necesarios para la terminación. (Este cálculo puede ser un paso costoso).
Por ejemplo, es ineficiente usar una moneda con para emular directamente una variable de Bernoulli : toma casi diez lanzamientos en promedio. Pero si usamos una moneda , entonces en solo dos lanzamientos seguramente lo haremos y el número esperado de lanzamientos es solo .( 0.01 ) p = 1 - 0.0 = 0.1 1.2
Aquí están los detalles.
Particionar cualquier intervalo medio abierto en los intervalos
Esto define las dos transformaciones y que operan en intervalos de media abierta.s ( ∗ , T )
Como cuestión de terminología, si un conjunto de números reales, dejemos la expresión
significa que es un límite inferior para : para todo . Del mismo modo, significa es un límite superior para .I t < x x ∈ I t > I t I
Escribe . (De hecho, no habrá diferencia si es real en lugar de racional; solo requerimos que )t 0 ≤ t ≤ 1
Aquí está el algoritmo para producir una variante con el parámetro Bernoulli deseado:
Establezca e .I n = I 0 = [ 0 , 1 )
Mientras que {Lanza la moneda para producir . Establezca Incremento .}X n + 1 I n + 1 = S ( I n , X n + 1 ) . norte
Si , establezca . De lo contrario, establezca . Z = 1 Z = 0
Para ilustrar, aquí hay una R
implementación del aloritmo como la función draw
. Sus argumentos son el valor objetivo y el intervalo , inicialmente . Utiliza la función auxiliar que implementa . Aunque no es necesario, también rastrea el número de lanzamientos de monedas. Devuelve la variable aleatoria, el recuento de lanzamientos y el último intervalo que inspeccionó.[ x , y ) [ 0 , 1 ) ss
s <- function(x, ab, p) {
d <- diff(ab) * p
if (x == 1) c(ab[1], ab[1] + d) else c(ab[1] + d, ab[2])
}
draw <- function(target, p) {
between <- function(z, ab) prod(z - ab) <= 0
ab <- c(0,1)
n <- 0
while(between(target, ab)) {
n <- n+1; ab <- s(runif(1) < p, ab, p)
}
return(c(target > ab[2], n, ab))
}
Como ejemplo de su uso y prueba de su precisión, tome el caso y . Dibujemos valores usando el algoritmo, informemos sobre la media (y su error estándar) e indiquemos el número promedio de volteos utilizados.p = 0,9 10 , 000
target <- 0.01
p <- 0.9
set.seed(17)
sim <- replicate(1e4, draw(target, p))
(m <- mean(sim[1, ])) # The mean
(m - target) / (sd(sim[1, ]) / sqrt(ncol(sim))) # A Z-score to compare to `target`
mean(sim[2, ]) # Average number of flips
En esta simulación, de los lanzamientos eran cabezas. Aunque es inferior al objetivo de , el puntaje Z de no es significativo: esta desviación puede atribuirse al azar. El número promedio de fue de poco menos de diez. Si hubiéramos utilizado el moneda, la media habría sido --still no significativamente diferente que el objetivo, pero sólo habrían sido necesarias saltos en promedio.0.01 - 0.5154 9.886 1 - p 0.0094 1.177
Aquí hay una solución (un poco desordenada, pero es mi primera puñalada). En realidad, puede ignorar y WLOG supone 1/2 . ¿Por qué? Existe un algoritmo inteligente para generar un lanzamiento de moneda imparcial a partir de dos lanzamientos de moneda sesgados. Entonces podemos suponer que .P ( H ) = 1 / 2 P ( H ) = 1 / 2
Para generar un , puedo pensar en dos soluciones (la primera no es la mía, pero la segunda es una generalización):
Lanza la moneda imparcial veces. Si cabezas no están presentes, empezar de nuevo. Si cabezas están presentes, de retorno si la primera moneda es cara o no (porque )a a P (la primera moneda es cara | a cara en b monedas ) = a
Esto se puede extender a cualquier valor de . Escribe en forma binaria. Por ejemplo,p 0.1 = 0.0001100110011001100110011 ... base 2
Crearemos un nuevo número binario usando monedas. Comience con y agregue dígitos dependiendo de si aparece una cara (1) o una cola (0). En cada vuelta, compare su nuevo número binario con la representación binaria de hasta el mismo dígito . Eventualmente, los dos divergirán y regresarán si es mayor que su número binario.p b i n ( p )
En Python:
def simulate(p):
binary_p = float_to_binary(p)
binary_string = '0.'
index = 3
while True:
binary_string += '0' if random.random() < 0.5 else '1'
if binary_string != binary_p[:index]:
return binary_string < binary_p[:index]
index += 1
Alguna prueba:
np.mean([simulate(0.4) for i in range(10000)])
es de aproximadamente 0.4 (sin embargo, no es rápido)
Veo una solución simple, pero sin duda hay muchas formas de hacerlo, algunas presumiblemente más simples que esta. Este enfoque se puede dividir en dos pasos:
Generar a partir de dos eventos con igual probabilidad dado un procedimiento de lanzamiento de moneda injusto (la combinación de la moneda particular y el método por el cual se lanza generando una cabeza con probabilidad ). Podemos llamar a estos dos eventos igualmente probables y . [Hay un enfoque simple para esto que requiere tomar pares de lanzamientos y para producir dos resultados igualmente probables, y todos los demás resultados conducen a generar un nuevo par de rollos para intentar de nuevo.]H ∗ T ∗ H ∗ = ( H , T ) T ∗ = ( T , H )
Ahora genera una caminata aleatoria con dos estados absorbentes utilizando la moneda justa simulada. Al elegir la distancia de los estados de absorción desde el origen (uno arriba y otro debajo de él), puede establecer la posibilidad de absorción al decir que el estado de absorción superior es una relación deseada de enteros. En concreto, si coloca la barrera absorbente superior, en y la inferior a (e iniciar el proceso desde el origen), y ejecuta el paseo aleatorio hasta la absorción, la probabilidad de absorción a la barrera superior es .- ( b - a ) a
(Hay algunos cálculos que deben hacerse aquí para mostrarlo, pero puede obtener las probabilidades con bastante facilidad trabajando con relaciones de recurrencia ... o puede hacerlo sumando series infinitas ... o hay otras formas).
[self-study]
etiqueta y lea su wiki . Tenga en cuenta que no hay necesidad de pedir ayuda al final de su pregunta: ¡sabemos que todos los que publican aquí esperan ayuda!