[英]generate N(0,1) using uniform(0,1) in R
我正在尝试使用uniform(0,1)生成N(0,1)进行仿真,但是无法运行代码。
首先,通过使X成为正常CDF的主题,然后找出直方图来找到我的x。 接下来,施加法线以查看其是否适合。 下面是我的代码。
sigma=1; mu=0
u<-runif(n)
x<-mu + sqrt(2*sigma(log(u*sigma*sqrt(2*pi))))
hist(x, Freq=F)
xpt<-seq(-5,5,0.1)
ypt<-dnorm(xpt,0,1)
lines(xpt,ypt,col=2)
您似乎倒置了PDF(概率密度函数)而不是CDF(累积密度函数)。
实际上,反型CDF不会生成正态随机变量,因为其CDF并不是封闭形式。
查看Box-Muller变换 。 您模拟两组独立的统一随机变量:
u <- runif(1000)
v <- runif(1000)
x <- sqrt(-2 * log(u)) * cos(2 * pi * v)
# y <- sqrt(-2 * log(u)) * sin(2 * pi * v)
然后x
来自N(0, 1)
, (x, y)
是二元正态,均值和恒等协方差为零。
我所有评论的来源:
Averill M. Law,W。David Kelton,《 模拟建模与分析》 ,第三版,McGraw-Hill,2000年。ISBN:0-07-058290-4
可以通过生成两个U(0,1)随机变量来使用Box-Muller变换。
`x1 = sqrt(-2 * log(u1)) * cos(2 * pi * u2)`
`x2 = sqrt(-2 * log(u1)) * sin(2 * pi * u2)`
概括如下:
box_muller <- function(n = 1, mean = 0, sd = 1)
{
x <- vector("numeric", n)
i <- 1
while(i <= n)
{
u1 <- runif(1, 0, 1)
u2 <- runif(1, 0, 1)
x[i] <- sqrt(-2 * log(u1)) * cos(2 * pi * u2)
if ((i + 1) <= n)
{
x[i + 1] <- sqrt(-2 * log(u1)) * sin(2 * pi * u2)
i <- i + 1
}
i <- i + 1
}
x * sd + mean
}
hist(box_muller(1000))
但是请注意,
尽管该方法在原理上是有效的,即如果
U1
和U2
确实是IID U(0,1)随机变量,但是如果U1
和U2
实际上是由线性同余生成器生成的相邻随机数,则存在严重的困难。 (第465页)
Marsaglia Bray极地方法
此方法分为两步,其中
- 生成
U1
和U2
作为IID U(0,1); 令V[i] = 2 * U[i] - 1
因为i = 1,2 ; 令W = V[1]^2 + V[2]^2
。- 如果
W > 1
,则返回步骤1。否则,让Y = sqrt(-2 log(W)/W)
,X[1] = V[1] * Y
,而X[2] = V2 * Y
然后X[1]
和X[2]
是IID N(0,1)个随机变量。 (第466页)
执行:
marsaglia_bray <- function(n = 1, mean = 0, sd = 1)
{
x <- vector("numeric", n)
i <- 1
while(i <= n)
{
u <- runif(2, 0, 1)
v <- 2 * u - 1
w <- sum(v^2)
if (w < 1)
{
y <- sqrt(-2 * log(w) / w)
z <- v * y
x[i] <- z[1]
if ((i + 1) <= n)
{
x[i + 1] <- z[2]
i <- i + 1
}
i <- i + 1
}
}
x * sd + mean
}
hist(marsaglia_bray(1000))
您也可以考虑使用Ziggurat Alogrithm
如果要从反转CDF中真正采样,则CDF = 1/2(1 + erf(x-mu / sigma * sqrt(2)))
要反转它,您需要erf -1 (x),可以使用qnorm
表示qnorm
。 沿线
erfinv <- function (x) {
qnorm((1.0 + x)/2.0)/sqrt(2.0)
}
sample <- function(U01, mu, sigma) {
N01 = sqrt(2.0) * erfinv( 2.0 * U01 - 1.0 )
mu + sigma*N01
}
n = 10
u <- runif(n)
q <- sample(u, 0.0, 1.0)
print(u)
print(q)
在这里检查CDF和分位数功能
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.