A distribuição binomial descreve problemas onde os dados são do tipo 0/1, TRUE/FALSE, Detectado/não-Detectado, Cara/Coroa; em geral sucesso/não-sucesso
A distribuição binomial tem um único parâmetro, \(\theta\): a probabilidade de sucesso em cada tentativa
Probabilidade de \(n\) sucessos em \(N\) tentativas independentes: \[ P(n|\theta,N)=\binom Nn \theta^n (1-\theta)^{N-n} = {N! \over n!(N-n)!} \theta^n (1-\theta)^{N-n}\] média e variância: \[ \bar n = \sum_{n=0}^N n P(n) = N\theta ~~~~~~ \sigma^2 = \sum_{n=0}^N (n-\bar n)^2 P(n) = N\theta(1-\theta) \]
Exemplo:
par(mfrow=c(2,2)) # panel de 2 x 2 figuras
# distribuição binomial com p=0.1
N=15 #número de tentativas
n = seq(0,20,1) # número de sucessos - numeros inteiros positivos
y = dbinom(n,N,prob=0.10)
N=30
plot(n,y,main="distribuição binomial (N,p)=(15,0.1)",type="h")
y = dbinom(n,N,prob=0.10)
plot(n,y,main="distribuição binomial (N,p)=(30,0.1)",type="h")
# distribuição binomial com p=0.5
N=15
y = dbinom(n,N,prob=0.5)
plot(n,y,main="distribuição binomial (N,p)=(15,0.5)",type="h")
N=30
y = dbinom(n,N,prob=0.5)
plot(n,y,main="distribuição binomial (N,p)=(30,0.5)",type="h")
Dado um conjunto de dados, vamos fazer um modelo bayesiano para estimar \(\theta\) (\(0 \le \theta \le 1\))
Vamos escrever a verossimilhança como a distribuição binomial \[ P(\theta|n,N) = \binom{N}{n} \theta^n(1-\theta)^{N-n} \]
e o prior como uma função Beta, já que a variável \(\theta\) é definida entre 0 e 1: \[ Beta(\theta|a,b) = \Bigg[ \frac{\Gamma(a+b)}{\Gamma(a)\Gamma(b)}\Bigg] \theta^{a-1} (1-\theta)^{b-1} \] \[(a,b ~ > 0) \]
# distribuição beta em R: dbeta(x,a,b)
# vamos gerar uma sequência de números entre 0 e 1 separados por 0.01
# vamos amostrar a função beta nesses valores
x=seq(0,1,0.01)
# vamos fazer uma figura com 3 x 2 subfiguras
par(mfrow=c(3,2))
# vamos considerar valores diferentes de a e b e ver a cara da função:
a=10
b=30
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
a=1
b=3
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
a=1
b=1
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
a=3
b=1
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
a=30
b=10
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
a=10
b=10
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main=sprintf(paste('a,b = ',a,b,sep=' ')))
posterior: \[ P(\theta|D) \propto \theta^{n+a-1}(1-\theta)^{N-n+b-1} \] \[ \propto Beta(\theta|n+a,N-n+b) \]
note que, nesse caso, tanto o prior quanto o posterior são funções Beta: Beta é um prior conjugado da distribuição binomial
Exemplo 1: baseado em https://www.r-exercises.com/2017/12/03/basic-bayesian-inference-for-mcmc-techniques-exercises-part-1/
Um modelo de formação de galáxias prevê que em aglomerados de galáxias ricos a maior parte das galáxias luminosas sejam elípticas ou lenticulares (em baixos redshifts). Queremos analisar se esse é realmente o caso em uma amostra de aglomerados. Este problema é uma adaptação do descrito no link acima.
Seja \(\theta\) a fração de galáxias early type (ET: E e S0). O estudo de uma grande simulação revela que em uma amostra de \(N=1000\) galáxias luminosas em aglomerados ricos, \(n=735\) são desse tipo. Vamos classificar as galáxias como \(y=1\) se forem ET e \(y=0\) se não o forem.
Vamos ver, inicialmente, qual é a distribuição de probabilidade dos dados, plotando a verossimilhança:
plot(dbinom(x = seq(1, 1000, 1), size = 1000, prob = 735/1000),
type = "l", lwd = 3, main = "verossimilhança", ylab = "densidade de probabilidades", xlab = "número de galáxias early type", col='blue')
abline(v = 735, col = "red",lwd=2)
Vamos considerar inicialmente um prior uniforme para \(\theta\); ele corresponde a \(Beta(\theta|a=1,b=1)\)
a=1
b=1
y = dbeta(x,a,b)
plot(x,y,type='l',col='blue', main='prior', ylab = "densidade de probabilidades",xlab=expression(theta),lwd=3)
e o posterior será \[ P(\theta|D,a,b) \propto Beta(\theta|a=736,b=266):\]
a=1
b=1
n=735
N=1000
y = dbeta(x,n+a,N-n+b)
plot(x,y,type='l',col='green', main='posterior', ylab = "densidade de probabilidades",xlab=expression(theta),lwd=3)
# moda
# https://stackoverflow.com/questions/2547402/how-to-find-the-statistical-mode
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
M=100000
post_sample = rbeta(M, shape1 = n+a, shape2 = N-n+b)
Mode(post_sample)
## [1] 0.7391225
# intervalo de confian,ca de 95%:
quantile(post_sample, probs = c(0.025, 0.975))
## 2.5% 97.5%
## 0.7066068 0.7613735
Uma outro estudo indica que apenas 60+/-20% das galáxias luminosas são ET. Queremos usar esta informação como prior. Como podemos fazer isso?
A distribuição beta tem dois hiperparâmetros (“shape parameters”) que podem ser obtidos da média e variância da distribuição:
estBetaParams <- function(mean, variance) {
alpha <- ((1 - mean) / variance - 1 / mean) * mean^2
beta <- alpha * (1 / mean - 1)
return(params = list(a = alpha, b = beta))
}
Assim, em nosso exemplo o prior de \(\theta\) tem parâmetros:
prior.params <- estBetaParams(mean = 0.6, variance = 0.2^2)
prior.params
## $a
## [1] 3
##
## $b
## [1] 2
Vamos representar graficamente este prior:
x_grid <- seq(from = 0,to = 1, by = 0.001)
# note que seq deve estar no intervalo de Beta, [0,1]
plot(x = x_grid, dbeta(x = x_grid, shape1 = prior.params$a, shape2 = prior.params$b), lwd = 3, col = 'blue', ylab = "densidade", xlab = expression(theta), type = "l", main = "prior")
E o posterior será:
N <- 1000
n <- 735
# hiper-parâmetros do posterior
alpha_post <- prior.params$a + n
beta_post <- prior.params$b + N - n
#plot do posterior
plot(x = x_grid, dbeta(x = x_grid, shape1 = alpha_post, shape2 = beta_post), lwd = 3, type = "l", ylab = "densidade", xlab = expression(theta), col = "red", main = "posterior e prior")
# prior
lines(x = x_grid, dbeta(x = x_grid, shape1 = prior.params$a, shape2 = prior.params$b), lwd = 3)
legend("topright",c("Posterior","Prior"),col=c("red", "black"),lwd=c(3,3))
# valor de teta da verossimilhança
abline(v = 0.735, col = "green")
# moda
M=100000
post_sample = rbeta(M, shape1 = n+a, shape2 = N-n+b)
Mode(post_sample)
## [1] 0.7269337
# intervalo de confian,ca de 95%:
post_sample = rbeta(M, shape1 = prior.params$a, shape2 = prior.params$b)
quantile(post_sample, probs = c(0.025, 0.975))
## 2.5% 97.5%
## 0.1960180 0.9329706
Pode-se notar que, nesse exemplo, a forma do prior afeta muito pouco o posterior. Compare a moda e o intervalo de confiança de \(\theta\) nos dois casos. Se o número de dados fosse bem menor as diferenças seriam maiores!
Exemplo 2: este exemplo é do blog de Rasmus Bååth (ver http://www.sumsar.net/) e mostra um exemplo do problema binomial, ilustrando a evolução do posterior de acordo com o número de observações.
https://www.r-bloggers.com/2018/12/yet-another-visualization-of-the-bayesian-beta-binomial-model/
# This function takes a number of successes and failuers coded as a TRUE/FALSE
# or 0/1 vector. This should be given as the data argument.
# The result is a visualization of the how a Beta-Binomial
# model gradualy learns the underlying proportion of successes
# using this data. The function also returns a sample from the
# posterior distribution that can be further manipulated and inspected.
# The default prior is a Beta(1,1) distribution, but this can be set using the
# prior_prop argument.
# Make sure the packages tidyverse and ggridges are installed, otherwise run:
# install.packages(c("tidyverse", "ggridges"))
# Example usage:
# data <- c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE)
# prop_model(data)
prop_model <- function(data = c(), prior_prop = c(1, 1), n_draws = 10000) {
library(tidyverse)
data <- as.logical(data)
# data_indices decides what densities to plot between the prior and the posterior
# For 20 datapoints and less we're plotting all of them.
data_indices <- round(seq(0, length(data), length.out = min(length(data) + 1, 20)))
# dens_curves will be a data frame with the x & y coordinates for the
# denities to plot where x = proportion_success and y = probability
proportion_success <- c(0, seq(0, 1, length.out = 100), 1)
dens_curves <- map_dfr(data_indices, function(i) {
value <- ifelse(i == 0, "Prior", ifelse(data[i], "Success", "Failure"))
label <- paste0("n=", i)
probability <- dbeta(proportion_success,
prior_prop[1] + sum(data[seq_len(i)]),
prior_prop[2] + sum(!data[seq_len(i)]))
probability <- probability / max(probability)
data_frame(value, label, proportion_success, probability)
})
# Turning label and value into factors with the right ordering for the plot
dens_curves$label <- fct_rev(factor(dens_curves$label, levels = paste0("n=", data_indices )))
dens_curves$value <- factor(dens_curves$value, levels = c("Prior", "Success", "Failure"))
p <- ggplot(dens_curves, aes(x = proportion_success, y = label,
height = probability, fill = value)) +
ggridges::geom_density_ridges(stat="identity", color = "white", alpha = 0.8,
panel_scaling = TRUE, size = 1) +
scale_y_discrete("", expand = c(0.01, 0)) +
scale_x_continuous("Underlying proportion of success") +
scale_fill_manual(values = hcl(120 * 2:0 + 15, 100, 65), name = "", drop = FALSE,
labels = c("Prior ", "Success ", "Failure ")) +
ggtitle(paste0(
"Binomial model - Data: ", sum(data), " successes, " , sum(!data), " failures")) +
theme_light() +
theme(legend.position = "top")
print(p)
# Returning a sample from the posterior distribution that can be further
# manipulated and inspected
posterior_sample <- rbeta(n_draws, prior_prop[1] + sum(data), prior_prop[2] + sum(!data))
invisible(posterior_sample)
}
set.seed(123)
big_data <- sample(c(TRUE, FALSE), prob = c(0.75, 0.25),
size = 100, replace = TRUE)
posterior <- prop_model(big_data)
## ── Attaching packages ────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.2.1 ✓ purrr 0.3.3
## ✓ tibble 2.1.3 ✓ dplyr 0.8.3
## ✓ tidyr 1.0.2 ✓ stringr 1.4.0
## ✓ readr 1.3.1 ✓ forcats 0.4.0
## ── Conflicts ───────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
## Warning: `data_frame()` is deprecated, use `tibble()`.
## This warning is displayed once per session.
quantile(posterior, c(0.025, 0.5, 0.975))
## 2.5% 50% 97.5%
## 0.6360817 0.7272447 0.8082072