Machine Learning, R

Naive Bayes: conceito, aplicações e implementação em R

 

O Naive Bayes é um algoritmo para classificação probabilística, baseado no teorema de Bayes.

Enquanto o kNN, que também é um algoritmo para classificação, utiliza a ideia de proximidade (em geral modelada pela distância Euclidiana) para classificar novas entidades, o Naive Bayes usa o conceito de probabilidade para realizar a classificação.

Neste artigo apresento o conceito de probabilidade condicional, o teorema de Bayes, o método do Naive Bayes e como implementá-lo em linguagem R.

 

Probabilidade Condicional

 

Em poucas palavras, probabilidade condicional é a probabilidade de que algo aconteça dado que alguma outra coisa já aconteceu.

O raciocínio para calcular a probabilidade condicional é que: se temos dois eventos A e B, podemos calcular a probabilidade de A acontecer dado que B aconteceu , P(A | B), fazendo a divisão entre a probabilidade de A e B ocorrerem juntos, P(A ∩ B), pela probabilidade de B ocorrer, P(B).

O diagrama a seguir exemplifica este conceito:

 

Teorema de Bayes

 

O teorema de Bayes é um corolário da lei de probabilidade condicional.

Perceba pela fórmula de probabilidade condicional, que podemos representar a probabilidade de intersecção, P(A ∩ B), no formato P(A | B) P(B) ou no formato P(B | A) P(A), visto que P(A ∩ B) = P(B ∩ A):

E é através dessa conclusão que nasce o Teorema de Bayes, representado pela fórmula:

No qual:

P(A)P(B) são chamadas de probabilidades a priori; e

P(A | B) P(B | A) são chamadas de probabilidades a posteriori.

 

Um exemplo para entender a regra de Bayes poderia ser:

A: ter uma doença

B: um teste para esta doença dar positivo.

 

Teríamos então:

Probabilidade de ter a doença dado que o teste deu positivo =

[(Probabilidade do teste dar positivo dado que se tem a doença)*(Probabilidade de ter a doença)] / 

/ (Probabilidade do teste dar positivo, com ou sem doença)

 

Havendo os conceitos de probabilidade condicional e do teorema de Bayes claros, vamos agora ao algoritmo de Naive Bayes e à sua implementação computacional:

 

O algoritmo Naive Bayes

 

Naive, em inglês, significa ingênuo, tolo. Isso é devido ao fato de que o algoritmo assume que existe independência entre as variáveis do conjunto de dados. Em outras palavras, o Naive Bayes considera que o valor de uma variavél não está relacionado ou não é consequência do valor de outra variável.

Em um processo de classificação no qual um exemplar com classe desconhecida seja apresentado, o Naive Bayes tomará a decisão sobre qual é a classe daquele exemplar, por meio do cálculo de probabilidades condicionais. Ele faz isso calculando as probabilidades de ele pertencer à cada uma das diferentes classes existentes no conjunto de treinamento e então classifica o exemplar pela classe com maior probabilidade.

Para tornar mais claro, vamos tomar um exemplo utilizando dados do Titanic, o qual também será usado na implementação computacional em R no final do artigo.

Na tabela a seguir temos as seguintes informações de passageiros que estavam no Titanic: a classe à qual pertenciam, o sexo, a idade e se sobreviveram ou não. Para este exemplo eu usei dados fictícios, mas utilizaremos a tabela real na implementação computacional em R ao final do artigo.

Este é o nosso conjunto de treinamento, que possui 12 observações:

Tomando a variável Sobreviveu como aquela a ser prevista, a implementação do Naive Bayes seria a de criar um modelo probabilístico que faria a previsão se uma pessoa sobreviveria ou não com base na sua classe, sexo e idade.

O primeiro passo a se fazer seria o de calcular as nossas probabilidades a priori:

P(Sim) = 5/12 ; P(Não) = 7/12

 

Em seguida avaliamos cada uma das outras variáveis para o cálculo de probabilidades condicionais. Por exemplo, para a variável Sexo temos que:

P(Masculino | Sobreviveu Sim) = 3/5

P(Masculino | Não Sobreviveu) = 3/7

P(Feminino | Sobreviveu Sim) = 2/5

P(Feminino | Não Sobreviveu) = 4/7

 

E assim repetimos o processo para todas as variáveis, e então, para realizar uma previsão, basta multiplicar todas as probabilidades.

Vamos supor que o nosso conjunto de teste seja um único exemplar e que seja o personagem interpretado por Leonardo DiCaprio no filme Titanic. Teríamos então:

Calculando as probabilidades para este exemplar, teríamos:

P(Sobreviver sim | terceira classe, sexo masculino e idade adulta) = 5/12 * 2/5 * 3/5 * 4/5 = 0,08

P(Não sobreviver | terceira classe, sexo masculino e idade adulta) = 7/12 * 2/7 * 3/7 * 3/7 = 0,03

Assim, o nosso exemplar é classificado pela probabilidade maior, que no caso é a de Sobreviver = sim. O que prova que Jack cabia sim naquela tábua.

 

 

O modelo Naive Bayes é fácil de construir e particularmente útil para conjuntos de dados muito grandes. Juntamente com a simplicidade, Naive Bayes é conhecido por superar outros métodos de classificação altamente sofisticados.

Naive Bayes é comumente usado quando você possui variáveis discretas, ou quando contínuas, seguem uma distribuição conhecida (ainda que abordagens não-paramétricas também possam ser usadas).

Dentre as diferentes aplicações do Naive Bayes, as mais usadas são:

  • Previsão em tempo real: Naive Bayes é um classificador eficiente e bastante rápido. Quando o modelo é implementado para receber dados que são gerados muito rapidamente, como aqueles oriundos de Big Data, o algoritmo pode realizar previsões em tempo real.
  • Previsão multivariada: Este algoritmo também é bem conhecido para o recurso de predição multi-classe. No caso para prever a probabilidade de múltiplas classes de uma variável alvo.
  • Classificação de texto: o classificador Naive Bayes é um dos algoritmos mais bem sucedidos quando se trata da classificação de documentos de texto, ou seja, se um documento de texto pertence a uma ou mais categorias (classes). Devido ao melhor resultado em problemas de várias classes e regras de independência, o Naive Bayes possui maior taxa de sucesso em comparação com outros algoritmos. Dentre as aplicações da classificação de texto, estão:
    • Filtragem de spam: Isso se tornou um mecanismo popular para distinguir o email de spam do e-mail legítimo. Vários serviços de e-mail modernos implementam filtragem de spam bayesiana.
    • Análise do Sentimento: pode ser usado para analisar o caráter de tweets ou postagens de Facebook, comentários e avaliações, sejam eles negativos, positivos ou neutros.
  • Sistema de recomendação: O algoritmo Naive Bayes em combinação com filtragem colaborativa é usado para criar sistemas de recomendação híbridos que ajudam a prever se um usuário gostaria de um determinado recurso ou não.

 

  • Vantagens:
    • Quando a suposição de independência é válida, um classificador Naive Bayes se apresenta melhor comparado a outros modelos, como a regressão logística e você precisa de menos dados de treinamento.
    • É fácil e rápido prever a classe de conjuntos de dados de teste. Ele também funciona bem na previsão de várias classes.
    • Ele funciona bem tanto para variáveis categóricas como para variáveis numéricas (para variáveis numéricas, é assumida a distribuição normal).
  • Desvantagens:
    • Se a variável categórica tiver uma categoria (no conjunto de dados de teste), que não foi observada no conjunto de dados de treinamento, então o modelo atribuirá uma probabilidade de 0 (zero) e será incapaz de fazer uma previsão. Isso geralmente é conhecido como “Frequência zero”. Para resolver isso, podemos usar a técnica de suavização. Uma das técnicas de suavização mais simples é chamada de estimativa de Laplace.
    • Naive Bayes muitas vezes é um estimador ruim, então as saídas de probabilidade de probabilidade não devem ser consideradas seriamente demais.

 

Implementação do Naive Bayes em R

 

O pacote que vamos utilizar aqui para implementar o Naive Bayes é o pacote e1071, e para a criação do modelo utilizamos a função naiveBayes(). Caso você não tenha o pacote instalado, basta executar o comando install.packages(“e1071”). Nosso primeiro passo então é o de carregar o pacote:

library(e1071)

O conjunto de dados que vamos utilizar como exemplo é o Titanic. Este dataset já está presente no base do R (certifique-se que você está com a versão do R atualizada) e possui as mesmas variáveis do exemplo utilizado neste artigo: Classe, Sexo, Idade e Sobrevivência.

data(Titanic)
str(Titanic)

 

Decidi por manter o conjunto de dados no formato table mesmo. Caso você transforme para data frame, use a variável de frequência de cada classe para fazer a divisão do conjunto de dados. Eu coloquei a função para isto no final do código disponível ao final do artigo.

Para construção do modelo, utilizamos a função naiveBayes(). Os parâmetros principais são: 1) a variável cuja classes são o objeto de previsão e que serão as probabilidades a priori; 2) O conjunto de dados de treinamento.

No nosso caso, a nossa variável para o primeiro parâmetro é Survived e o conjunto de dados é o Titanic:

modelo_NB <- naiveBayes(Survived ~., data = Titanic)

 

Se executarmos o objeto modelo_NB, teremos como output os valores das probabilidades a priori  e as probabilidades condicionais das outras variáveis:

 

O nosso conjunto de teste será novamente um exemplar fictício:

exemplar_teste <- data.frame(Class=”1st”, Sex=”Female”, Age=”Adult”)

 

E assim, utilizamos a função predict() para obter o resultado da estimativa.

Dentro da função predict, você pode especificar o parâmetro type = “class” para obter somente a classe prevista, ou type = “raw” para obter a probabilidade para cada uma das classes:

 

A seguir está todo o código em R:

 

 

library(e1071)

data(Titanic)
str(Titanic)

modelo_NB <- naiveBayes(Survived ~., data = Titanic)
modelo_NB

exemplar_teste <- data.frame(Class="1st", Sex="Female", Age="Adult")

predict(modelo_NB, exemplar_teste, type = "class")
predict(modelo_NB, exemplar_teste, type = "raw")



# Caso você queira transformar o conjunto para data.frame e dividir as observações pelas respectivas frequências:
Titanic <- as.data.frame(Titanic)
head(Titanic)

countsToCases <- function(x, countcol = "Freq"){
  idx <- rep.int(seq_len(nrow(x)), x[[countcol]])
  x[[countcol]] <- NULL
  x[idx,]
}

novo_Titanic <- countsToCases(as.data.frame(Titanic))

 

 


 

Espero que você tenha gostado deste artigo e que ele possa ter sido bastante útil para você.

Até a próxima!