Equivalente bayesiano de duas amostras do teste t?


39

Não estou procurando um método plug and play como o BEST em R, mas uma explicação matemática de quais são alguns métodos bayesianos que posso usar para testar a diferença entre a média de duas amostras.


15
o documento BEST original original pode ser o que você está procurando: indiana.edu/~kruschke/BEST/BEST.pdf
Cam.Davidson.Pilon

4
Só para esclarecer, estamos falando de um teste de duas amostras que é equivalente a um teste freqüentista de diferenças médias em dois grupos, como o teste t? ou você está interessado em testes da hipótese nula forte para diferenças distributivas como o teste de Kolmogorov-Smirnoff?
Adamo

Respostas:


46

Essa é uma boa pergunta, que parece aparecer muito: link 1 , link 2 . O artigo Bayesian Estimation Superseed the T-Test que Cam.Davidson.Pilon apontou é um excelente recurso sobre esse assunto. Também é muito recente, publicado em 2012, que acho que em parte se deve ao interesse atual na área.

Tentarei resumir uma explicação matemática de uma alternativa bayesiana ao teste t de duas amostras. Este resumo é semelhante ao artigo BEST, que avalia a diferença em duas amostras, comparando a diferença em suas distribuições posteriores (explicadas abaixo em 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)

insira a descrição da imagem aqui

Para comparar a amostra, precisamos estimar o que são. O método bayesiano para fazer isso usa o teorema de Bayes: P (A | B) = P (B | A) * P (A) / P (B) (a sintaxe de P (A | B) é lida como a probabilidade de A dado B)

P(meuman.1|sumampeue.1) P(sumampeue.1|meuman.1)P(meuman.1)P(sumampeue.1|meuman.1)P(meuman.1)

Vamos colocar no código. Código torna tudo melhor.

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)
}

Fiz algumas suposições anteriores que precisam ser justificadas. Para evitar que os anteriores prejudiquem a média estimada, eu queria torná-los amplos e uniformes sobre valores plausíveis, com o objetivo de permitir que os dados produzissem as características do posterior. Usei a configuração recomendada de BEST e distribuí os mu's normalmente com média = média (agrupada) e um amplo desvio padrão = 1000 * sd (agrupada). Os desvios padrão que defini para uma ampla distribuição exponencial, porque eu queria uma ampla distribuição ilimitada.

Agora podemos fazer a posterior

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

Amostraremos a distribuição posterior usando uma cadeia de markov monte carlo (MCMC) com modificação de Metropolis Hastings. É mais fácil entender com código.

#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
}

A matriz de resultados é uma lista de amostras da distribuição posterior para cada parâmetro que podemos usar para responder à nossa pergunta original: sample.1 é diferente de sample.2? Mas, primeiro, para evitar efeitos dos valores iniciais, iremos "queimar" os primeiros 500 valores da cadeia.

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

Agora, sample.1 é diferente de sample.2?

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

hist(mu1 - mu2)

insira a descrição da imagem aqui

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

A partir dessa análise, concluo que há uma chance de 99,5% de que a média da amostra.1 seja menor que a média da amostra.2.

Uma vantagem da abordagem bayesiana, como apontado no artigo BEST, é que ela pode fazer teorias fortes. Por exemplo, qual é a probabilidade de que a amostra.2 seja 5 unidades maior que a amostra.1.

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

Concluiríamos que existe uma chance de 93% de que a média da amostra.2 seja 5 unidades maior que a amostra.1. Um leitor atento acharia isso interessante porque sabemos que as populações verdadeiras têm meios de 100 e 103, respectivamente. Provavelmente, isso se deve ao pequeno tamanho da amostra e à escolha de usar uma distribuição normal para a probabilidade.

Terminarei esta resposta com um aviso: Este código é para fins de ensino. Para uma análise real, use o RJAGS e, dependendo do tamanho da amostra, ajuste uma distribuição t para a probabilidade. Se houver interesse, publicarei um teste t usando o RJAGS.

EDIT: Conforme solicitado, aqui está um modelo 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)

Imaginando se existe uma solução razoável para usar a comparação bayesiana de duas amostras com esse tipo de conjunto de dados. stackoverflow.com/q/57503523/7288088
pyring

7

A excelente resposta do usuário1068430 implementada em Python

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

Com uma análise bayesiana, você tem mais coisas a especificar (isso é realmente uma coisa boa, pois oferece muito mais flexibilidade e capacidade de modelar o que você acredita ser a verdade). Você está assumindo normais para as probabilidades? Os 2 grupos terão a mesma variação?

Uma abordagem direta é modelar as 2 médias (e 1 ou 2 variações / dispersões) e depois olhar para o posterior na diferença das 2 médias e / ou no intervalo de credibilidade na diferença das 2 médias.


Você poderia fornecer mais alguns detalhes sobre isso? Não sei como modelar 2 significa e olhar para os posteriores.
John John

4

uma explicação matemática de quais são alguns métodos bayesianos que posso usar para testar a diferença entre a média de duas amostras.

Existem várias abordagens para "testar" isso. Vou mencionar alguns:

  • Se você deseja uma decisão explícita , pode considerar a teoria da decisão.

  • Uma coisa bastante simples que às vezes é feita é encontrar um intervalo para a diferença nos meios e considerar se inclui 0 ou não. Isso envolveria começar com um modelo para as observações, anteriores aos parâmetros e computar a distribuição posterior da diferença de médias condicionada aos dados.

    Você precisaria dizer qual é o seu modelo (por exemplo, variação normal e constante) e, em seguida (pelo menos) um número anterior para a diferença de médias e um anterior para a variação. Você pode ter antecedentes sobre os parâmetros desses antecedentes. Ou você pode não assumir variação constante. Ou você pode assumir algo diferente da normalidade.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.