为帕累托分布编程逆变换采样

机器算法验证 分布 数理统计 帕累托分布
2022-04-14 05:40:29

我在推导公式以及使用其分布运行模拟时遇到问题。帕累托分布有 CDF:

F(x)=1(kx)γfor xk,

其中k>0是尺度参数,γ>0是形状参数。我需要导出概率逆变换“分位数”:

X=F1(U)=Q(U).

我尝试推导方程并最终得到X=k/gammaroot(1U)那有意义吗?如果是这样,我将如何在中执行gammaroot函数R

2个回答

我假设您正在参考逆变换采样方法。它非常直截了当。请参阅Wiki文章和此站点

帕累托 CDF 由下式给出:

F(X)=1(kx)γ;xk>0 and γ>0

您所做的就是等同于均匀分布并求解x

F(X)=UUUniform(0,1)1(kx)γ=ux=k(1u)1/γ

现在在 R 中:


#N = number of samples
#N = number of sample
rpar <- function(N,g,k){
  
  if (k < 0 | g <0){
    stop("both k and g >0")
  }
  
 k*(1-runif(N))^(-1/g)
}


rand_pareto <- rpar(1e5,5, 16)
hist(rand_pareto, 100, freq = FALSE)

#verify using built in random variate rpareto in package extrDistr
x <- (extraDistr::rpareto(1e5,5, 16))
hist(x, 100, freq = FALSE)

rand_parero 的直方图

从包 ExtraDsitribution 生成的直方图 fir x

这将为您提供帕累托分布的随机变量。我不确定你在哪里得到gammaroot

使用分位数并反转 CDF 方程给出分位数函数:p=F(x)

Q(p)=k(1p)1/γfor all 0p1.

对应的对数分位数函数为:

logQ(p)=logk1γlog(1p)for all 0p1.

帕累托分布的概率函数已经在R(参见例如EnvStats)中可用。然而,如果愿意的话,从头开始编程这个函数是相当简单的。这是该函数的矢量化版本。

qpareto <- function(p, scale, shape = 1, lower.tail = TRUE, log.p = FALSE) {
  
  #Check input p
  if (!is.vector(p))                { stop('Error: p must be a numeric vector') }
  if (!is.numeric(p))               { stop('Error: p must be a numeric vector') }
  if (min(p) < 0)                   { stop('Error: p must be between zero and one') }
  if (max(p) > 1)                   { stop('Error: p must be between zero and one') }
  
  n   <- length(p)
  OUT <- numeric(n)
  for (i in 1:n) { 
    P      <- ifelse(lower.tail, 1-p[i], p[i])
    OUT[i] <- log(scale) - log(P)/shape) }
  
   if (log.p) OUT else exp(OUT) }

一旦有了 quantile 函数,就很容易使用逆变换采样生成随机变量。同样,这已经在 中的现有 Pareto 函数中完成R,但如果您想从头开始编程,这很简单。

rpareto <- function(n, scale, shape = 1) {
  
  #Check input n
  if (!is.vector(n))                { stop('Error: n must be a single positive integer') }
  if (!is.numeric(n))               { stop('Error: n must be a single positive integer') }
  if (length(n) != 1)               { stop('Error: n must be a single positive integer') }
  if (as.integer(n) != n)           { stop('Error: n must be a single positive integer') }
  if (n <= 0)                       { stop('Error: n must be a single positive integer') }
  
  qpareto(runif(n), scale = scale, shape = shape) }