BLiTZ — Uma lib de Deep Learning Bayesiano no PyTorch

Simples e extensível para criar camadas de Deep Learning Bayesiano no PyTorch

Piero Esposito
Turing Talks
6 min readJun 14, 2020

--

Ilustração para regressão bayesiana. Fonte: https://ericmjl.github.io/bayesian-deep-learning-demystified/images/linreg-bayesian.png (Acessado em 2020–03–30)

Esse post é uma tradução de BLiTZ — A Bayesian Neural Network library for PyTorch, escrito por mim e publicado no towards data science.

O link para o repositório da lib é: https://github.com/piEsposito/blitz-bayesian-deep-learning.

Neste post, vamos apresentar como usar a primeira lib de Deep Learning feita por um membro do Grupo Turing — e focaremos mais no uso dessa lib do que na teoria do Deep Learning Bayesiano. Se você for novo no tema, pode querer procurar um dos inúmeros posts do Medium sobre ele ou ir à seção da documentação da lib dedicada a teoria.

Existe uma demanda crescente, tanto no mercado como no meio acadêmico, para formas de extrair a confiabilidade de predições de modelos de Deep Learning. As redes neurais Bayesianas surgiram como uma abordagem bem intuitiva para resolver essa demanda — e isso se confirma pelo fato de aparecerem cada vez mais como “trending-topic” em Deep Learning.

Ocorre que, a despeito de o PyTorch estar ganhando cada vez mais espaço como um framework (de pesquisa principalmente) de Deep Learning, não há nenhuma lib que permita que se introduza camadas Bayesianas de redes neurais de forma fácil como se faz com a nn.Linear e nn.Conv2d, por exemplo.

Logicamente, isso cria um gargalo para qualquer um que queira iterar de forma flexível com abordagens Bayesianas em suas modelagens de dados, assim como para qualquer um que tenha que criar camadas Bayesianas do zero em detrimento de focar na arquitetura e hiperparâmetros do modelo.

A BLiTZ veio para resolver esse gargalo. Ao ser completamente integrada com o PyTorch (incluindo os módulos nn.Sequential ) e fácil de se extender, nossa lib deixa o usuário introduzir incerteza em suas redes neurais sem muito esforço, podendo focar mais na arquitetura e hiperparâmetros do modelo.

Neste post, vamos discutir como treinar e inferir sobre modelos de redes neurais Bayesianas com incerteza em seus pesos.

Camadas de Deep Learning Bayesiano

Como se sabe, a ideia principal em Deep Learning probabilístico é a de, ao invés de se ter pesos determinísticos (isso é, aquele tensor de pesos), a camada tem uma distribuição de probabilidade para seus pesos que, a cada operação feedforward, são extraídos com processo de sampling dessa distribuição.

Consequentemente os parâmetros treináveis dessas camadas bayesianas são a média e a variância da distribuição (para cada escalar que compõe o tensor).

Matematicamente as operações vão de:

Operação de feedforward em rede neural determinística.

Para:

Operação feedforward para camada bayesiana de rede neural.

Implementar no PyTorch camadas onde nossos ρ e μ são parâmetros treináveis pode ser complicado — e fazer com que sejam integradas com o resto do framework é pior ainda. Vamos mostrar como facilmente podemos usar a camada linear Bayesiana BayesianLinear do BLiTZ, que pode ser facilmente integrada no modelo:

O modelo que essa classe representa funciona como um nn.Module simples do PyTorch, mas sua camada BayesianLinear vai fazer a inferência e ser treinada levando em consideração a incerteza explicada acima.

Função custo

Conforme proposto no paper que introduziu as redes Bayesianas, a função custo é uma combinação do custo de “fitting nos dados” com um “custo de complexidade”, isso é, que mede quanta incerteza está presente nessa distribuição.

Esse custo de complexidade é a verossimilhança das predições obtidas pela amostragem da distribuição numa função densidade de probabilidade P(x) bem mais simples que a que define nossos pesos. Adotamos como Q(x) a função que corresponde à operação feedforward que nossa rede neural aplica sobre os inputs para obter a predição.

Extrair um custo de complexidade dependente do tensor de pesos da camada é algo que exige a manipulação do framework de Deep Learning a ser usado num nível de abstração bem baixo, o que pode ser complicado e demandar tempo.

Para evitar esse problema, BLiTZ traz um decorator, variational_estimator , que adiciona um método para extrair a soma dos custos de complexidade de todas as camadas Bayesianas do modelo.

Para extraí-la, esse custo do modelo, é simples assim:

Para otimizar o modelo

Redes neurais bayesianas costumam ser otimizadas fazendo uma amostragem da loss várias vezes e depois o backprop. Isso acontece porque, como nossos pesos não são determinísticos, fazemos uma estimação da nossa predição por métodos de Monte Carlo (isto é, vários feedforwards, cada um com os pesos extraídos da distribuição, e depois a média).

Isso também pode complicar a vida do praticante de Deep Learning, e para isso, o decorator variational_estimator introduz também o método sample_elbo (Evidence Lower Bound, nome atribuído a função custo em Deep Learning Bayesiano).

Com esse método, introduzido o criterion (objeto do Torch que calcula a função custo), os inputs , labels e sample_nbr (número de operações feedforward para obter o custo), é possível calcular o custo sem verbosidade no código. Veja só como é fácil otimizar uma rede usando BLiTZ:

Pra terminar, um exemplo completo

Agora vamos mostrar um exemplo, passo a passo, de como usar BLiTZ para criar uma rede neural Bayesiana e estimar intervalos de confiança para os preços do toy-dataset de preços de casa de Boston. Isso corresponde a esse exemplo, da lib. Se você quiser ver os outros, estão aqui.

Imports necessários

Além dos imports usuais de quando se usa PyTorch, vamos importar, da BLiTZ, o decorator variational_estimator , que vai nos ajudar a performar as operações específicas de Deep Learning Bayesiano sem afetar a integração com o PyTorch e, é claro, BayesianLinear , que é nossa camada Bayesiana correspondente à nn.Linear do PyTorch.

Carregando e pré-processando os dados

Nada de novo sob o Sol aqui, vamos só importar e fazer aquele scaling básico nos dados:

Criando a classe do regressor

Vamos criar nossa classe herdando de nn.Module como normalmente se faz com PyTorch. Nosso decorator vai introduzir de forma não invasiva o que precisamos para operar essa rede neural como Bayesiana. Pra isso, duas camadas, já que os dados são simples e queremos ter resultados rápido.

Uma função para avaliar o intervalo de confiança da predição

Para poder avaliar nosso modelo, queremos ver a precisão de nosso intervalo de confiança.

Criamos então uma função que performa, nos dados de teste, a operação feedforward X vezes e depois, escolhendo um multipicador para o desvio padrão, vemos se os valores corretos estão dentro do intervalo (média — multiplicador * desvio padrão, média + multiplicador * desvio padrão).

Criando o regressor e carregando os dados em DataLoaders do PyTorch

Note que, a despeito do decorator, criamos nosso BayesianRegressor como faríamos com um nn.Module — e o usaremos da mesma forma:

Loop de treinamento e avaliação

Nosso loop de treinamento segue, em grande parte, o que se faz em treinamentos padrão no PyTorch — a única diferença é que obtemos nosso custo com o método sample_elbo . O resto das operações é feito normalmente.

Decidimos, por fim, que a cada 100 iterações ele vai printar o custo e acurácia de nosso intervalo de confiança.

Conclusão

A BLiTZ é uma lib útil para iterar experimentos em Deep Learning Bayesiano sem muito esforço. Bem integrado com PyTorch e com poucas mudanças para o código usual, é bem intuitivo para o usuário comum do framework usar sem muita dor de cabeça, podendo extrair o custo de complexidade e obter amostras do custo sem muito trabalho.

Por fim, aqui está novamente o link para o nosso repo: https://github.com/piEsposito/blitz-bayesian-deep-learning. Se você gostou, deixe seus claps e uma estrelinha lá no repositório — isso ajuda muito nosso trabalho a ter mais visibilidade e ajudar mais pessoas com seus experimentos em Deep Learning.

Referências

--

--

Piero Esposito
Turing Talks

Google Developer Expert in Machine Learning and Machine Learning Engineer @ Sticker Mule; I’m your friendly neghborhood nerdy guy.