我正在尝试使用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)
答案 0 :(得分:3)
您似乎将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)
是双变量正常,零均值和同一性协方差。
答案 1 :(得分:3)
我所有评论的来源:
Averill M. Law,W。David Kelton, Simulation Modeling and Analysis ,第三版,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
,则存在严重的困难。 1}}实际上是由线性同余生成器产生的相邻随机数。 (第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
答案 2 :(得分:0)
如果你想从倒置的CDF真正采样,那么CDF = 1/2(1 + erf(x-mu / sigma * sqrt(2)))
要反转它,你需要erf -1 (x),可以用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和分位数函数here