贝叶斯等效的两个样本t检验?


39

我不是在寻找R中的BEST的即插即用方法,而是在数学上解释可以用来测试两个样本均值之间的差异的贝叶斯方法。


15
最好的原始论文可能就是您想要的:indiana.edu/~kruschke/BEST/BEST.pdf
Cam.Davidson.Pilon 2014年

4
明确地说,我们是否说的是两次抽样检验,等同于两组均值差异的频繁检验,例如t检验?还是对诸如Kolmogorov-Smirnoff检验之类的分布差异的强零假设检验感兴趣?
AdamO

Answers:


46

这是一个很好的问题,似乎弹出了很多:链接1链接2。本文贝叶斯估计Superseeds T检验是Cam.Davidson.Pilon指出的是关于这个问题的一个很好的资源。这也是最近出版的,于2012年出版,我认为部分原因是由于对该领域的当前兴趣。

我将尝试总结对两个样本t检验的贝叶斯替代方案的数学解释。此摘要类似于BEST论文,BEST通过比较两个样本的后验分布差异来评估两个样本之间的差异(以下在R中进行了解释)。

set.seed(7)

#create samples
sample.1 <- rnorm(8, 100, 3)
sample.2 <- rnorm(10, 103, 7)

#we need a pooled data set for estimating parameters in the prior.
pooled <- c(sample.1, sample.2)
par(mfrow=c(1, 2))

hist(sample.1)
hist(sample.2)

在此处输入图片说明

为了比较样本的意思,我们需要估计它们是什么。贝叶斯方法使用贝叶斯定理:P(A | B)= P(B | A)* P(A)/ P(B)(将P(A | B)的语法作为概率给定的B)

P(mean.1|sample.1) P(sample.1|mean.1)P(mean.1)P(sample.1|mean.1)P(mean.1)

让我们将其放入代码中。代码使一切变得更好。

likelihood <- function(parameters){
  mu1=parameters[1]; sig1=parameters[2]; mu2=parameters[3]; sig2=parameters[4]
  prod(dnorm(sample.1, mu1, sig1)) * prod(dnorm(sample.2, mu2, sig2))
}

prior <- function(parameters){
  mu1=parameters[1]; sig1=parameters[2]; mu2=parameters[3]; sig2=parameters[4]
  dnorm(mu1, mean(pooled), 1000*sd(pooled)) * dnorm(mu2, mean(pooled), 1000*sd(pooled)) * dexp(sig1, rate=0.1) * dexp(sig2, 0.1)
}

在此之前,我做了一些假设,这些假设需要证明。为了防止先验误差影响估计均值,我希望使它们具有比合理值宽泛且统一的特征,目的是让数据产生后验特征。我使用了BEST的推荐设置,并以均值=均值(合并)和宽泛的标准偏差= 1000 * sd(合并)将mu的正态分布。我将标准偏差设置为广泛的指数分布,因为我想要广泛的无界分布。

现在我们可以使后

posterior <- function(parameters) {likelihood(parameters) * prior(parameters)}

我们将使用经过Metropolis Hastings修改的马尔可夫链蒙特卡洛(MCMC)来采样后验分布。用代码最容易理解。

#starting values
mu1 = 100; sig1 = 10; mu2 = 100; sig2 = 10
parameters <- c(mu1, sig1, mu2, sig2)

#this is the MCMC /w Metropolis method
n.iter <- 10000
results <- matrix(0, nrow=n.iter, ncol=4)
results[1, ] <- parameters
for (iteration in 2:n.iter){
  candidate <- parameters + rnorm(4, sd=0.5)
  ratio <- posterior(candidate)/posterior(parameters)
  if (runif(1) < ratio) parameters <- candidate #Metropolis modification
  results[iteration, ] <- parameters
}

结果矩阵是每个参数的后验分布的样本列表,我们可以用来回答我们的原始问题:sample.1是否不同于sample.2?但是首先要避免受到初始值的影响,我们将“老化”链的前500个值。

#burn-in
results <- results[500:n.iter,]

现在,sample.1与sample.2不同吗?

mu1 <- results[,1]
mu2 <- results[,3]

hist(mu1 - mu2)

在此处输入图片说明

mean(mu1 - mu2 < 0)
[1] 0.9953689

从这一分析中,我得出结论,样本1的平均值小于样本2的平均值的可能性为99.5%。

正如BEST论文所指出的那样,贝叶斯方法的一个优点是它可以建立强有力的理论。例如,sample.2比sample.1大5个单位的概率是多少?

mean(mu2 - mu1 > 5)
[1] 0.9321124

我们可以得出结论,样本2的平均值比样本1大5个单位的可能性为93%。细心的读者会发现这很有趣,因为我们知道真实人口的均值分别为100和103。这很可能是由于样本量小以及选择使用正态分布作为可能性的缘故。

我将以警告结束此答案:该代码用于教学目的。对于真实的分析,请使用RJAGS,并根据样本量拟合可能性的t分布。如果有兴趣,我将使用RJAGS发布t检验。

编辑:这里要求的是JAGS模型。

model.str <- 'model {
    for (i in 1:Ntotal) {
        y[i] ~ dt(mu[x[i]], tau[x[i]], nu)
    }
    for (j in 1:2) {
        mu[j] ~ dnorm(mu_pooled, tau_pooled)
        tau[j] <- 1 / pow(sigma[j], 2)
        sigma[j] ~ dunif(sigma_low, sigma_high)
    }
    nu <- nu_minus_one + 1
    nu_minus_one ~ dexp(1 / 29)
}'

# Indicator variable
x <- c(rep(1, length(sample.1)), rep(2, length(sample.2)))

cpd.model <- jags.model(textConnection(model.str),
                        data=list(y=pooled,
                                  x=x,
                                  mu_pooled=mean(pooled),
                                  tau_pooled=1/(1000 * sd(pooled))^2,
                                  sigma_low=sd(pooled) / 1000,
                                  sigma_high=sd(pooled) * 1000,
                                  Ntotal=length(pooled)))
update(cpd.model, 1000)
chain <- coda.samples(model = cpd.model, n.iter = 100000,
                      variable.names = c('mu', 'sigma'))
rchain <- as.matrix(chain)
hist(rchain[, 'mu[1]'] - rchain[, 'mu[2]'])
mean(rchain[, 'mu[1]'] - rchain[, 'mu[2]'] < 0)
mean(rchain[, 'mu[2]'] - rchain[, 'mu[1]'] > 5)

只是想知道是否存在将贝叶斯两个样本比较与此类数据集一起使用的合理解决方案。stackoverflow.com/q/57503523/7288088

7

用Python实现的user1068430的出色答案

import numpy as np
from pylab import plt

def dnorm(x, mu, sig):
    return 1/(sig * np.sqrt(2 * np.pi)) * np.exp(-(x - mu)**2 / (2 * sig**2))

def dexp(x, l):
    return l * np.exp(- l*x)

def like(parameters):
    [mu1, sig1, mu2, sig2] = parameters
    return dnorm(sample1, mu1, sig1).prod()*dnorm(sample2, mu2, sig2).prod()

def prior(parameters):
    [mu1, sig1, mu2, sig2] = parameters
    return dnorm(mu1, pooled.mean(), 1000*pooled.std()) * dnorm(mu2, pooled.mean(), 1000*pooled.std()) * dexp(sig1, 0.1) * dexp(sig2, 0.1)

def posterior(parameters):
    [mu1, sig1, mu2, sig2] = parameters
    return like([mu1, sig1, mu2, sig2])*prior([mu1, sig1, mu2, sig2])


#create samples
sample1 = np.random.normal(100, 3, 8)
sample2 = np.random.normal(100, 7, 10)

pooled= np.append(sample1, sample2)

plt.figure(0)
plt.hist(sample1)
plt.hold(True)
plt.hist(sample2)
plt.show(block=False)

mu1 = 100 
sig1 = 10
mu2 = 100
sig2 = 10
parameters = np.array([mu1, sig1, mu2, sig2])

niter = 10000

results = np.zeros([niter, 4])
results[1,:] = parameters

for iteration in np.arange(2,niter):
    candidate = parameters + np.random.normal(0,0.5,4)
    ratio = posterior(candidate)/posterior(parameters)
    if np.random.uniform() < ratio:
        parameters = candidate
    results[iteration,:] = parameters

#burn-in
results = results[499:niter-1,:]

mu1 = results[:,1]
mu2 = results[:,3]

d = (mu1 - mu2)
p_value = np.mean(d > 0)

plt.figure(1)
plt.hist(d,normed = 1)
plt.show()

6

使用贝叶斯分析,您可以指定更多的东西(这实际上是一件好事,因为它提供了更多的灵活性和能力来建模您认为是事实的事物)。您是否为可能性假设法线?两组的方差是否相同?

一种简单的方法是对2个均值(和1个或2个方差/离散度)建模,然后在2个均值的差值上查看后验和/或在2个均值的差值上查看可信区间。


您能否提供更多详细信息?我不确定如何对2的均值进行建模并查看后验。
约翰

4

关于贝叶斯方法的数学解释,可以用来检验两个样本的均值之间的差异。

有几种方法可以“测试”这一点。我会提到几个:

  • 如果您想做出明确的决策,可以参考决策理论。

  • 有时要做的一个非常简单的事情是找到均值差的间隔,并考虑是否包括0。这将涉及从观察模型,参数先验和计算以数据为条件的均值差的后验分布开始。

    您需要说出您的模型是什么(例如,正常,恒定方差),然后(至少)说出均值差异的先验值和方差的先验值。您可能会依次拥有这些先验参数的先验。否则,您可能不会假设方差恒定。否则,您可能会认为不是正常现象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.