Distribuições a Priori e a Posteriori

Priori

Tratamos de um modelo como uma variável aleatória e atribuimos uma distribuição para esse parâmetro. O nome será distribuição a priori. Ao fazer modelagens, ela é em geral pré-definida pelo modelador, que é em geral aconselhado por um especialista.

Posteriori

Sejam v.a. observadas e um parâmetro desconhecido. A distribuição de condicionado nas variáveis aleatórias é a distribuição a posteriori. Observe a relação com o Teorema de Bayes.

Teorema

Suponha que formam uma amostra aleatória de uma distribuição . Suponha que o parâmetro seja desconhecido e que a distribuição da priori seja . Então, a distribuição a posteriori é:

Onde é a distribuição marginal conjunta de

Observe que, essencialmente , mas que sua integral seja . Queremos que essa função seja integrável e a integral sobre o domínio seja .

Função de Verossimilhança

Quando a função de densidade de probabilidade das observações de uma amostra aleatória é vista como uma função de , chamamos ela de função de verossimilhança.

Observações Sequenciais e Predições

Nesse caso a ordem das variáveis importam (como uma série temporal, por exemplo). Nesse caso, podemos, iterativamente fazer:

Isso acontece dada a independência das variáveis aleatórias.

Notebook de Referência

Frequentistas

Bayesianos

Simples exemplo de inferência Bayesiana

Hemofilia é uma disordem genética que prejudica a coagulação em resposta a rupturas em vasos sanguíneos. É recessiva ligada ao cromossomo X. Isso implica que homens com 1 gene são afetados, enquanto as mulheres não são afetadas, mas portadoras.

Considere uma mulher cuja mãe é portadora e tem um irmão afetado. Ela se casa com um homem não afetado. A mulher tem dois filhos consecutivos que não são afetados. Será que a mãe é portadora?

A pergunra é simples. Vamos tentar usar um pouco do que sabemos. Seja se a mulher é portadora e se ela não for portadora. Queremos saber , isto é, os filhos não são afetados.

Que informação nós temos ? A mãe dela é portadora, portanto uma priori interessante é:

Podemos calcular a função de verossimilhança:

python import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm

```python priori = 0.5 # P(W = 1) p = 0.5 # prob de um filho ser afetado

Likelihood = lambda w, s: np.prod([(1 - i, pi*(1-p)(1 - i))[w]for i in s])

s = [0,0]

posteriori = Likelihood(1,s)priori/(Likelihood(1,s)priori + Likelihood(0,s)*(1 - priori)) print("A probabilidade da mãe portar é {} com dois filhos não portadores.".format(posteriori)) ```

A probabilidade da mãe portar é 0.2 com dois filhos não portadores.

```python s = [0] # terceiro filho

priori = posteriori

posteriori = Likelihood(1,s)priori/(Likelihood(1,s)priori + Likelihood(0,s)*(1 - priori)) print("A probabilidade da mãe portar é {:.3f} com três filhos não portadores.".format(posteriori)) ```

A probabilidade da mãe portar é 0.111 com três filhos não portadores.

```python priori = 0.5 p = 0.5 s = [0] posteriori = [] for i in range(50): posteriori.append(Likelihood(1,s)priori/(Likelihood(1,s)priori + Likelihood(0,s)*(1 - priori))) priori = posteriori[-1]

priori = 0.5 posteriori2 = [] for i in range(50): posteriori2.append(Likelihood(1,s)priori/(Likelihood(1,s)priori + Likelihood(0,s)*(1 - priori))) priori = posteriori2[-1] s = [np.random.choice([0,1], p = (0.9, 0.1))]

plt.plot(range(50), posteriori, label = 'Situação 1') plt.plot(range(50), posteriori2, label = 'Situação 2') plt.legend() plt.title('Probabilidade dado cada filho') plt.show() ```

svg

Princípio de Verossimilhança

Afirma que para uma inferência sobre um parâmetro , toda evidência de qualquer observação de uma variável aleatória com distribuição se encontra na função de verossimilhança .

A interpretação é de que qualquer observação de pode construir conclusões sobre . Além disso, se pudéssemos obter informação de sobre outra variável aleatória com verossimilhança , teremos que . Isto é, as conclusões sobre o parâmetro não dependem da observação feita.

Qual o problema?

Jeffreys: "An hypothesis that may be true is rejected because it has failed to predict observable results that have not occurred. "

```python import pymc3 as pm from pymc3 import Model, Normal, Slice from pymc3 import sample from pymc3 import traceplot from pymc3.distributions import Interpolated

from scipy import stats

import matplotlib as mpl

plt.style.use('seaborn-darkgrid') ```

Gerando os dados

```python

True parameters

alpha_true = 5 beta0_true = 7 beta1_true = 13

Size of the dataset

size = 100

Random variables

np.random.seed(1)

X1 = np.random.randn(size) X2 = np.random.randn(size)*0.2

e = np.random.randn(size)

Y = alpha_true + beta0_true * X1 + beta1_true * X2 + e ```

Especificando o modelo

Vamos fazer um modelo simples aqui, só para mostrar essa biblioteca nova. A ideia é mostrar como funciona a ideia de priori e posteriori.

Vamos dizer que , onde

```python model = Model() #cria um novo modelo, que em Python, é um objeto

with model: # Isso cria um contexto em python

# Vamos dizer nossas prioris!
alpha = Normal('alpha', mu = 0, sigma = 1)
beta0 = Normal('beta0', mu = 12, sigma  = 1)
beta1 = Normal('beta1', mu = 18, sigma = 1)

# Valor esperado da saída 
mu = alpha + beta0*X1 + beta1*X2

# Verossimilhança das observações 
Y_obs = Normal('Y_obs', mu = mu, sigma = 1, observed = Y)

# Amostras da distribuição 
trace = sample(1000)

```

Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 3 seconds.

A próxima função é um plot de distribuição a priori amostrada (que é basicamente um histograma) de cada parâmetro. Veja que parece um chiado em torno da média.

python traceplot(trace);

svg

Agora que nós temos os dados gerados , vamos atualizar nosso conhecimento, nossa confiança nos parâmetros, através da distribuição a posteriori. Os dados devem ser independentes a ada interação para que valha o que estudamos. Para isso, precisamos calcular a posteriori de cada parâmetro. Nesse caso, vamos utilizar uma aproximação para a distribuição, utlizando aproximação Kernel. Não se preocupe com isso, é só para mostrar que estamos calculado a posteriori

```python def from_posterior(param, samples):

smin, smax = np.min(samples), np.max(samples)
width = smax - smin

x = np.linspace(smin, smax, 100)

y = stats.gaussian_kde(samples)(x)

# what was never sampled should have a small probability but not 0,
# so we'll extend the domain and use linear approximation of density on it
x = np.concatenate([[x[0] - 3 * width], x, [x[-1] + 3 * width]])
y = np.concatenate([[0], y, [0]])
return Interpolated(param, x, y)

```

Agora, vamos gerar mais dados e usar a Fórmula de Bayes e usaremos uma forma sequencial das observações, isto é, a posteriori da iteração será a priori da iteração .

```python traces = [trace] # salva os traços para que plotamos depois. for _ in range(10): # _ indica uma variável que não é usada

#  Gerando mais e mais dados!
X1 = np.random.randn(size)
X2 = np.random.randn(size) * 0.2
e = np.random.randn(size)
Y = alpha_true + beta0_true * X1 + beta1_true * X2 + e

model = Model()
with model:
    # As novas prioris são as posterioris 
    alpha = from_posterior('alpha', trace['alpha'])
    beta0 = from_posterior('beta0', trace['beta0'])
    beta1 = from_posterior('beta1', trace['beta1'])

    # EValor esperado da saída 
    mu = alpha + beta0 * X1 + beta1 * X2

    # Calculando a verossimilhança dos novos dados 
    Y_obs = Normal('Y_obs', mu = mu, sigma = 1, observed = Y)

    # Amostrando da posteriori, porque não estamos calculando a forma fechada 
    trace = sample(1000)
    traces.append(trace)

```

Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 5 seconds.
The number of effective samples is smaller than 25% for some parameters.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 3 seconds.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 3 seconds.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 3 seconds.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 4 seconds.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 5 seconds.
The estimated number of effective samples is smaller than 200 for some parameters.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 4 seconds.
The rhat statistic is larger than 1.4 for some parameters. The sampler did not converge.
The estimated number of effective samples is smaller than 200 for some parameters.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 4 seconds.
The number of effective samples is smaller than 25% for some parameters.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 4 seconds.
The acceptance probability does not match the target. It is 0.8800702431829607, but should be close to 0.8. Try to increase the number of tuning steps.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (2 chains in 2 jobs)
NUTS: [beta1, beta0, alpha]
█Sampling 2 chains for 1_000 tune and 1_000 draw iterations (2_000 + 2_000 draws total) took 3 seconds.

```python fig, ax = plt.subplots(1,3,figsize=(20, 5))

Definindo cores

cmap = mpl.cm.autumn

for index, param in enumerate(['alpha', 'beta0', 'beta1']):

for update_i, trace in enumerate(traces):

    samples = trace[param]
    smin, smax = np.min(samples), np.max(samples)
    x = np.linspace(smin, smax, 100)
    y = stats.gaussian_kde(samples)(x)

    ax[index].plot(x, y, color=cmap(1 - update_i / len(traces)), alpha = update_i/len(traces))

ax[index].axvline({'alpha': alpha_true, 'beta0': beta0_true, 'beta1': beta1_true}[param], c='k')
ax[index].set_ylabel('Frequency')
ax[index].set_title(param)

plt.tight_layout(); ```

svg

```python

```