簡體   English   中英

生成N個統一隨機數,總和為1

[英]Generate N uniform random numbers with sum of one

我正在嘗試生成100個范圍為[0.005,0.008]的統一隨機數,總和為1。 我一直在尋找與自己的擔憂相關的幾個問題,但沒有找到答案。 有人可以給我一個建議嗎?

首先,我將稍微修改您的示例,假設100個變量以[0.008,0.012]為界,並且它們的總和為1(這可以確保您要采樣的集合中有可行的點)。

“命中並運行”算法在n維空間的有界子集中統一采樣。 對於您的情況,我們有n = 100個尺寸; 讓我們定義相應的變量x_1, x_2, ..., x_100 然后,我們有三種類型的約束來限制我們要從中采樣的空間區域。

變量的下限為0.008-可以通過以下線性不等式捕獲:

x_1 >= 0.008
x_2 >= 0.008
...
x_100 >= 0.008

變量的上限為0.012-可以通過以下線性不等式捕獲:

x_1 <= 0.012
x_2 <= 0.012
...
x_100 <= 0.012

變量的總和為1-可以通過以下方式捕獲:

x_1 + x_2 + ... + x_100 = 1

假設我們要獲取10組在我們的空間內均勻分布的變量。 然后,我們可以通過以下方式在R中使用hitandrun軟件包:

library(hitandrun)
n <- 100
lower <- 0.008
upper <- 0.012
s <- 1
constr <- list(constr = rbind(-diag(n), diag(n), rep(1, n), rep(-1, n)),
               dir = rep("<=", 2*n+2),
               rhs = c(rep(-lower, n), rep(upper, n), s, -s))
samples <- hitandrun(constr, n.samples=10)
dim(samples)
# [1]  10 100

請注意,這要花很長時間(在我的情況下,不到2小時),因為我們是在高維空間(尺寸n = 100)中進行采樣,並且要確保均勻采樣,命中並運行算法實際上會執行O (n ^ 3)次迭代,繪制每個樣本。 您可以通過調整函數的thin參數來減少運行時間,盡管這可能會影響繪制的獨立性。

我的想法是逐步生成隨機數。 在每個步驟中,請注意剩余的總和不要太小。 在最后一步中,這些隨機數被隨機排列:

N <- 100

lowerBound <- 0.008
upperBound <- 0.012
Sum        <- 1

X <- rep(NA,N)
remainingSum <- Sum

for (i in 1:(N-1))
{
  a <- max( lowerBound, remainingSum-(N-i)*upperBound )
  b <- min( upperBound, remainingSum-(N-i)*lowerBound )

  A <- ceiling(1e+8*a)
  B <- floor(1e+8*b)

  X[i] <- ifelse( A==B, A, sample(A:B,1)) / 1e+8

  remainingSum <- remainingSum - X[i]
}

X[N] <- remainingSum

X <- sample(X,N)

對於for -loop很抱歉,但這是基本的R解決方案,它似乎可以正常工作。

> sum(X)
[1] 1
> min(X)
[1] 0.00801727
> max(X)
[1] 0.01199241
> plot(X)

在此處輸入圖片說明

分布不完全相同,但是幾乎是均勻的。 我重復了5000次計算,並將第n個樣本存儲在X[,n]

在此處輸入圖片說明 在此處輸入圖片說明 在此處輸入圖片說明

所有職位加在一起:

在此處輸入圖片說明

在下限和上限附近,頻率增加,但是在下限之間的其余間隔中,該頻率幾乎恆定。

這是一個使分布更加均勻的想法:組合上下邊界附近的一些數字並將它們“扔到中間”:

  • 在下邊界附近選擇x1 ,在上邊界附近選擇x2 它們的平均值將大約是間隔的中心。
  • 繪制一個隨機數y ,以使yx1+x2-y包含在間隔中。
  • yx1+x2-y替換x1x2
  • 重復直到邊界的峰消失。

沒有有關這些數字將用於什么目的的更多信息,問題就很模糊。 通過研究一些較低維的示例,我們可以看到“統一”在這里的含義很模糊。 如果計划將其用於基於蒙特卡洛的某種模擬,則獲得的結果很可能不會有用。

讓我們看一下n=4 ,約束[210,300]且總數為1000

我們生成(效率低下)與標准相符的所有離散值的詳盡列表

values <- 210:300
df <- subset(expand.grid(a=values, b=values, c=values, d=values), a+b+c+d==1000)

由於對稱,a,b,c和d的分布將相同。 分布看起來像

> plot(prop.table(table(df$a)), type='l')

單變量分布

隨着尺寸的增加,這個問題只會變得更糟。 “求和為1”的要求具有將采樣限制為N-1維超平面的效果,並且各個分量約束用於將可行的子集雕刻為多面體(基於N維超立方體與N維超立方體的交集)。平面嵌入N空間)。

在3維中,子空間看起來像是平面和立方體的交點; 中間是六邊形,兩端是三角形。 通過查看前兩個主要成分的圖即可輕松進行驗證

> values <- 100:150; df <- subset(expand.grid(a=values, b=values, c=values), a + b + c==370); df2 <- as.data.frame(predict(princomp(df)))
> plot(df2$Comp.1, df2$Comp.2)

結果的主成分分析

總而言之,在沒有某種使用意圖的知識的情況下,解決該問題比看起來要困難得多。

這是基於Metropolis-Hastings的改進解決方案。 請注意,由於您的限制,我還沒有達到收斂; 但是,它非常接近:

simple_MH <- function(n= 100, low= 0.005, up= 0.02, max_iter= 1000000) {
  x <- runif(n, low, up)
  sum_x <- sum(x)
  iter <- 0

  if (sum_x == 1) return(x)
  else {
    while (sum_x != 1 & iter < max_iter) {
      iter <- iter + 1
      if (sum_x > 1) {
        xt <- sample(which(x > mean(x)), 1)  
      } else {
        xt <- sample(which(x < mean(x)), 1)
      }

      propose <- runif(1, low, up)
      d_prop <- dnorm(propose, 1 / n, sqrt(1/12 *(up - low)^2))
      d_xt   <- dnorm(x[xt], 1 / n, sqrt(1/12 *(up - low)^2))
      alpha <- d_prop / d_xt

      if (alpha >= 1) {
        x[xt] <- propose
        sum_x <- sum(x)
      } else {
        acc <- sample(c(TRUE, FALSE), 1, prob= c(alpha, 1-alpha))
        if (acc) {
          x[xt] <- propose
          sum_x <- sum(x)
        }
      }
    }
  }
  return(list(x=x, iter= iter))
}

# try it out:
test <- simple_MH() # using defaults (note not [0.005, 0.008])
test2 <- simple_MH(max_iter= 5e6)
R> sum(test[[1]]) # = 1.003529
R> test[[2]] # hit max of 1M iterations
R> sum(test2[[1]]) # = 0.9988
R> test2[[2]] # hit max of 5M iterations

暫無
暫無

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

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