如果我对您的理解正确,那么您想从多项式分布中以概率采样值使,但是您希望对分布进行截断以便代表所有。p 1,... ,p ķ Σ 我X 我 = Ñ 一个我 ≤ X 我 ≤ b 我X 我x1,…,xkp1,…,pk∑ixi=nai≤xi≤bixi
我看到了三种解决方案(都不像未截断的情况那样优雅):
- 接受拒绝。来自非截断多项式的样本,如果样本符合截断边界,则接受样本,否则拒绝并重复该过程。它速度很快,但效率可能非常低。
rtrmnomReject <- function(R, n, p, a, b) {
x <- t(rmultinom(R, n, p))
x[apply(a <= x & x <= b, 1, all) & rowSums(x) == n, ]
}
- 直接模拟。以类似于数据生成过程的方式进行采样,即从随机的中采样单个大理石,并重复此过程,直到总共采样了大理石,但是当您从给定的deploy中部署大理石总数时(已经等于),然后停止从这种中抽水。我在下面的脚本中实现了这一点。X 我b 我nxibi
# single draw from truncated multinomial with a,b truncation points
rtrmnomDirect <- function(n, p, a, b) {
k <- length(p)
repeat {
pp <- p # reset pp
x <- numeric(k) # reset x
repeat {
if (sum(x<b) == 1) { # if only a single category is left
x[x<b] <- x[x<b] + n-sum(x) # fill this category with reminder
break
}
i <- sample.int(k, 1, prob = pp) # sample x[i]
x[i] <- x[i] + 1
if (x[i] == b[i]) pp[i] <- 0 # if x[i] is filled do
# not sample from it
if (sum(x) == n) break # if we picked n, stop
}
if (all(x >= a)) break # if all x>=a sample is valid
# otherwise reject
}
return(x)
}
- Metropolis算法。最后,第三种也是最有效的方法是使用Metropolis算法。通过使用直接仿真(但可以不同地初始化)以绘制第一个样本来初始化算法。在以下步骤中,反复进行:建议值以概率
接受为,否则将值取为在这里,。作为建议,我使用了函数,该函数采用值并将其从0随机翻转到个案数,并将其移至另一个类别。 Ÿ = q (X 我- 1)X 我 ˚F (Ý )/ ˚F (X 我- 1)X 我- 1个 ˚F (X )α Π 我p X 我我 / X 我!q X i − 1X1y=q(Xi−1)Xif(y)/f(Xi−1)Xi−1F(X )α Π一世pX一世一世/ x一世!qXi − 1
step
# draw R values
# 'step' parameter defines magnitude of jumps
# for Meteropolis algorithm
# 'init' is a vector of values to start with
rtrmnomMetrop <- function(R, n, p, a, b,
step = 1,
init = rtrmnomDirect(n, p, a, b)) {
k <- length(p)
if (length(a)==1) a <- rep(a, k)
if (length(b)==1) b <- rep(b, k)
# approximate target log-density
lp <- log(p)
lf <- function(x) {
if(any(x < a) || any(x > b) || sum(x) != n)
return(-Inf)
sum(lp*x - lfactorial(x))
}
step <- max(2, step+1)
# proposal function
q <- function(x) {
idx <- sample.int(k, 2)
u <- sample.int(step, 1)-1
x[idx] <- x[idx] + c(-u, u)
x
}
tmp <- init
x <- matrix(nrow = R, ncol = k)
ar <- 0
for (i in 1:R) {
proposal <- q(tmp)
prob <- exp(lf(proposal) - lf(tmp))
if (runif(1) < prob) {
tmp <- proposal
ar <- ar + 1
}
x[i,] <- tmp
}
structure(x, acceptance.rate = ar/R, step = step-1)
}
该算法从开始,然后在分布的不同区域徘徊。显然,它比以前的要快,但是您需要记住,如果使用它来采样少量案例,那么最终可能会得出彼此接近的平局。另一个问题是,您需要确定大小,即算法应进行多大的跳跃-太小可能导致移动缓慢,太大可能导致提出太多无效建议并拒绝它们。您可以在下面查看其用法示例。在图上可以看到:第一行的边际密度,第二行的轨迹图,以及显示变量对的后续跳跃的图。X1个step
n <- 500
a <- 50
b <- 125
p <- c(1,5,2,4,3)/15
k <- length(p)
x <- rtrmnomMetrop(1e4, n, p, a, b, step = 15)
cmb <- combn(1:k, 2)
par.def <- par(mfrow=c(4,5), mar = c(2,2,2,2))
for (i in 1:k)
hist(x[,i], main = paste0("X",i))
for (i in 1:k)
plot(x[,i], main = paste0("X",i), type = "l", col = "lightblue")
for (i in 1:ncol(cmb))
plot(jitter(x[,cmb[1,i]]), jitter(x[,cmb[2,i]]),
type = "l", main = paste(paste0("X", cmb[,i]), collapse = ":"),
col = "gray")
par(par.def)
从这种分布进行抽样的问题是,通常描述了一种非常低效的抽样策略。想象一下,和,和与接近,在这种情况下,您希望对具有不同概率的类别进行采样频率到底。在极端情况下,请想象两类分布,其中和,p1个≠ ⋯ ≠ pķ一个1个= ⋯ = 一个ķb1个= … bķ一个一世b一世p1个» p2一个1个« 一2b1个≪ b2,在这种情况下,您预计会发生一些非常罕见的事件(这种分布的现实示例是研究人员重复采样,直到他发现与假设相符的采样为止,因此与作弊相比,与随机采样更多有关) 。
如果将其定义为Rukhin(2007,2008),则分配问题就少得多,在该示例中,您对每个类别的案例进行抽样,即与成比例地抽样ñ p一世p一世的。
Rukhin,AL(2007)。处理分配问题中的正态统计和几何随机变量总和。统计和概率字母,77(12),1312-1321。
Rukhin,AL(2008)。平衡分配问题中的停止规则:精确分布和渐近分布。序列分析,27(3),277-292。