我在多项分布中将贝叶斯估计量与MLE进行比较。我使用
从特定的多项分布中使用rmultinom绘制随机样本rmultinom(400, size = 30, prob = c(5,7,10,8,14,10,15,12,10,9))
对于400个样本中的每一个,我计算10个概率参数的MLE和Bayes估计量。我现在想要找出真实分布与估算者定义的分布之间的总变差距离。
由于30号和10号箱的可能安排超过2亿,我认为使用理论定义并不是一个好主意。
包distrEx有一个函数“TotalVarDist()”,但它只能用于distr包中定义的分发,而多项不是其中之一。有定义它们的方向(参见here和here),但选项要么通过明确列出支持来定义离散分布(再次,我不认为这是一个很好的选择,因为支持的大小超过2亿)或者从头开始使用与创建distr包相同的方法,这超出了我目前的能力。
关于如何使用所提到的包或以完全不同的方式做任何想法?
答案 0 :(得分:1)
我的回答是关于如何使用基数R来计算它。
我们有两个多项参数矢量,θ和η。总变差距离相当于P_θ(E) - P_η(E),其中 E = {ω| P_θ({ω})>P_η({ω})} ,ω是样本计数的向量。
我知道有两种方法来评估基础R中的 P(E)。一种是一种非常简单的基于模拟的方法。另一个根据计数的线性组合(大致正态分布)重新解决问题,并使用pnorm
函数。
您可以模拟每个分布中的样本,使用概率质量函数检查它们是否在 E 中,并计算它们的频率。我将在这里举一个例子。我们将假设你问题的真实分布:
unnormalized.true <- c(5,7,10,8,14,10,15,12,10,9)
true <- unnormalized.true / sum(unnormalized.true)
我们将使用贝叶斯估计器绘制样本并估计新分布:
set.seed(921)
result <- as.vector(rmultinom(1, size = 30, prob = true))
result
## [1] 3 6 2 0 5 3 3 4 1 3
dirichlet <- (result+1)/(30+length(true))
计算真实分布下 E 的概率:
set.seed(939)
true.dist <- rmultinom(10^6, 30, true)
p.true.e <- mean(apply(true.dist, 2, function(x)
dmultinom(x, 30, true) - dmultinom(x, 30, dirichlet) > 0))
根据贝叶斯估计量的估计分布计算 E 的概率:
dirichlet.dist <- rmultinom(10^6, 30, dirichlet)
p.dirichlet.e <- mean(apply(dirichlet.dist, 2, function(x)
dmultinom(x, 30, true) - dmultinom(x, 30, dirichlet) > 0))
我们可以减去总变差距离。
p.true.e - p.dirichlet.e
## [1] 0.83737
用最大似然估计重复这一点,我们得到了估计量的比较。
mle <- result/30
mle.dist <- rmultinom(10^6, 30, mle)
p.true.e2 <- mean(apply(true.dist, 2, function(x)
dmultinom(x, 30, true) - dmultinom(x, 30, mle) > 0))
p.mle.e2 <- mean(apply(mle.dist, 2, function(x)
dmultinom(x, 30, true) - dmultinom(x, 30, mle) > 0))
p.true.e2 - p.mle.e2
## [1] 0.968301
(编辑以解决一个严重的错误。之前我在与MLE的比较中重新使用了p.true.e
。我忘了事件 E 是根据估计的分布来定义的。)
我认为这种方法实际上比基于模拟的方法更准确,尽管有正常的近似值。正如您将看到的,我们没有对多项计数进行正态近似,这对于 n = 30 来说不太准确。我们对这些计数的线性组合进行了正态近似,这与正常情况接近。这种方法的弱点将证明它无法处理估计分布中的零概率。这是一个真正的问题,因为对我来说优雅地处理零是使用总变差距离而不是Kullback-Leibler散度的一部分。但就是这样。
以下推导产生 E 的重述:
定义
其中 N_i 是多项式样本的一个单元格,
然后, E 是 L&gt; 0 的事件。
我们遇到零概率问题的原因是它导致λ_i中的一个是无限的。
我想验证 L 接近正态分布,在前面的示例中。我将通过使用先前的多项式模拟从 L 的分布中获取样本来做到这一点:
lambda <- log(true/dirichlet)
L.true.dist <- apply(true.dist, 2, function(x) sum(lambda*x))
L.dirichlet.dist <- apply(dirichlet.dist, 2, function(x) sum(lambda*x))
请注意,我正在对真实分布和贝叶斯估计分布进行比较。我不能用MLE做一个,因为我的样本没有计数。
绘制 L 的分布并与正常拟合进行比较:
par(mfrow=c(1,2))
L.true.dist.hist <- hist(L.true.dist)
L.true.dist.fit <- function(x)
length(L.true.dist) * diff(L.true.dist.hist$breaks)[1] *
dnorm(x, mean(L.true.dist), sd=sd(L.true.dist))
curve(L.true.dist.fit, add=TRUE, n=1000, col='red')
L.dirichlet.dist.hist <- hist(L.dirichlet.dist)
L.dirichlet.dist.fit <- function(x)
length(L.dirichlet.dist) * diff(L.dirichlet.dist.hist$breaks)[1] *
dnorm(x, mean(L.dirichlet.dist), sd=sd(L.dirichlet.dist))
curve(L.dirichlet.dist.fit, add=TRUE, n=1000, col='red')
par(mfrow=c(1,1))
L 的分布似乎正常。因此,我们可以使用pnorm
而不是使用模拟。但是,我们需要计算 L 的平均值和标准差。这可以按如下方式完成。
L 的平均值是
其中 p_i 是分布 p 中单元格 i 的单元格概率。方差是
,其中
是多项分布的协方差矩阵。我将为这个例子计算这些时刻,并根据模拟中的经验时刻进行检查。首先,在真实分布下分配 L :
n <- 30
k <- length(true)
mean.L.true <- sum(lambda * n * true)
# Did we get the mean right?
c(mean.L.true, mean(L.true.dist))
## [1] 3.873509 3.875547
# Covariance matrix assuming the true distribution
sigma.true <- outer(1:k, 1:k, function(i,j)
ifelse(i==j, n*true[i]*(1-true[i]), -n*true[i]*true[j]))
var.L.true <- t(lambda) %*% sigma.true %*% lambda
# Did we get the standard deviation right?
c(sqrt(var.L.true), sd(L.true.dist))
## [1] 2.777787 2.776945
然后,贝叶斯估计分布下 L 的均值和方差:
mean.L.dirichlet <- sum(lambda * n * dirichlet)
# Did we get the mean right?
c(mean.L.dirichlet, mean(L.dirichlet.dist))
## [1] -3.893836 -3.895983
# Covariance matrix assuming the estimated distribution
sigma.dirichlet <- outer(1:k, 1:k, function(i,j)
ifelse(i==j, n*dirichlet[i]*(1-dirichlet[i]), -n*dirichlet[i]*dirichlet[j]))
var.L.dirichlet <- t(lambda) %*% sigma.dirichlet %*% lambda
# Did we get the standard deviation right?
c(sqrt(var.L.dirichlet), sd(L.dirichlet.dist))
## [1] 2.796348 2.793421
有了这些,我们可以用pnorm
计算总变差距离:
pnorm(0, mean.L.true, sd=sqrt(var.L.true), lower.tail=FALSE) -
pnorm(0, mean.L.dirichlet, sd=sqrt(var.L.true), lower.tail=FALSE)
## [1] 0.8379193
# Previous result was 0.83737
我们得到三位数字的模拟协议。
我不知道有任何简单的方法来扩展常规逼近方法来处理零概率。我有一个想法,但我试图计算条件的协方差矩阵,条件是具有0计数的特定单元格。如果你认为你可以做些什么,我可以分享我的进步。