Em problemas de classificação queremos encontrar a hipótese “h” para um determinada observação “o”, ou seja, queremos definir/prever uma classe para um dada observação. Uma maneira de se fazer isso é analisando o histórico dos dados e assim calcular a probabilidade para a hipótese “h”. Essa é a ideia básica por trás do teorema de Bayes.

O teorema de Bayes é dado pela equação: P(h|o) = P(o|h) x P(h) / P(o), onde:

  • P(h|o) é a probabilidade da hipótese “h” dado a observação “o”. Isso é conhecido como probabilidade posterior
  • P(o|h) é a probabilidade da observação o dado que a hipótese “h” é verdadeira
  • P(h) é a probabilidade de hipótese “h” ser verdadeira (independentemente dos dados). Isso é conhecido como probabilidade anterior de “h
  • P(o) é a probabilidade da observação “o” (independentemente da hipótese)

Como podemos observar, estamos interessados na probabilidade posterior de “h” dado “o”. Pode parecer confuso a princípio, mas veja que faz todo sentido: Depois de calcular a probabilidade de várias hipóteses “h” (várias classes) devemos selecionar aquela com a maior probabilidade e associá-la a observação. Esta lógica é conhecida como MAP (Maximum a Posteriori).

Podemos definir MAP formalmente como: MAP(h) = max(P(h|o)), ou seja, a maior probabilidade calculada para cada classe, se escrevermos todas as fórmulas temos: MAP(h) = P(o|h) x P(h) / P(o) [veja que é apenas a junção das duas equações anteriores].

Note que o termo P(o) refere-se a probabilidade de observação independente da hipótese e por isso deve ser um valor constante. Na prática este termo pode ser retirado da equação.

Note também que o termo P(h) também é um valor constante, pois é a probabilidade de cada classe (de acordo com o conjunto de dados). Este termo também pode ser retirado da equação.

Assim, a equação final da probabilidade posterior de “h” é dada por MAP (h) = max (P(o|h)).

Classificador Naive Bayes

Naive Bayes é um algoritmo de classificação binária ou multi classe. Ele é conhecido como Naive Bayes ou Idiot Bayes porque o cálculo da probabilidade de cada hipótese (classe) foi simplificado para que pudesse ser rastreado. É isso mesmo, então se você achava que o algoritmo era super complexo, na verdade ele foi simplificado para facilitar o seu entendimento (e isso está muito longe de dizer que o algoritmo não é útil, muito pelo contrário).

Ao invés de calcular o valor das probabilidades relacionando cada atributo P (o1, o2, o3|h), o algoritmo assume que as probabilidades são condicionalmente independentes dada a variável resposta, sendo P(o1|h) x P(o2|h) e assim por diante. Esta é uma premissa muito forte do algoritmo, pois basicamente ele diz que os atributos não interagem entre si (coisa que não é tão comum no mundo real).

Um classificador Naive Bayes é representado por probabilidades, ou seja, ao terminar o modelo teremos uma lista de probabilidades que serão usadas para fazer as previsões nos dados novos. Estas probabilidades são:

  • Probabilidade da classe: A probabilidade de cada classe no conjunto de dados de treino
  • Probabilidade condicional: A probabilidade condicional de cada atributo dado cada classe.

Treinando um classificador Naive Bayes

Treinar um classificador Naive Bayes é relativamente rápido porque não precisamos encontrar coeficientes ou coisas do tipo. As únicas coisas que precisamos calcular é a probabilidade de cada classe e a probabilidade condicional de cada classe dada a observação “o”.

Para calcular a probabilidade de cada classe basta somar a quantidade de observações que pertencem à classe e dividir pelo total de observações existentes.

P (classe 1) = quantidade de observações da classe 1 / total de observações

Já a probabilidade condicional é a frequência de cada atributo para uma determinada classe dividido pela quantidade de observações daquela classe. Vamos exemplificar.

Imagine que queremos calcular a probabilidade do cliente sair da empresa (famoso churn) de acordo com a variável “reclamou”, que informa se o cliente alguma vez já reclamou do serviço ou não. Neste casos temos:

P (input = reclamou | classe = saiu) =
Quantidade (input = reclamou AND classe = saiu) / Quantidade (classe = saiu)
P (input = não reclamou | classe = saiu) =
Quantidade (input = não reclamou AND classe = saiu) / Quantidade (classe = saiu)
P (input = reclamou | classe = não saiu) =
Quantidade (input = reclamou AND classe = não saiu) / Quantidade (classe = não saiu)
P (input = não reclamou | classe = não saiu) =
Quantidade (input = não reclamou AND classe = não saiu) / Quantidade (classe = não saiu)

Lembre bem dessas probabilidades, pois é tudo que você precisa para aplicar o teorema de Bayes.

Fazendo previsões com um classificador Naive Bayes

Muito bem, uma vez que você calculou todas estas probabilidades que acabaram de ser citadas, tudo que o precisa fazer é usá-las em dados novos para fazer a classificação. Vamos usar estes valores dentro do teorema de Bayes para fazer as predições:

MAP(h) = max (P(o|h) x P(h))

Imagine que entramos com um novo registro cujo valor do input é “reclamou”. Neste caso temos que usar duas das fórmulas citadas anteriormente (referente ao input = reclamou):

P (input = reclamou | classe = saiu) =
Quantidade (input = reclamou AND classe = saiu) / Quantidade (classe = saiu)
P (input = reclamou | classe = não saiu) =
Quantidade (input = reclamou AND classe = não saiu) / Quantidade (classe = não saiu)

Finalmente basta escolher a classe com o maior valor de probabilidade. Note que este problema é bem simples, pois temos apenas um único input. Em problemas reais costumamos usar mais de um input para explicar a relação entre as variáveis independentes e a resposta. Não muda muita coisa, basta adicionar o novo input à fórmula (imagine que nosso segundo input é estado civil):

P (sair) =
P (input1 = reclamou | classe = saiu) x P (input2 = solteiro | classe = saiu)
x P (classe = saiu)

Adaptando o Naive Bayes para valores de entrada numéricos

Se você ainda não se perguntou, certamente faria esta pergunta quando estivesse colocando a mão na massa: o que acontece quando o atributo de entrada é um valor numérico (real)? Até agora só trabalhamos com inputs categóricos, certo?

O classificador Naive Bayes possui uma adaptação para dados numéricos que é referida como Gaussian Naive Bayes. Para este tipo de variável, o algoritmo assume que a mesma possui uma distribuição Gaussiana ou normal.

Outras distribuições poderiam ser utilizadas. Porém com a distribuição Gaussiana as cosas ficam mais fáceis, pois tudo que precisamos fazer é calcular a média e o desvio padrão da variável numérica (ou das variáveis, caso tenha mais do que uma) para cada classe resposta.

Acredito que você já esteja familiarizado com o cálculo da média, então vou reforçar apenas o cálculo do desvio padrão:

desviopadrao

As probabilidades são calculadas por meio de uma Gaussian Probability Density Function (PDF):

pdf

A função parece um pouco complicada, mas note que se abstrairmos sua complexidade e voltarmos à lógica do modelo, é simples que entender. Vamos voltar ao nosso modelo de churn, mas agora temos duas variáveis para prever se o cliente vai sair da empresa:

P (sair) =
P (input1 = reclamou | classe = saiu) x P (pdf(RendaMensal) | classe = saiu)
x P (classe = saiu)

Informações adicionais sobre Naive Bayes

Algumas informações que vale a pena destacar:

  • Se a sua variável de entrada for do tipo numérico (valor real), então o algoritmo assumirá que a mesma segue uma distribuição normal. Portanto, remover outliers pode ser uma boa ideia para fazer com que a distribuição da variável se aproxime mais de uma curva normal.
    Adicionalmente você pode usar alguma função kernel de densidade para especificar um outro tipo de distribuição.
  • Você pode atualizar as probabilidades do seu modelo conforme novos dados surgem. Isso ajudará a manter o modelo atualizado.
  • O cálculo das probabilidades de cada classe consiste na multiplicação de pequenos números, o que eventualmente pode ocasionar erros de precisão numérica ou até mesmo overflow. Uma boa prática para evitar este problema é usar a transformação logarítmica das probabilidades.

Implementando Naive Bayes do zero

Ok, chega de teoria e vamos implementar o Naive Bayes do zero! Retirei este exemplo de um livro chamado Master Machine Learning Algorithm, Jason Brownlee. Todos os créditos pra ele porque o cara é muito bom.

Este será o nosso dataset. Você também pode baixa-lo no link de download no final deste artigo.

Weather Car Class
sunny working go-out
rainy broken go-out
sunny working go-out
sunny working go-out
sunny working go-out
rainy broken stay-home
rainy broken stay-home
sunny working stay-home
sunny broken stay-home
rainy broken stay-home

Para facilitar as coisas vamos transformar as variáveis categóricas em variáveis numéricas, então usaremos o dataset abaixo para modelagem.

Weather Car Class
1 1 1
0 0 1
1 1 1
1 1 1
1 1 1
0 0 0
0 0 0
1 1 0
1 0 0
0 0 0

O primeiro passo é calcular a probabilidade de cada classe, para isso basta contar quantas ocorrências existem na classe 1 e dividir pelo total de ocorrências.

Classe 1 = 5/10 = 50%
Classe 2 = 5/10 = 50%

Agora vamos calcular as probabilidades condicionais, que são as probabilidade de cada input para cada classe. A fórmula geral é:

P (input = X | class = Y) = quantidade (input = X E class = Y) / quantidade (class = Y)

No nosso caso temos:

P (weather = sunny | class = go-out) = 0.8
P (weather = rainy | class = go-out) = 0.2
P (weather = sunny | class = stay-home) = 0.4
P (weather = rainy | class = stay-home) = 0.6
P (car = working | class = go-out) = 0.8
P (car = broken | class = go-out) = 0.2
P (car = working | class = stay-home) = 0.2
P (car = broken | class = stay-home) = 0.8

Agora temos tudo que precisamos para fazer previsões. Neste caso, vamos usar o próprio dataset de teste para fazer as previsões e verificar se nosso modelo está acertando. Num cenário real, é recomendado separar uma parte dos seus dados apenas para usar nesta parte do teste.

Como descrito na parte prática, vamos usar a seguinte fórmula para fazer as predições:

MAP(h) = max (P (o|h) x P(h))

Na prática, faremos a predição de cada linha para cada classe. A classe com maior valor de probabilidade será escolhida como resposta. Para fazer a predição da linha 1, onde weather = sunny e car = working, temos:

go-out = P (weather = sunny | class = go-out) x P (car = working | class = go-out) x P (class = go-out)
go-out = 0.8 x 0.8 x 0.5 -> 0.32
stay-home =P (weather = sunny | class = stay-home) x P (car = working | class = stay-home) x P (class = stay-home)
stay-home = 0.4 x 0.2 x 0.5 -> 0.04

Como podemos ver, a probabilidade da classe go-out é maior do que a probabilidade da classe stay-home, logo a resposta para a linha 1 é go-out. O processo se repete para cada linha do dataset, até que tenhamos todas as predições calculadas.

Veja a lógica completa no arquivo Excel disponível para download. Não vou postar aqui o passo para variáveis com valores reais, mas basta seguir o que foi dito na parte teórica. Você também pode comprar o material do Jason Brownlee para ver a implementação de outros algoritmos do zero.

No material anexo existem duas estratégias de cálculo (planilha “modelo”, ambas chegam ao mesmo resultado). A diferença é a ordem em que as probabilidades condicionais são calculadas. A segunda estratégia foi uma contribuição do Grimaldo Oliveira, consultor de Business Intelligence e Analytics.

Faça download do dataset e da lógica implementada

Grande abraço!
Weslley Moura

Sobre o Autor: Weslley Moura

Mestre em engenharia da computação, professor de cursos relacionados a análise de dados e co-fundador da empresa Pepsoft Sistemas. Profissional apaixonado pela ciência existente nos dados e suas aplicações práticas. Nos últimos anos vem dedicando seu tempo a projetos de aprendizagem de máquina e mantém seu site pessoal com dicas e aulas relacionadas ao tema em Hacking Analytics.

3 comentários

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

w

Conectando a %s