Random-Generation
如何有效地在區間內生成排序均勻分佈的值?
假設我想從區間生成一組隨機數
(a, b)
。生成的序列還應該具有已排序的屬性。我可以想到兩種方法來實現這一點。令
n
為要生成的序列的長度。第一種算法:
Let `offset = floor((b - a) / n)` for i = 1 up to n: generate a random number r_i from (a, a+offset) a = a + offset add r_i to the sequence r
第二種算法:
for i = 1 up to n: generate a random number s_i from (a, b) add s_i to the sequence s sort(r)
我的問題是,算法 1 生成的序列是否與算法 2 生成的序列一樣好?
第一個算法嚴重失敗有兩個原因:
- 發言可以大幅度減少。確實,當,它將為零,為您提供一個值都相同的集合!
- 當您不發言時,結果值分佈過於均勻。 例如,在任何簡單的隨機樣本中iid 統一變量(比如在和),有一個最大的可能不在上區間到. 對於算法 1,有一個最大值將在該區間內的機會。出於某些目的,這種超均勻性是好的,但總的來說,這是一個可怕的錯誤,因為 (a) 許多統計數據會被破壞,但 (b) 很難確定原因。
- 如果要避免排序,請改為生成獨立的指數分佈變量。將它們的累積總和標準化為範圍除以總和。刪除最大值(這將始終是)。重新縮放到範圍.
顯示了所有三種算法的直方圖。(每個描述的累積結果獨立組每個值。)算法 1 的直方圖中沒有任何可見的變化表明了那裡的問題。其他兩種算法的變化正是可以預期的——以及隨機數生成器所需要的。
有關模擬獨立均勻變量的更多(有趣)方法,請參閱使用正態分佈的繪圖模擬均勻分佈的繪圖。
這是
R
生成該圖的代碼。b <- 1 a <- 0 n <- 100 n.iter <- 1e3 offset <- (b-a)/n as <- seq(a, by=offset, length.out=n) sim.1 <- matrix(runif(n.iter*n, as, as+offset), nrow=n) sim.2 <- apply(matrix(runif(n.iter*n, a, b), nrow=n), 2, sort) sim.3 <- apply(matrix(rexp(n.iter*(n+1)), nrow=n+1), 2, function(x) { a + (b-a) * cumsum(x)[-(n+1)] / sum(x) }) par(mfrow=c(1,3)) hist(sim.1, main="Algorithm 1") hist(sim.2, main="Algorithm 2") hist(sim.3, main="Exponential")