Path: blob/master/site/pt-br/probability/examples/Modeling_with_JointDistribution.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
Licensed under the Apache License, Version 2.0 (the "License");
Modelagem bayesiana com distribuição conjunta
JointDistributionSequential
é uma classe de distribuições recém-lançada que permite aos usuários fazer um protótipo rápido de um modelo bayesiano. Ela permite encadear diversas distribuições e usar a função lambda para introduzir dependências. Essa classe foi concebida para criar modelos bayesianos de tamanho pequeno a médio, incluindo diversos modelos usados com frequência, como GLMs, modelos de efeitos mistos, modelos de mistura e muitos outros. Essa classe conta com todos os recursos necessários para um workflow bayesiano, como amostragem preditiva a priori. É possÃvel usá-la como componente de outro modelo gráfico bayesiano maior ou de uma rede neural. Neste Colab, mostraremos alguns exemplos de como utilizar JointDistributionSequential
para fazer seu workflow bayesiano cotidiano.
Dependências e pré-requisitos
Vamos acelerar as coisas!
Antes de prosseguirmos, vamos usar uma GPU para a demonstração.
Para fazer isso, selecione "Runtime" -> "Change runtime type" (Alterar tipo de runtime) -> "Hardware accelerator" (Acelerador de hardware) -> "GPU".
O seguinte trecho de código verificará se temos acesso a uma GPU.
Observação: se, por algum motivo, você não conseguir acessar uma GPU, este Colab ainda funcionará (mas o treinamento levará mais tempo).
JointDistribution
Observação: esta classe de distribuições é útil quando você tem apenas um modelo simples. Aqui, "simples" significa grafos tipo cadeia, embora, tecnicamente, a estratégia funcione para qualquer PGM com grau máximo de 255 para a um único nó (porque as funções Python podem ter no máximo essa quantidade de argumentos).
A ideia básica é fazer o usuário especificar uma lista de callable
s que gerem instâncias de tfp.Distribution
, uma para cada vértice em seu PGM. O callable
terá no máximo o número de argumentos de seu Ãndice na lista (para conveniência dos usuários, os argumentos são passados na ordem inversa de criação). Internamente, vamos "percorrer o grafo" simplesmente passando o valor anterior de cada variável aleatória para cada callable. Ao fazer isso, implementamos a [regra da cadeia de probabilidade](https://en.wikipedia.org/wiki/Chain_rule_(probability)#More_than_two_random_variables): ParseError: KaTeX parse error: Expected '}', got '&' at position 40: … p(x_i|x{/em4}{&̲lt;i}).
A ideia é bem simples, mesmo com código Python. Veja o básico:
Estão disponÃveis mais informações na documentação de JointDistributionSequential
, mas a essência é que você passa uma lista de distribuições para inicializar a classe; se algumas distribuições na lista dependerem da saÃda de outra distribuição/variável upstream, basta encapsulá-las com uma função lambda. Agora, vamos ver como isso funciona!
Regressão linear (robusta)
Na documentação do PyMC3: GLM – Regressão robusta com detecção de ponto fora da curva.
Modelo MQO (mÃnimos quadrados ordinários) convencional
Agora, vamos criar um modelo linear, um problema simples de intercepto + regressão de declive:
Você pode verificar o grafo do modelo para ver a dependência. Observe que x
é reservado como o nome do último nó, e você não pode usá-lo como argumento lambda em seu modelo de JointDistributionSequential.
A amostragem do modelo é bem simples e direta:
...que fornece uma lista de tf.Tensors. Você pode usá-la imediatamente na função log_prob para computar a log-probabilidade do modelo:
Parece que tem algo errado: deverÃamos obter uma log-probabilidade escalar! Podemos avaliar mais a fundo para ver se há algum problema ao chamar .log_prob_parts
, que fornece a log_prob
de cada nó no modelo gráfico:
...descobrimos que o último nó não está sofrendo reduce_sum ao longo do eixo/dimensão independente e identicamente distribuÃdo. Quando fazemos a soma das duas primeiras variáveis, é feito um broadcast incorreto.
O truque é usar tfd.Independent
para reinterpretar o formato do lote (para que o resto do eixo seja reduzido corretamente):
Agora, vamos verificar o último nó/distribuição do modelo. Você verá que agora o formato do evento foi interpretado corretamente. Observe que pode ser necessário fazer tentativa e erro para obter o reinterpreted_batch_ndims
correto, mas é fácil exibir via print a distribuição ou o tensor amostrado para verificar novamente o formato.
Outras APIs JointDistribution*
Estimativa da máxima verossimilhança
E agora podemos fazer a inferência. Você pode usar o otimizador para encontrar a estimativa da máxima verossimilhança.
Versão do modelo em lotes e MCMC
Na inferência bayesiana, geralmente queremos trabalhar com amostras MCMC, pois, quando as amostras são da distribuição posterior, podemos usá-las em qualquer função para computar expectativas. Entretanto, a API de MCMC requer modelos que possam ser divididos em lotes, e podemos verificar se nosso modelo não pode ser dividido em lotes chamando sample([...])
Neste caso, é relativamente simples, pois temos somente uma função linear dentro do modelo, e expandir o formato deve ser suficiente:
Podemos amostrar novamente e avaliar log_prob_parts para fazer algumas checagens:
Algumas observações:
Queremos trabalhar com a versão do modelo dividido em lotes porque é mais rápido para o MCMC multicadeia. Nos casos em que você não pode reescrever o modelo como uma versão em lotes (como modelos de equação diferencial ordinária), você pode mapear a função log_prob usando
tf.map_fn
para conseguir o mesmo efeito.mdl_ols_batch.sample()
talvez não funcione, pois temos um prior de escalar e não podemos fazerscaler_tensor[:, None]
. A solução é expandir o tensor escalar para o posto 1 encapsulandotfd.Sample(..., sample_shape=1)
.É uma boa prática escrever o modelo como uma função para que você possa alterar as configurações, como hiperparâmetros, com muito mais facilidade.
MCMC usando o No-U-Turn Sampler
Teste T de Student
Observe que, a partir de agora, vamos sempre trabalhar com a versão do modelo dividido em lotes.
Amostra para frente (amostragem preditiva a priori)
Estimativa da máxima verossimilhança
MCMC
Pooling parcial hierárquico
Dos dados de beisebol para 18 jogadores de Efron e Morris (1975) do PyMC3:
Amostra para frente (amostragem preditiva a priori)
Novamente, se você não usar tfd.Independent, observe como acabará com uma log_prob com o batch_shape errado.
Estimativa da máxima verossimilhança
Um recurso incrÃvel de tfp.optimizer
é que você pode otimizar em paralelo para o lote k do ponto de partida e especificar o kwarg stopping_condition
: você pode defini-lo como tfp.optimizer.converged_all
para ver se todos encontram o mesmo mÃnimo ou tfp.optimizer.converged_any
para encontrar uma solução local rapidamente.
LBFGS não convergiu.
MCMC
Modelo de efeitos mistos (Radon)
O último modelo na documentação do PyMC3: Cartilha sobre métodos bayesianos para modelagem multinÃvel.
Algumas alterações na distribuição a priori (escala menor, etc.):
Para modelos com transformação complexa, implementá-la de uma forma funcional deixaria a escrita de código e o teste muito mais fáceis. Além disso, facilita bastante a geração programática da função log_prob condicionada a um minilote dos dados de entrada:
Inferência variacional
Um recurso muito poderoso de JointDistribution*
é que você pode gerar uma aproximação para inferência variacional com facilidade. Por exemplo: para fazer inferência variacional com diferenciação automática e teoria do campo médio, basta inspecionar o grafo e substituir todas as distribuições não observadas por uma distribuição normal.
Inferência variacional com diferenciação automática e teoria do campo médio
Você também pode usar o recurso experimental em tensorflow_probability/python/experimental/vi para fazer aproximação variacional, que basicamente é a mesma lógica usada abaixo (isto é, usar JointDistribution para fazer aproximação), porém com a saÃda da aproximação no espaço original em vez de no espaço não limitado.
Inferência variacional com diferenciação automática de posto completo
Para inferência variacional com diferenciação automática de posto completo, queremos aproximar a distribuição posterior com uma gaussiana multivariada.
Modelo misturado beta-Bernoulli
Um modelo misturado em que diversos revisores rotulam alguns itens com rótulos latentes desconhecidos (verdadeiros).