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.

John
fonte
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)
user1068430
fonte
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()
Francisco Grings
fonte
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.

Greg Snow
fonte
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.

Glen_b -Reinstate Monica
fonte