Atualização Bayesiana com Matplotlib

Beginner

This tutorial is from open-source community. Access the source code

Introdução

A atualização bayesiana (Bayesian updating) é uma abordagem estatística que nos permite atualizar a probabilidade de uma hipótese à medida que novos dados se tornam disponíveis. Neste laboratório, usaremos Matplotlib para criar uma animação que mostra como a atualização bayesiana funciona. Especificamente, simularemos um experimento de lançamento de moeda e usaremos a atualização bayesiana para estimar a probabilidade da moeda cair com a face "cara" para cima.

Dicas para a VM

Após a inicialização da VM, clique no canto superior esquerdo para mudar para a aba Notebook e acessar o Jupyter Notebook para praticar.

Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.

Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão, e resolveremos o problema prontamente para você.

Importar as Bibliotecas Necessárias

Começamos importando as bibliotecas que usaremos no laboratório. Especificamente, usaremos matplotlib.pyplot para visualização, numpy para computação numérica e math para funções matemáticas.

import math

import matplotlib.pyplot as plt
import numpy as np

Definir a PDF da Distribuição Beta

A distribuição beta é uma distribuição de probabilidade contínua que é frequentemente usada para representar a distribuição de probabilidades. Na atualização bayesiana (Bayesian updating), usamos a distribuição beta como uma distribuição a priori (prior distribution) para representar nossas crenças sobre a probabilidade de uma hipótese antes de observar quaisquer dados. Em seguida, atualizamos a distribuição beta à medida que observamos novos dados.

Para simular a atualização bayesiana, precisamos definir uma função que calcula a função densidade de probabilidade (PDF, probability density function) da distribuição beta. Podemos usar a função math.gamma para calcular a função gama, que é usada na PDF da distribuição beta.

def beta_pdf(x, a, b):
    return (x**(a-1) * (1-x)**(b-1) * math.gamma(a + b)
            / (math.gamma(a) * math.gamma(b)))

Definir a Classe UpdateDist

Em seguida, definimos uma classe chamada UpdateDist que será usada para atualizar a distribuição beta à medida que novos dados são observados. A classe UpdateDist recebe dois argumentos: o objeto de eixo do Matplotlib e a probabilidade inicial de sucesso.

class UpdateDist:
    def __init__(self, ax, prob=0.5):
        self.success = 0
        self.prob = prob
        self.line, = ax.plot([], [], 'k-')
        self.x = np.linspace(0, 1, 200)
        self.ax = ax

        ## Set up plot parameters
        self.ax.set_xlim(0, 1)
        self.ax.set_ylim(0, 10)
        self.ax.grid(True)

        ## This vertical line represents the theoretical value, to
        ## which the plotted distribution should converge.
        self.ax.axvline(prob, linestyle='--', color='black')

O método __init__ inicializa a instância da classe definindo o número inicial de sucessos como zero (self.success = 0) e a probabilidade inicial de sucesso para o valor passado como argumento (self.prob = prob). Também criamos um objeto de linha para representar a distribuição beta e configuramos os parâmetros do gráfico.

O método __call__ é chamado toda vez que a animação é atualizada. Ele simula um experimento de lançamento de moeda e atualiza a distribuição beta de acordo.

def __call__(self, i):
        ## This way the plot can continuously run and we just keep
        ## watching new realizations of the process
        if i == 0:
            self.success = 0
            self.line.set_data([], [])
            return self.line,

        ## Choose success based on exceed a threshold with a uniform pick
        if np.random.rand() < self.prob:
            self.success += 1
        y = beta_pdf(self.x, self.success + 1, (i - self.success) + 1)
        self.line.set_data(self.x, y)
        return self.line,

Se este for o primeiro quadro da animação (if i == 0), redefinimos o número de sucessos para zero e limpamos o objeto de linha. Caso contrário, simulamos um experimento de lançamento de moeda gerando um número aleatório entre 0 e 1 (np.random.rand()) e comparando-o com a probabilidade de sucesso (self.prob). Se o número aleatório for menor que a probabilidade de sucesso, contamos como um sucesso e atualizamos a distribuição beta usando a função beta_pdf. Finalmente, atualizamos o objeto de linha com os novos dados e o retornamos.

Criar Animação

Agora que definimos a classe UpdateDist, podemos criar a animação usando a classe FuncAnimation do Matplotlib. Criamos um objeto de figura e um objeto de eixo e passamos o objeto de eixo para a classe UpdateDist para criar uma nova instância da classe.

fig, ax = plt.subplots()
ud = UpdateDist(ax, prob=0.7)
anim = FuncAnimation(fig, ud, frames=100, interval=100, blit=True)
plt.show()

A classe FuncAnimation recebe vários argumentos:

  • fig: o objeto de figura
  • ud: a instância UpdateDist
  • frames: o número de quadros a serem animados
  • interval: o tempo entre os quadros em milissegundos
  • blit: se deve atualizar apenas as partes do gráfico que foram alteradas

Interpretar os Resultados

A animação mostra como a distribuição beta é atualizada à medida que novos dados são observados. A linha tracejada preta representa a verdadeira probabilidade de sucesso (ou seja, a probabilidade da moeda cair com a face "cara" para cima). À medida que a animação progride, vemos que a distribuição beta começa com um pico na probabilidade a priori de sucesso (0.7) e gradualmente se desloca em direção à verdadeira probabilidade de sucesso à medida que mais dados são observados.

Resumo

Neste laboratório, usamos o Matplotlib para criar uma animação que demonstra a atualização bayesiana. Definimos uma função para calcular a PDF (Função Densidade de Probabilidade) da distribuição beta e uma classe para atualizar a distribuição beta à medida que novos dados são observados. Em seguida, usamos a classe FuncAnimation do Matplotlib para criar a animação e interpretar os resultados.