Lab 1 more
Analisi Bayesiana di Dati Binomiali
Altri esercizi riguardo alla visualzzazione e all’inferenza Bayesiana.
Uso di ggplot2
Probabilità di una nascita femminile data la condizione placenta previa
(BDA3 p. 37).
L’a posteriori è una Beta(438,544)
# seq creates evenly spaced values
df1 <- data.frame(theta = seq(0.375, 0.525, 0.001))
a <- 438
b <- 544
# dbeta computes the posterior density
df1$p <- dbeta(df1$theta, a, b)Calcoliamo anche l’intervallo centrale del 95%
# seq creates evenly spaced values from 2.5% quantile to 97.5% quantile (i.e., 95% central interval)
# qbeta computes the value for a given quantile given parameters a and b
df2 <- data.frame(theta = seq(qbeta(0.025, a, b), qbeta(0.975, a, b), length.out = 100))
# compute the posterior density
df2$p <- dbeta(df2$theta, a, b)Si disegni l’a posteriori (Beta(438,544)) e la linea verticale per la media della popolazione (48.8%)
ggplot2
One of the key ideas behind ggplot2 is that it allows you to easily iterate, building up a complex plot a layer at a time. Each layer can come from a different dataset and have a different aesthetic mappings, making it possible to create sophisticated plots that display data from multiple sources.
ggplot(mapping = aes(theta, p)) +
geom_line(data = df1) +
# Add a layer of colorized 95% posterior interval
geom_area(data = df2, aes(fill='1')) +
# Add the proportion of girl babies in general population
geom_vline(xintercept = 0.488, linetype='dotted', linewidth=1.25) +
# Decorate the plot a little
labs(title='Uniform prior -> Posterior is Beta(438,544)',x=expression(theta), y = '') +
scale_y_continuous(expand = c(0, 0.1), breaks = NULL) +
scale_fill_manual(values = 'lightblue', labels = '95% posterior interval') +
theme(legend.position = 'bottom', legend.title = element_blank())change from ggplot2 3.4.0
Warning: Using
sizeaesthetic for lines was deprecated in ggplot2 3.4.0. ℹ Please uselinewidthinstead.
Effetto di diverse a priori in un modello binomiale
Effetto dell’a priori e confronto delle a posteriori con valori dei parametri differenti per le a priori beta
Oltre a ggplot2 per la visualizzazione, tidyr è usato
per lavorare sui data frame
Dati osservati: 437 femmine e 543 maschi
La densità viene valutata nei punti equamente distribuiti tra 0.375 e 0.525
A posteriori con Beta(1,1), ie. a priori uniforme
Tre scelte differenti per le a priori
Beta(\(0.488*2\),\((1-0.488)*2\))
Beta(\(0.488*20\),\((1-0.488)*20\))
Beta(\(0.488*200\),\((1-0.488)*200\))
n <- c(2, 20, 200) # conteggi a priori
apr <- 0.488 # prop di successo a priori
# helperf ritorna, dati un numero di osservazioni a priori, una prop di successo a priori,
# un numero di successi e fallimenti osservati e un dataframe con i valori per theta,
# un dataframe nuovo con valori a priori e a posteriori calcolati nei punti theta.
#
helperf <- function(n, apr, a, b, df)
cbind(df, pr = dbeta(df$theta, n*apr, n*(1-apr)), po = dbeta(df$theta, n*apr + a, n*(1-apr) + b), n = n)
# lapply the above function over prior counts n, then bind by row, and lastly gather results into key-value pairs.
df2 <- lapply(n, helperf, apr, a, b, df1) %>% do.call(rbind, args = .) %>%
gather(key = grp, value = p, -c(theta, n), factor_key = T)
df2 %>% head; df2 %>% tail
theta n grp p
1 0.375 2 pu 0.0008507679
2 0.376 2 pu 0.0011418738
3 0.377 2 pu 0.0015257278
4 0.378 2 pu 0.0020295190
5 0.379 2 pu 0.0026876416
6 0.380 2 pu 0.0035433725
theta n grp p
1354 0.520 200 po 0.0006885263
1355 0.521 200 po 0.0005006071
1356 0.522 200 po 0.0003622430
1357 0.523 200 po 0.0002608721
1358 0.524 200 po 0.0001869727
1359 0.525 200 po 0.0001333673
# add correct labels for plotting
df2$title <- factor(paste0('alpha/(alpha+beta)=0.488, alpha+beta=',df2$n))
levels(df2$grp)
[1] "pu" "pr" "po"
levels(df2$grp) <- c('Posterior with unif prior', 'Prior', 'Posterior')
df2 %>% head
theta n grp p
1 0.375 2 Posterior with unif prior 0.0008507679
2 0.376 2 Posterior with unif prior 0.0011418738
3 0.377 2 Posterior with unif prior 0.0015257278
4 0.378 2 Posterior with unif prior 0.0020295190
5 0.379 2 Posterior with unif prior 0.0026876416
6 0.380 2 Posterior with unif prior 0.0035433725
title
1 alpha/(alpha+beta)=0.488, alpha+beta=2
2 alpha/(alpha+beta)=0.488, alpha+beta=2
3 alpha/(alpha+beta)=0.488, alpha+beta=2
4 alpha/(alpha+beta)=0.488, alpha+beta=2
5 alpha/(alpha+beta)=0.488, alpha+beta=2
6 alpha/(alpha+beta)=0.488, alpha+beta=2Grafico delle distribuzioni
ggplot(data = df2) +
geom_line(aes(theta, p, color = grp)) +
geom_vline(xintercept = apr, linetype = 'dotted') +
facet_wrap(~ title, ncol = 1) +
labs(x = '', y = '') +
scale_y_continuous(breaks = NULL) +
theme(legend.position = 'bottom', legend.title = element_blank())Inferenza basata sulla simulazione
Simuliamo campioni da una Beta(438,544), disegniamo un istogramma (con quantili), e facciamo lo stesso per una variabile trasformata.
Campioniamo dalla a posteriori Beta(438,544). Otteniamo tutte le estrazioni in una volta e salviamole in un vettore ‘theta’
Calcoliamo l’odds ratio per tutte le estrazioni
Calcoliamo i quantili 2.5% e 97.5% aprossimati usando i campioni
Istogrammi con 30 bins per theta e phi
# merge the data into one data frame for plotting
df1 <- data.frame(phi,theta) %>% gather()
#df1 %>% head
# merge quantiles into one data frame for plotting
df2 <- data.frame(phi = phiq, theta = thetaq) %>% gather()
#df2
ggplot() +
geom_histogram(data = df1, aes(value), bins = 30) +
geom_vline(data = df2, aes(xintercept = value), linetype = 'dotted', linewidth = 1.25) +
facet_wrap(~key, ncol = 1, scales = 'free_x') +
labs(x = '', y = '') +
scale_y_continuous(breaks = NULL)Se vogliamo aggoiungere la densità
ggplot(data = df1, aes(value)) +
geom_histogram(aes(y = after_stat(density)), fill="white", col="black", bins = 30) +
geom_density(col = 2, fill = 2, alpha=.2) +
geom_vline(data = df2, aes(xintercept = value), linetype = 'dotted', linewidth = 1.25) +
facet_wrap(~key, ncol = 1, scales = 'free') +
labs(x = '', y = '') +
scale_y_continuous(breaks = NULL)Grid e inverse-cdf sampling
Campionamento con griglia e con l’inversa della funzione di ripartizione
- Calcoliamo la distribuzione a posteriori su una griglia discreta di punti moltiplicando la verosimiglianza e un’a priori non coniugata in ogni punto e poi normalizzando sui punti.
- Simuliamo campioni dalla distribuzione a posteriori non standard risultante utilizzando l’inversa della cdf e la griglia discreta.
A posteriori con osservazioni (437,543) e a priori uniforme (Beta(1,1))
Calcoliamo la densità di un’a priori non-coniugata nei punti discreti di una griglia.
E.g., un’a priori lineare a pezzi con una certa % di probabilità al di fuori dell’intervallo (0.388, 0.588) (si veda la figura 2.4 in BDA3)
pp <- rep(1, nrow(df1))
pi <- sapply(c(0.388, 0.488, 0.588), function(pi) which(df1$theta == pi))
pi
[1] 289 389 489
pm <- 11
pp[pi[1]:pi[2]] <- seq(1, pm, length.out = length(pi[1]:pi[2])) #%>% print
pp[pi[3]:pi[2]] <- seq(1, pm, length.out = length(pi[3]:pi[2])) #%>% printNormalizziamo la a priori
Calcoliamo l’a posteriori non-normalizzata e non-coniugata sulla griglia, quindi la normalizziamo
Disegniamo l’a posteriori con a priori uniforme, l’a priori non-coniugata e la corrispondente a posteriori non-coniugata
# gather the data frame into key-value pairs
# and change variable names for plotting
df2 <- gather(df1, grp, p, -theta, factor_key = T) #%>%
levels(df2$grp) <- c('Posterior with uniform prior', 'Non-conjugate prior', 'Non-conjugate posterior')
ggplot(data = df2) +
geom_line(aes(theta, p)) +
facet_wrap(~grp, ncol = 1, scales = 'free_y') +
coord_cartesian(xlim = c(0.35,0.6)) +
scale_y_continuous(breaks=NULL) +
labs(x = '', y = '')Inverse cdf sampling
calcoliamo la densità cumulata (funzione di ripartizione) sulla griglia
Campioniamo dalla distr uniforme U(0,1)
# set.seed(seed) is used to set seed for the random number generator
set.seed(2601)
# runif(k) returns k uniform random numbers from interval [0,1]
r <- runif(10000)Campionamento tramite l’inversa della cdf
# function to find the smallest value theta at which the cumulative sum of the posterior densities is greater than r.
invcdf <- function(r, df) df$theta[sum(df$cs_po < r) + 1]
# sapply function for each sample r. The returned values s are now random draws from the distribution.
s <- sapply(r, invcdf, df1)Creiamo tre grafici: p1 è l’a posteriori, p2 è la cdf dell’a posteriori e p3 è l’istogramma delle estrazioni dall’a posteriori (estratte usando l’inversa-cdf)
p1 <- ggplot(data = df1) +
geom_line(aes(theta, nc_po)) +
coord_cartesian(xlim = c(0.35, 0.6)) +
labs(title = 'Non-conjugate posterior', x = '', y = '') +
scale_y_continuous(breaks = NULL)
p2 <- ggplot(data = df1) +
geom_line(aes(theta, cs_po)) +
coord_cartesian(xlim = c(0.35, 0.6)) +
labs(title = 'Posterior-cdf', x = '', y = '') +
scale_y_continuous(breaks = NULL)
p3 <- ggplot() +
geom_histogram(aes(s, y = after_stat(density)), binwidth = 0.003) +
geom_line(aes(s, y = after_stat(density)), stat = "bin", binwidth = 0.003, col='red') +
coord_cartesian(xlim = c(0.35, 0.6)) +
labs(title = 'Histogram of posterior samples', x = '', y = '') +
scale_y_continuous(breaks = NULL)
# combine the plots
grid.arrange(p1, p2, p3)