Naïve Bayes

Prof. Letícia Raposo

CARACTERÍSTICAS O que é o Naïve Bayes?

  • Uma família de classificadores probabilísticos baseados no teorema de Bayes.
  • Parte de um pressuposto de independência entre as variáveis — daí o nome naïve (ingênuo).
  • Serve para classificação binária e multiclasse.

CARACTERÍSTICAS Da distância à probabilidade

flowchart TB
    subgraph KNN["k-NN: distância"]
      direction LR
      k1(["novo<br/>exemplo"]) --> k2["mede distâncias<br/>aos exemplos de treino"] --> k3["vizinhos<br/>mais próximos"] --> k4(["voto da<br/>maioria"])
    end
    subgraph NB["Naïve Bayes: probabilidade"]
      direction LR
      n1(["novo<br/>exemplo"]) --> n2["calcula P(classe | exemplo)<br/>para cada classe"] --> n3(["classe mais<br/>provável"])
    end
    classDef ini fill:#C9DCEE,stroke:#1B4F7A,color:#12283F
    classDef passo fill:#F3F7FB,stroke:#8FB6D9,color:#12283F
    classDef fim fill:#12283F,stroke:#12283F,color:#ffffff
    class k1,n1 ini
    class k2,k3,n2 passo
    class k4,n3 fim
    style KNN fill:#ffffff,stroke:#C9DCEE,color:#6B7280
    style NB fill:#ffffff,stroke:#1B4F7A,color:#12283F
    KNN ~~~ NB

O k-NN compara o novo exemplo com pontos do treino; o Naïve Bayes compara-o com um resumo probabilístico de cada classe.

FUNDAMENTOS O teorema de Bayes

\[P(B \mid A) = \frac{P(A \mid B)\, P(B)}{P(A)}\]

  • Trata de problemas em que queremos a probabilidade de um evento dada uma condição: a probabilidade de \(B\), sabendo que \(A\) já ocorreu.
  • De onde vem? A probabilidade conjunta pode ser escrita de duas formas:

\[P(A \cap B) = P(B \mid A)\,P(A) = P(A \mid B)\,P(B)\]

Basta isolar \(P(B \mid A)\).

EXEMPLO Determinar se uma pessoa está gripada

Variáveis explicativas: coriza, tosse, febre, dor muscular, dor de garganta.

Variável resposta: gripe (sim/não).

Um paciente chega com:

  • Coriza = Sim
  • Tosse = Frequente
  • Febre = Alta
  • Dor muscular = Sim
  • Dor de garganta = Não

Qual a probabilidade de ele estar gripado?

FUNDAMENTOS As quatro peças do teorema

flowchart LR
    PR["<b>Prior</b><br/>P(Gripe)<br/><i>quão comum é a gripe</i>"] --> X(("×"))
    VE["<b>Verossimilhança</b><br/>P(sintomas | Gripe)<br/><i>quão típicos são esses<br/>sintomas entre os gripados</i>"] --> X
    X --> D(("÷"))
    EV["<b>Evidência</b><br/>P(sintomas)<br/><i>quão comuns são esses<br/>sintomas em geral</i>"] --> D
    D --> PO["<b>Posterior</b><br/>P(Gripe | sintomas)<br/><i>o que queremos saber</i>"]
    classDef prior fill:#C9DCEE,stroke:#8FB6D9,color:#12283F
    classDef veros fill:#8FB6D9,stroke:#3A7CB0,color:#12283F
    classDef evid fill:#F3F7FB,stroke:#C9DCEE,color:#6B7280
    classDef post fill:#12283F,stroke:#12283F,color:#ffffff
    classDef op fill:#ffffff,stroke:#3A7CB0,color:#12283F
    class PR prior
    class VE veros
    class EV evid
    class PO post
    class X,D op

\[\underbrace{P(y_i \mid \mathbf{x})}_{\text{posterior}} = \frac{\overbrace{P(\mathbf{x} \mid y_i)}^{\text{verossimilhança}}\;\overbrace{P(y_i)}^{\text{prior}}}{\underbrace{P(\mathbf{x})}_{\text{evidência}}}\]

NAÏVE BAYES Por que “ingênuo”?

Ingênuo (naïve)

Assume que os valores dos atributos de um exemplo são independentes entre si, dada a classe — o que torna o cálculo muito mais fácil.

Eventos independentes

  • A ocorrência de \(A\) em nada interfere na probabilidade de \(B\).
  • A probabilidade de ambos ocorrerem é o produto: \(P(A \cap B) = P(A)\,P(B)\).

Faz sentido supor que tosse e febre são independentes? Em geral, não — mas o Naïve Bayes supõe isso dentro de cada classe (entre os gripados e entre os não gripados), e mesmo assim costuma funcionar bem.

NAÏVE BAYES A verossimilhança vira um produto

%%{init: {"flowchart": {"nodeSpacing": 12, "rankSpacing": 28}}}%%
flowchart TB
    J["<b>P(sintomas | Gripe)</b><br/><i>conjunta: difícil de estimar</i>"]
    J -- "independência<br/>dada a classe" --> PROD
    subgraph PROD[" "]
      direction LR
      F1["P(coriza<br/>| gripe)"] --- M1(("×")) --- F2["P(tosse<br/>| gripe)"] --- M2(("×")) --- F3["P(febre<br/>| gripe)"] --- M3(("×")) --- F4["P(dor muscular<br/>| gripe)"] --- M4(("×")) --- F5["P(sem dor de<br/>garganta | gripe)"]
    end
    classDef conj fill:#12283F,stroke:#12283F,color:#ffffff
    classDef fator fill:#C9DCEE,stroke:#3A7CB0,color:#12283F
    classDef op fill:#F3F7FB,stroke:#F3F7FB,color:#1B4F7A,font-size:22px
    class J conj
    class F1,F2,F3,F4,F5 fator
    class M1,M2,M3,M4 op
    style PROD fill:#F3F7FB,stroke:#C9DCEE

Em vez de uma probabilidade conjunta difícil de estimar, multiplicamos cinco probabilidades simples — cada uma obtida por contagem.

NAÏVE BAYES Em fórmulas

Dada a classe, \(P(\mathbf{x} \mid y_i)\) se decompõe em \(P(x^1 \mid y_i) \times \cdots \times P(x^d \mid y_i)\):

\[P(y_i \mid \mathbf{x}) = \frac{P(\mathbf{x} \mid y_i)\,P(y_i)}{P(\mathbf{x})} = \frac{\prod_{j=1}^{d} P(x^j \mid y_i)\; P(y_i)}{P(\mathbf{x})}\]

O denominador \(P(\mathbf{x})\) é o mesmo para todas as classes, então pode ser ignorado na comparação:

\[P(y_i \mid \mathbf{x}) \;\propto\; P(y_i) \prod_{j=1}^{d} P(x^j \mid y_i)\]

  • A hipótese de independência entre atributos é quase sempre violada…
  • … mas, na prática, o classificador Naïve Bayes se mostra bastante robusto: para decidir, basta que a classe certa tenha o maior valor, mesmo que as probabilidades não sejam exatas.

NAÏVE BAYES Regra de decisão: MAP

Calculamos o posterior (não normalizado) para cada classe e escolhemos o maior — estimativa por MAP (Maximum A Posteriori):

\[\hat{y} = \underset{y_i \in \{\text{classes}\}}{\arg\max}\; P(y_i) \prod_{j=1}^{d} P(x^j \mid y_i)\]

  • Se as classes têm o mesmo número de observações no treino, \(P(y_i)\) é igual para todas e também pode ser descartado:

\[\hat{y} = \underset{y_i}{\arg\max}\; \prod_{j=1}^{d} P(x^j \mid y_i)\]

  • Se quisermos as probabilidades propriamente ditas, basta normalizar: dividir o valor de cada classe pela soma de todas.

NAÏVE BAYES Por que usar logaritmos?

  • Multiplicar muitas probabilidades pequenas gera valores ainda menores — o computador acaba arredondando para zero (underflow).
  • Como o log é crescente, ele preserva qual classe tem o maior valor — e transforma o produto em soma:

\[\hat{y} = \underset{y_i}{\arg\max}\; \Big[\log P(y_i) + \sum_{j=1}^{d} \log P(x^j \mid y_i)\Big]\]

NAÏVE BAYES Funcionamento

flowchart LR
    subgraph TREINO["① Treinamento"]
      direction TB
      T1[("Conjunto de<br/>treinamento")] --> T2["Prior de cada classe<br/>P(y)"]
      T1 --> T3["Tabelas de probabilidade<br/>P(atributo = valor | y)"]
    end
    subgraph CLASSIF["② Classificação"]
      direction TB
      N(["Novo exemplo x"]) --> C1["Classe 1<br/>P(y₁) × ∏ P(xʲ | y₁)"]
      N --> C2["Classe 2<br/>P(y₂) × ∏ P(xʲ | y₂)"]
      N --> C3["… Classe n<br/>P(yₙ) × ∏ P(xʲ | yₙ)"]
      C1 --> R{{"maior valor (MAP)"}}
      C2 --> R
      C3 --> R
      R --> L(["Rótulo previsto"])
    end
    TREINO == "probabilidades<br/>estimadas" ==> CLASSIF
    classDef dado fill:#C9DCEE,stroke:#3A7CB0,color:#12283F
    classDef passo fill:#F3F7FB,stroke:#8FB6D9,color:#12283F
    classDef fim fill:#12283F,stroke:#12283F,color:#ffffff
    class T1,N dado
    class T2,T3,C1,C2,C3 passo
    class R,L fim
    style TREINO fill:#ffffff,stroke:#8FB6D9,color:#1B4F7A
    style CLASSIF fill:#ffffff,stroke:#1B4F7A,color:#12283F

  • O “treino” é apenas contar: não há otimização iterativa, por isso o algoritmo é muito rápido.

EXEMPLO Jogar tênis

Dia Aparência Temperatura Umidade Vento Jogar tênis
1 Ensolarado Quente Alta Fraco Não
2 Ensolarado Quente Alta Forte Não
3 Nublado Quente Alta Fraco Sim
4 Chuva Moderada Alta Fraco Sim
5 Chuva Fria Normal Fraco Sim
6 Chuva Fria Normal Forte Não
7 Nublado Fria Normal Forte Sim
8 Ensolarado Moderada Alta Fraco Não
9 Ensolarado Fria Normal Fraco Sim
10 Chuva Moderada Normal Fraco Sim
11 Ensolarado Moderada Normal Forte Sim
12 Nublado Moderada Alta Forte Sim
13 Nublado Quente Normal Fraco Sim
14 Chuva Moderada Alta Forte Não

Jogar tênis ou não, dado que:

Aparência = Ensolarado

Temperatura = Fria

Umidade = Alta

Vento = Forte?

EXEMPLO Quais probabilidades precisamos?

\[\begin{aligned}\text{MAP} = \underset{y_i \in \{\text{Sim},\,\text{Não}\}}{\arg\max}\;\; & P(y_i)\, P(\text{Ensolarado} \mid y_i)\, P(\text{Fria} \mid y_i) \\ & \times P(\text{Alta} \mid y_i)\, P(\text{Forte} \mid y_i)\end{aligned}\]

  • Probabilidade das classes: \(P(\text{Sim})\) e \(P(\text{Não})\).
  • Cada probabilidade condicional, para as duas classes:
    • \(P(\text{Ensolarado} \mid \text{Sim})\) e \(P(\text{Ensolarado} \mid \text{Não})\)
    • \(P(\text{Fria} \mid \text{Sim})\) e \(P(\text{Fria} \mid \text{Não})\)
    • \(P(\text{Alta} \mid \text{Sim})\) e \(P(\text{Alta} \mid \text{Não})\)
    • \(P(\text{Forte} \mid \text{Sim})\) e \(P(\text{Forte} \mid \text{Não})\)

São 10 números, todos obtidos por contagem na tabela.

EXEMPLO Probabilidades a priori e condicionais

Prior: \(\;P(\text{Sim}) = 9/14 \qquad P(\text{Não}) = 5/14\)

Aparência Jogar = Sim Jogar = Não
Ensolarado 2/9 3/5
Nublado 4/9 0/5
Chuva 3/9 2/5
Temperatura Jogar = Sim Jogar = Não
Quente 2/9 2/5
Moderada 4/9 2/5
Fria 3/9 1/5
Umidade Jogar = Sim Jogar = Não
Alta 3/9 4/5
Normal 6/9 1/5
Vento Jogar = Sim Jogar = Não
Forte 3/9 3/5
Fraco 6/9 2/5

EXEMPLO Classificando o novo dia

\(\mathbf{x}'\) = (Aparência = Ensolarado, Temperatura = Fria, Umidade = Alta, Vento = Forte)

\[\begin{aligned} \text{Sim:}&\quad \tfrac{9}{14} \times \tfrac{2}{9} \times \tfrac{3}{9} \times \tfrac{3}{9} \times \tfrac{3}{9} = 0{,}0053 \\[4pt] \text{Não:}&\quad \tfrac{5}{14} \times \tfrac{3}{5} \times \tfrac{1}{5} \times \tfrac{4}{5} \times \tfrac{3}{5} = 0{,}0206 \end{aligned}\]

EXEMPLO Resultado

Como \(0{,}0053 < 0{,}0206\), rotulamos \(\mathbf{x}'\) como “Não”: não vai ter tênis.

Normalizando:

\[P(\text{Não} \mid \mathbf{x}') = \frac{0{,}0206}{0{,}0259} \approx 79{,}5\%\]

\[P(\text{Sim} \mid \mathbf{x}') \approx 20{,}5\%\]

FREQUÊNCIA ZERO Um valor que nunca apareceu

Dia Aparência Jogar tênis
1 Ensolarado Não
2 Ensolarado Não
3 Nublado Sim
4 Chuva Sim
5 Chuva Sim
6 Chuva Não
7 Nublado Sim
8 Ensolarado Não
9 Ensolarado Sim
10 Chuva Sim
11 Ensolarado Sim
12 Nublado Sim
13 Nublado Sim
14 Chuva Não

Aparência = Nublado só aparece com Jogar = Sim:

\[P(\text{Nublado} \mid \text{Não}) = \tfrac{0}{5} = 0\]

flowchart TB
    Z["P(Nublado | Não) = 0/5"] --> P["5/14 × <b>0</b> × 1/5 × 4/5 × 3/5"]
    P --> R["P(Não | Nublado, …) = 0"]
    R --> C["“Não” fica <b>impossível</b>,<br/>não importa o resto"]
    classDef zero fill:#C9DCEE,stroke:#3A7CB0,color:#12283F
    classDef passo fill:#F3F7FB,stroke:#8FB6D9,color:#12283F
    classDef fim fill:#12283F,stroke:#12283F,color:#ffffff
    class Z zero
    class P,R passo
    class C fim

FREQUÊNCIA ZERO Por que isso é um problema?

  • A probabilidade a posteriori também será zero: \(P(\text{Não} \mid \text{Nublado}, \dots) = 0\).
    • Como as probabilidades são multiplicadas, um único zero anula tudo;
    • não importam as probabilidades dos outros atributos.
  • A base de treinamento pode não ser totalmente representativa.
    • Classes minoritárias podem ter valores raros — nunca ter visto não significa ser impossível.

Com só 5 dias de “Não” no treino, é razoável concluir que nunca deixamos de jogar em dia nublado?

FREQUÊNCIA ZERO Estimador de Laplace

Adicionar uma unidade fictícia a cada combinação valor-classe — valores nunca vistos passam a ter 1 exemplo:

\[P(x^j = v \mid y_i) = \frac{\text{contagem}(x^j = v,\ y_i) + 1}{n_{y_i} + k}\]

(\(n_{y_i}\): exemplos da classe; \(k\): número de valores possíveis do atributo)

Aparência, classe Não (\(k = 3\)):

Valor Sem correção Com Laplace
Ensolarado 3/5 4/8
Nublado 0/5 1/8
Chuva 2/5 3/8

Deve ser feito para todos os valores e classes — senão, enviesamos uma classe só.

FREQUÊNCIA ZERO Refazendo a conta com Laplace

Dia (Nublado, Fria, Alta, Forte), com Laplace em todas as variáveis:

\[\begin{aligned} \text{Sim:}&\quad \tfrac{9}{14} \times \tfrac{4+1}{9+3} \times \tfrac{3+1}{9+3} \times \tfrac{3+1}{9+2} \times \tfrac{3+1}{9+2} = 0{,}0118 \\[4pt] \text{Não:}&\quad \tfrac{5}{14} \times \tfrac{0+1}{5+3} \times \tfrac{1+1}{5+3} \times \tfrac{4+1}{5+2} \times \tfrac{3+1}{5+2} = 0{,}0046 \end{aligned}\]

\[P(\text{Sim} \mid \mathbf{x}) \approx 72{,}2\% \qquad P(\text{Não} \mid \mathbf{x}) \approx 27{,}8\%\]

  • A classe prevista continua sendo Sim — mas agora “Não” deixou de ser impossível: a evidência de vento forte e umidade alta é levada em conta.

FREQUÊNCIA ZERO Estimativa m

Adicionar m unidades fictícias para cada combinação valor-classe — solução mais geral:

\[P(x^j = v \mid y_i) = \frac{\text{contagem}(x^j = v,\ y_i) + m \cdot p}{n_{y_i} + m}\]

\(p\): estimativa a priori (em geral, \(p = 1/k\)); \(m\): peso dessa estimativa.

Aparência, classe Não (\(p = 1/3\)):

  • Ensolarado: \(\tfrac{3}{5} \to \tfrac{3 + m/3}{5 + m}\)
  • Nublado: \(\tfrac{0}{5} \to \tfrac{0 + m/3}{5 + m}\)
  • Chuva: \(\tfrac{2}{5} \to \tfrac{2 + m/3}{5 + m}\)

Com \(m = k = 3\), recuperamos Laplace.

VALORES AUSENTES E se faltar o valor de um atributo?

flowchart LR
    A(["Observação com<br/>valor ausente"]) --> T{"Em qual<br/>etapa?"}
    T -- treinamento --> T1["Imputar o valor,<br/>se possível"]
    T1 -- "não é possível" --> T2["Excluir a observação<br/>do conjunto de treinamento"]
    T -- teste --> S1["Usar apenas os<br/>demais atributos"]
    S1 --> S2["o fator ausente<br/>simplesmente sai do produto"]
    classDef ini fill:#C9DCEE,stroke:#3A7CB0,color:#12283F
    classDef dec fill:#ffffff,stroke:#1B4F7A,color:#12283F
    classDef passo fill:#F3F7FB,stroke:#8FB6D9,color:#12283F
    classDef fim fill:#12283F,stroke:#12283F,color:#ffffff
    class A ini
    class T dec
    class T1,S1 passo
    class T2,S2 fim

Vantagem do Naïve Bayes

Como cada atributo entra como um fator separado, lidar com valores ausentes é natural — algo bem mais difícil no k-NN, que precisa de todas as coordenadas para calcular distâncias.

CONTÍNUOS E se os atributos forem contínuos?

Alternativa 1: discretizar os dados

  • Dividir em intervalos — por exemplo, número de intervalos k = mín(10, nº de valores diferentes).
  • Muita informação pode ser perdida.

Alternativa 2: usar uma função de densidade

  • No cálculo de \(P(x^j \mid y_i)\), usamos uma densidade de probabilidade.
  • Geralmente, a distribuição Normal (Naïve Bayes gaussiano), com média e desvio-padrão estimados em cada classe.
  • Pode-se usar outras distribuições que caracterizem melhor os dados.

CONTÍNUOS E se os atributos forem contínuos?

CONTÍNUOS Exemplo: temperatura em °F

Temperatura nos dias com Jogar = Sim: \(\mu = 73\), \(\sigma = 6{,}2\). Para um novo dia com temperatura 66:

\[f(\text{temperatura} = 66 \mid \text{Sim}) = \frac{1}{\sqrt{2\pi}\;6{,}2} \exp\!\left[-\frac{1}{2}\left(\frac{66 - 73}{6{,}2}\right)^{2}\right] = 0{,}034\]

Esse valor substitui \(P(\text{Temperatura} \mid \text{Sim})\) no produto. Atenção: é uma densidade (pode até ser maior que 1), mas serve para comparar as classes.

USO PRÁTICO Vantagens

  • Bom desempenho na predição de multiclasses.
  • Fácil de implementar, inclusive de forma incremental.
  • Fácil interpretação — as tabelas de probabilidade dizem como cada atributo pesa.
  • Melhor desempenho com entrada categórica.
  • Robusto a atributos irrelevantes (que têm distribuição parecida em todas as classes).
  • Classifica amostras com valores ausentes.
  • Paralelização simples.
  • Boa solução quando se tem poucos dados.

USO PRÁTICO Desvantagens

  • Suposição de preditores independentes.
  • Desempenho pode ser afetado por atributos correlacionados (a mesma evidência conta duas vezes).
  • Problema da frequência zero.
  • As probabilidades estimadas tendem a ser extremas (perto de 0 ou 1), mesmo quando a classe prevista está certa.

USO PRÁTICO Aplicações

flowchart TB
    NB(["Naïve Bayes"])
    NB --> A1["<b>Previsões em tempo real</b><br/>algoritmo rápido"]
    NB --> A2["<b>Previsões multiclasse</b><br/>probabilidade de cada classe<br/>da variável-alvo"]
    NB --> A3["<b>Classificação de textos</b><br/>filtragem de spam,<br/>análise de sentimento"]
    NB --> A4["<b>Sistemas de recomendação</b><br/>serviços de que um usuário<br/>poderia gostar"]
    classDef raiz fill:#12283F,stroke:#12283F,color:#ffffff
    classDef app fill:#F3F7FB,stroke:#3A7CB0,color:#12283F
    class NB raiz
    class A1,A2,A3,A4 app

Resumo

  • Técnica de classificação baseada no teorema de Bayes.
  • Suposição de independência entre os preditores, dada a classe.
  • Decide pela classe de maior probabilidade a posteriori (MAP) — e faz predições de múltiplas classes.
  • Desempenho melhor para variáveis de entrada categóricas; para contínuas, discretizar ou usar a Normal.
  • Uso do estimador de Laplace em problemas de frequência zero.

Referências

  • FACELI, K. et al. Inteligência Artificial: uma abordagem de aprendizado de máquina. Rio de Janeiro: LTC, 2011.
  • HASTIE, T.; TIBSHIRANI, R.; FRIEDMAN, J. The Elements of Statistical Learning. 2. ed. New York: Springer, 2009.
  • JAMES, G.; WITTEN, D.; HASTIE, T.; TIBSHIRANI, R. An Introduction to Statistical Learning. 2. ed. New York: Springer, 2021.
  • WITTEN, I. H.; FRANK, E.; HALL, M. A. Data Mining: Practical Machine Learning Tools and Techniques. 3. ed. Burlington: Morgan Kaufmann, 2011.
  • Notas de aula do curso Mineração de Dados em Biologia Molecular, ministrado por André C. P. L. F. de Carvalho.