我试图在[0.005,0.008]范围内生成100个均匀随机数,总和为1。我正在寻找几个与我的担忧有关的问题,但我找不到答案。 有人能给我一个建议吗?
答案 0 :(得分:3)
首先,我将略微修改你的例子,假设100个变量以[0.008,0.012]为界,并且它们总和为1(这确保了你在集合中有可行点)。重新抽样)。
"hit and run" algorithm在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
参数来减少运行时间,但这可能会影响绘制的独立性。
答案 1 :(得分:1)
我的想法是逐步生成随机数。在每一步中,要注意剩余的金额不会变大,也不会变小。在最后一步中,随机排列这些随机数:
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
- 循环,但它是一个基本的R解决方案,它似乎有效。
> sum(X)
[1] 1
> min(X)
[1] 0.00801727
> max(X)
[1] 0.01199241
> plot(X)
分布并不完全,但几乎是一致的。我重复了5000次计算并将第n个样本存储在X[,n]
:
所有职位在一起:
在下限和上限附近,频率增加,但在界限之间的其余区间,它几乎是恒定的。
这是一个如何使分布更均匀的想法: 在下边界和上边界附近组合一些数字并“将它们扔到中间”:
x1
,在上边界附近选择x2
。它们的平均值大约是间隔的中心。y
,使y
和x1+x2-y
包含在间隔中。x1
和x2
替换为y
和x1+x2-y
。答案 2 :(得分:1)
如果没有关于这些数字将用于什么的更多信息,问题就不明确了。通过探讨一些较低维度的例子,我们可以看到什么&#34;制服&#34;不幸的是,这里意味着含糊不清。如果计划将其用于某种基于蒙特卡罗的模拟,那么您获得的结果很可能没用。
让我们查看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')
这个问题只会随着尺寸的增加而变得更糟。 &#34;总结为1&#34;要求具有将采样限制为N-1维超平面的效果,并且单个组件约束用于将可行子集雕刻成多面体(基于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)
总之,如果不了解使用意图的含义,这个问题要比合理解决起来要困难得多。
答案 3 :(得分:0)
这是一个经过修改的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