Encontrando uma maneira de simular números aleatórios para esta distribuição


20

Eu estou tentando escrever um programa em R que simula números pseudo-aleatórios de uma distribuição com a função de distribuição cumulativa:

F(x)=1exp(axbp+1xp+1),x0

ondea,b>0,p(0,1)

Tentei amostragem por transformada inversa, mas a inversa não parece analiticamente solucionável. Ficaria feliz se você pudesse sugerir uma solução para este problema


1
Não há tempo suficiente para uma resposta completa, mas você pode verificar os algoritmos do Importance Sampling, como alternativa.
chuse

1
não é um exercício de manual, apenas estipulei a restrição porque é uma suposição razoável para meus dados
Sebastian

6
Surpreende-me então a normalização "milagrosa" de (p+1)1 que transforma a distribuição em um poder perfeito de um exponencial, mas milagres acontecem (com pequena probabilidade).
Xian

Respostas:


49

Existe uma solução direta (e, se for o caso, elegante) para este exercício: como aparece como um produto de duas distribuições de sobrevivência: a distribuição é a distribuição de Nesse caso, é a distribuição exponencial e é o -ésimo poder de uma distribuição Exponencial .1F(x)

(1F(x))=exp{axbp+1xp+1}=exp{ax}1F1(x)exp{bp+1xp+1}1F2(x)
F
X=min{X1,X2}X1F1,X2F2
F1E(a)F21/(p+1)E(b/(p+1))

O código R associado é o mais simples possível

x=pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))) #simulating an n-sample

e é definitivamente muito mais rápido que o pdf inverso e as resoluções de aceitação e rejeição:

> n=1e6
> system.time(results <- Vectorize(simulate,"prob")(runif(n)))
utilisateur     système      écoulé 
    89.060       0.072      89.124 
> system.time(x <- simuF(n,1,2,3))
utilisateur     système      écoulé 
     1.080       0.020       1.103 
> system.time(x <- pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))))
utilisateur     système      écoulé 
     0.160       0.000       0.163 

com um ajuste surpreendentemente perfeito:

insira a descrição da imagem aqui


5
solução muito legal!
Sebastian

14

Você sempre pode resolver numericamente a transformação inversa.

Abaixo, faço uma pesquisa de bissecção muito simples. Para uma dada probabilidade de entrada (eu uso desde que você já tenha um em sua fórmula), começo com e . Então até . Por fim, iterativamente o intervalo até que seu comprimento seja menor que e seu ponto médio satisfaça .qqpxL=0xR=1xRF(xR)>q[xL,xR]ϵxMF(xM)q

O ECDF se adequa ao seu bem o suficiente para minhas escolhas de e , e é razoavelmente rápido. Você provavelmente poderia acelerar isso usando alguma otimização do tipo Newton, em vez da simples pesquisa de bissecção.Fab

aa <- 2
bb <- 1
pp <- 0.1

cdf <- function(x) 1-exp(-aa*x-bb*x^(pp+1)/(pp+1))

simulate <- function(prob,epsilon=1e-5) {
    left <- 0
    right <- 1
    while ( cdf(right) < prob ) right <- 2*right

    while ( right-left>epsilon ) {
        middle <- mean(c(left,right))
        value_middle <- cdf(middle)
        if ( value_middle < prob ) left <- middle else right <- middle
    }

    mean(c(left,right))
}

set.seed(1)
results <- Vectorize(simulate,"prob")(runif(10000))
hist(results)

xx <- seq(0,max(results),by=.01)
plot(ecdf(results))
lines(xx,cdf(xx),col="red")

ECDF


10

Existe uma resolução um tanto complicada, se direta, por aceitação-rejeição. Primeiro, uma diferenciação simples mostra que o pdf da distribuição é Segundo, uma vez que temos o limite superior Terceiro, considerando o segundo termo em , faça a alteração da variável , ou seja, . Então é o jacobiano da mudança de variável. Se

f(x)=(a+bxp)exp{axbp+1xp+1}
f(x)=aeaxebxp+1/(p+1)1+bxpebxp+1/(p+1)eax1
f(x)g(x)=aeax+bxpebxp+1/(p+1)
gξ=xp+1x=ξ1/(p+1)
dxdξ=1p+1ξ1p+11=1p+1ξpp+1
Xtem uma densidade na forma que é a constante de normalização, então tem a densidade que significa que (i) é distribuído como uma variável exponencial e (ii) a constante é igual a um. Portanto, acaba sendo igual à mistura igualmente ponderada de uma distribuição Exponential e a -ésima potência de uma Exponentialκbxpebxp+1/(p+1)κΞ=X1/(p+1)
κbξpp+1ebξ/(p+1)1p+1ξpp+1=κbp+1ebξ/(p+1)
ΞE(b/(p+1))κg(x)E(a)1/(p+1)E(b/(p+1))distribuição, module uma constante multiplicativa ausente de para explicar os pesos: E é simples de simular como uma mistura.2
f(x)g(x)=2(12aeax+12bxpebxp+1/(p+1))
g

Uma renderização R do algoritmo de aceitação-rejeição é assim

simuF <- function(a,b,p){
  reepeat=TRUE
  while (reepeat){
   if (runif(1)<.5) x=rexp(1,a) else
      x=rexp(1,b/(p+1))^(1/(p+1))
   reepeat=(runif(1)>(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
      (a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1))))}
  return(x)}

e para uma n-amostra:

simuF <- function(n,a,b,p){
  sampl=NULL
  while (length(sampl)<n){
   x=u=sample(0:1,n,rep=TRUE)
   x[u==0]=rexp(sum(u==0),b/(p+1))^(1/(p+1))
   x[u==1]=rexp(sum(u==1),a)
   sampl=c(sampl,x[runif(n)<(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
      (a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1)))])
   }
  return(sampl[1:n])}

Aqui está uma ilustração para a = 1, b = 2, p = 3:

insira a descrição da imagem aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.