如何从 R 中的自定义分布 运行 monte carlo 模拟
How to run monte carlo simulation from a custom distribution in R
我想从 R 中的自定义分布中提取 1000 个样本
我有以下自定义分布
library(gamlss)
mu <- 1
sigma <- 2
tau <- 3
kappa <- 3
rate <- 1
Rmax <- 20
x <- seq(1, 2e1, 0.01)
points <- Rmax * dexGAUS(x, mu = mu, sigma = sigma, nu = tau) * pgamma(x, shape = kappa, rate = rate)
plot(points ~ x)
如何通过 Monte Carlo 模拟从这个分布中随机抽样?
我的第一次尝试是下面的代码,它产生了我没想到的直方图形状。
hist(sample(points, 1000), breaks = 51)
这不是我想要的,因为它与 pdf 不遵循相同的分布。
如果你想要一个 Monte Carlo 模拟,你需要从分布中多次抽样,而不是一次性抽取大量样本。
您的对象 points
的值随着索引增加到 400
附近的阈值而增加,趋于平稳,然后下降。这就是 plot(points ~ x)
显示的内容。它可能描述了一种分布,但 points
中值的实际分布是不同的。这显示了值在特定范围内的频率。您会注意到直方图的 x 轴类似于 plot(points ~ x)
图的 y 轴。 points
对象中值的实际分布很容易看到,它类似于您在随机采样 1000 个值时看到的情况,而无需从其中包含 1900
值的对象进行替换.这是 points
中的值分布(无需模拟):
hist(points, 100)
我特意使用了 100 个中断,这样您就可以看到一些细节。
请注意顶部尾部的小凸起,如果您希望直方图看起来像值与指数(或一些递增的 x)的关系图,您可能不会想到这一点。这意味着 points
中 2
附近的值多于 1
附近的值。看看当值在 2
左右时 plot(points ~ x)
的曲线如何变平,以及在 0.5
和 1.5
之间如何变得非常陡峭。还要注意直方图低端的大驼峰,再次查看 plot(points ~ x)
曲线。您是否看到大多数值(无论它们位于该曲线的低端还是高端)如何接近 0
,或至少小于 0.25
。如果您查看这些细节,您可能会说服自己直方图实际上正是您所期望的 :)
如果您想 Monte Carlo 模拟此对象的样本,您可以尝试类似的操作:
samples <- replicate(1000, sample(points, 100, replace = TRUE))
如果您想使用 points
作为概率密度函数生成数据,已提出并回答了该问题
您反转分布的 ECDF:
ecd.points <- ecdf(points)
invecdfpts <- with( environment(ecd.points), approxfun(y,x) )
samp.inv.ecd <- function(n=100) invecdfpts( runif(n) )
plot(density (samp.inv.ecd(100) ) )
plot(density(points) )
png(); layout(matrix(1:2,1)); plot(density (samp.inv.ecd(100) ),main="The Sample" )
plot(density(points) , main="The Original"); dev.off()
让我们将您的(未归一化的)概率密度函数定义为函数:
library(gamlss)
fun <- function(x, mu = 1, sigma = 2, tau = 3, kappa = 3, rate = 1, Rmax = 20)
Rmax * dexGAUS(x, mu = mu, sigma = sigma, nu = tau) *
pgamma(x, shape = kappa, rate = rate)
现在一种方法是使用一些MCMC(马尔可夫链Monte Carlo)方法。例如,
simMCMC <- function(N, init, fun, ...) {
out <- numeric(N)
out[1] <- init
for(i in 2:N) {
pr <- out[i - 1] + rnorm(1, ...)
r <- fun(pr) / fun(out[i - 1])
out[i] <- ifelse(runif(1) < r, pr, out[i - 1])
}
out
}
它从 init
点开始,给出 N
次平局。该方法可以在很多方面进行改进,但我只是从 init = 5
开始,包括 20000 的老化周期和 select 每秒绘制以减少重复次数:
d <- tail(simMCMC(20000 + 2000, init = 5, fun = fun), 2000)[c(TRUE, FALSE)]
plot(density(d))
这是另一种方法,它借鉴了 and :
x <- seq(1, 2e1, 0.01)
points <- 20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1)
f <- function (x) (20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1))
C <- integrate(f,-Inf,Inf)
> C$value
[1] 11.50361
# normalize by C$value
f <- function (x)
(20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1)/11.50361)
random.points <- approx(cumsum(pdf$y)/sum(pdf$y),pdf$x,runif(10000))$y
hist(random.points,1000)
hist((random.points*40),1000)
将像您的原始函数一样进行缩放。
我想从 R 中的自定义分布中提取 1000 个样本
我有以下自定义分布
library(gamlss)
mu <- 1
sigma <- 2
tau <- 3
kappa <- 3
rate <- 1
Rmax <- 20
x <- seq(1, 2e1, 0.01)
points <- Rmax * dexGAUS(x, mu = mu, sigma = sigma, nu = tau) * pgamma(x, shape = kappa, rate = rate)
plot(points ~ x)
如何通过 Monte Carlo 模拟从这个分布中随机抽样?
我的第一次尝试是下面的代码,它产生了我没想到的直方图形状。
hist(sample(points, 1000), breaks = 51)
这不是我想要的,因为它与 pdf 不遵循相同的分布。
如果你想要一个 Monte Carlo 模拟,你需要从分布中多次抽样,而不是一次性抽取大量样本。
您的对象 points
的值随着索引增加到 400
附近的阈值而增加,趋于平稳,然后下降。这就是 plot(points ~ x)
显示的内容。它可能描述了一种分布,但 points
中值的实际分布是不同的。这显示了值在特定范围内的频率。您会注意到直方图的 x 轴类似于 plot(points ~ x)
图的 y 轴。 points
对象中值的实际分布很容易看到,它类似于您在随机采样 1000 个值时看到的情况,而无需从其中包含 1900
值的对象进行替换.这是 points
中的值分布(无需模拟):
hist(points, 100)
我特意使用了 100 个中断,这样您就可以看到一些细节。
请注意顶部尾部的小凸起,如果您希望直方图看起来像值与指数(或一些递增的 x)的关系图,您可能不会想到这一点。这意味着 points
中 2
附近的值多于 1
附近的值。看看当值在 2
左右时 plot(points ~ x)
的曲线如何变平,以及在 0.5
和 1.5
之间如何变得非常陡峭。还要注意直方图低端的大驼峰,再次查看 plot(points ~ x)
曲线。您是否看到大多数值(无论它们位于该曲线的低端还是高端)如何接近 0
,或至少小于 0.25
。如果您查看这些细节,您可能会说服自己直方图实际上正是您所期望的 :)
如果您想 Monte Carlo 模拟此对象的样本,您可以尝试类似的操作:
samples <- replicate(1000, sample(points, 100, replace = TRUE))
如果您想使用 points
作为概率密度函数生成数据,已提出并回答了该问题
您反转分布的 ECDF:
ecd.points <- ecdf(points)
invecdfpts <- with( environment(ecd.points), approxfun(y,x) )
samp.inv.ecd <- function(n=100) invecdfpts( runif(n) )
plot(density (samp.inv.ecd(100) ) )
plot(density(points) )
png(); layout(matrix(1:2,1)); plot(density (samp.inv.ecd(100) ),main="The Sample" )
plot(density(points) , main="The Original"); dev.off()
让我们将您的(未归一化的)概率密度函数定义为函数:
library(gamlss)
fun <- function(x, mu = 1, sigma = 2, tau = 3, kappa = 3, rate = 1, Rmax = 20)
Rmax * dexGAUS(x, mu = mu, sigma = sigma, nu = tau) *
pgamma(x, shape = kappa, rate = rate)
现在一种方法是使用一些MCMC(马尔可夫链Monte Carlo)方法。例如,
simMCMC <- function(N, init, fun, ...) {
out <- numeric(N)
out[1] <- init
for(i in 2:N) {
pr <- out[i - 1] + rnorm(1, ...)
r <- fun(pr) / fun(out[i - 1])
out[i] <- ifelse(runif(1) < r, pr, out[i - 1])
}
out
}
它从 init
点开始,给出 N
次平局。该方法可以在很多方面进行改进,但我只是从 init = 5
开始,包括 20000 的老化周期和 select 每秒绘制以减少重复次数:
d <- tail(simMCMC(20000 + 2000, init = 5, fun = fun), 2000)[c(TRUE, FALSE)]
plot(density(d))
这是另一种方法,它借鉴了
x <- seq(1, 2e1, 0.01)
points <- 20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1)
f <- function (x) (20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1))
C <- integrate(f,-Inf,Inf)
> C$value
[1] 11.50361
# normalize by C$value
f <- function (x)
(20*dexGAUS(x,mu=1,sigma=2,nu=3)*pgamma(x,shape=3,rate=1)/11.50361)
random.points <- approx(cumsum(pdf$y)/sum(pdf$y),pdf$x,runif(10000))$y
hist(random.points,1000)
hist((random.points*40),1000)
将像您的原始函数一样进行缩放。