簡體   English   中英

嘗試使用逆 CDF 方法模擬泊松樣本,但我的 R 函數會產生錯誤的結果

[英]Trying to simulate Poisson samples using inverse CDF method but my R function produces wrong results

我寫了一些R代碼來模擬泊松分布中的隨機樣本,基於算法的描述(見附圖)。 但是我的代碼似乎無法正常工作,因為生成的隨機樣本與R的內置rpois()函數生成的隨機樣本具有不同的模式。 誰能告訴我我做錯了什么以及如何修復我的功能?

r.poisson <- function(n, l=0.5)
{
  U <- runif(n)
  X <- rep(0,n)
  p=exp(-l)
  F=p
  for(i in 1:n)
  {
    if(U[i] < F)
    {
      X[i] <- i
    } else
    {
      p=p*l/(i+1)
      F=F+p
      i=i+1
    }
  }
  return(X)
}

r.poisson(50)

輸出與rpois(50, lambda = 0.5)非常不同。 我遵循的算法是:

算法

(謝謝您的提問。現在我知道如何模擬泊松隨機變量了。)

你誤會了。 您引用的逆 CDF 方法(使用遞歸計算)用於生成單個泊松隨機樣本。 所以你需要修復這個函數來產生一個數字。 這是正確的功能,注釋以幫助您遵循每個步驟。

rpois1 <- function (lambda) {
  ## step 1
  U <- runif(1)
  ## step 2
  i <- 0
  p <- exp(-lambda)
  F <- p
  ## you need an "infinite" loop
  ## no worry, it will "break" at some time
  repeat {
    ## step 3
    if (U < F) {
      X <- i
      break
    }
    ## step 4
    i <- i + 1
    p <- lambda * p * i
    F <- F + p
    ## back to step 3
  }
  return(X)
}

現在要獲取n樣本,您需要調用此函數n次。 R有一個很好的函數,稱為replicate ,可以多次重復一個函數。

r.poisson <- function (n, lambda) {
  ## use `replicate()` to call `rpois1` n times
  replicate(n, rpois1(lambda))
}

現在我們可以與R自己的rpois進行合理的比較。

x1 <- r.poisson(1000, lambda = 0.5)
x2 <- rpois(1000, lambda = 0.5)

## set breaks reasonably when making a histogram
xmax <- max(x1, x2) + 0.5
par(mfrow = c(1, 2))
hist(x1, main = "proof-of-concept-implementation", breaks = seq.int(-0.5, xmax))
hist(x2, main = "R's rpois()", breaks = seq.int(-0.5, xmax))

歷史

矢量化版本將比使用replicate的非矢量化函數運行得快得多。 這個想法是隨着i的增加迭代地丟棄均勻的隨機樣本。

r.poisson1 <- function(n, l = 0.5) {
  U <- runif(n)
  i <- 0L
  X <- integer(n)
  p <- exp(-l)
  F <- p
  idx <- 1:n
  while (length(idx)) {
    bln <- U < F
    X[idx[bln]] <- i
    p <- l*p/(i <- i + 1L)
    F <- F + p
    idx <- idx[!bln]
    U <- U[!bln]
  }
  X
}

@Zheyuan Li 的非向量化函數:

rpois1 <- function (lambda) {
  ## step 1
  U <- runif(1)
  ## step 2
  i <- 0
  p <- exp(-lambda)
  F <- p
  ## you need an "infinite" loop
  ## no worry, it will "break" at some time
  repeat {
    ## step 3
    if (U < F) {
      X <- i
      break
    }
    ## step 4
    i <- i + 1
    p <- lambda * p * i
    F <- F + p
    ## back to step 3
  }
  return(X)
}

r.poisson2 <- function (n, lambda) {
  ## use `replicate()` to call `rpois1` n times
  replicate(n, rpois1(lambda))
}

基准:

microbenchmark::microbenchmark(r.poisson1(1e5),
                               r.poisson2(1e5, 0.5),
                               rpois(1e5, 0.5))
#> Unit: milliseconds
#>                    expr        min         lq       mean     median         uq        max neval
#>       r.poisson1(1e+05)   3.063202   3.129151   3.782200   3.225402   3.734600  18.377700   100
#>  r.poisson2(1e+05, 0.5) 217.631002 244.816601 269.692648 267.977001 287.599251 375.910601   100
#>       rpois(1e+05, 0.5)   1.519901   1.552300   1.649026   1.579551   1.620451   7.531401   100

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM