O que é o classificador Naive Bayes?
O classificador Naive Bayes é um modelo probabilístico simples baseado no teorema de Bayes. Ele assume que os atributos são condicionalmente independentes dada a classe alvo. Essa suposição “ingênua” (naive) simplifica drasticamente o cálculo das probabilidades. Apesar disso, ele funciona surpreendentemente bem em muitas aplicações reais. A regra de classificação é: classe = argmax P(classe) * ∏ P(atributoᵢ | classe). Ele é treinado estimando as probabilidades condicionais de cada atributo por classe. Para atributos contínuos, assume-se frequentemente uma distribuição normal (gaussiana). Para atributos discretos, usam-se frequências com suavização de Laplace. O Naive Bayes é rápido, escalável e fácil de implementar. Ele é amplamente usado em filtros de spam, análise de sentimentos e diagnóstico.
Características fundamentais do Naive Bayes
O Naive Bayes possui três características principais que o definem. Primeiro, ele é um modelo generativo: modela a distribuição conjunta P(classe, atributos). Segundo, a independência condicional reduz o número de parâmetros drasticamente. Terceiro, ele é robusto a atributos irrelevantes e a dados faltantes. A suposição de independência é forte, mas muitas vezes não prejudica a acurácia. Ele também produz probabilidades bem calibradas quando os dados são balanceados.
Vantagens e limitações típicas
A principal vantagem é a eficiência computacional e a baixa necessidade de dados. Ele é usado em classificação de textos, onde o número de atributos é enorme. Também é aplicado em sistemas de recomendação e previsão de churn. Contudo, a suposição de independência pode falhar em dados com forte correlação.
O Naive Bayes é um caso especial de rede bayesiana com estrutura em estrela. A classe é o nó raiz, e cada atributo é uma folha conectada diretamente a ela. O aprendizado de parâmetros é feito por ML ou MAP (com suavização). Para atributos binários, usa-se a distribuição de Bernoulli. Para atributos categóricos, usa-se a distribuição multinomial. Para atributos contínuos, a Gaussiana é a escolha mais comum. Existem variantes como o Multinomial Naive Bayes para contagens de palavras. E o Bernoulli Naive Bayes para presença/ausência de termos. O Naive Bayes é um bom baseline para problemas de classificação. Ele é surpreendentemente competitivo com métodos mais complexos. Sua interpretabilidade é alta: cada atributo contribui com um fator multiplicativo. A suavização de Laplace evita probabilidades zero para atributos não vistos. A escolha do parâmetro de suavização (α) controla a regularização. Assim, o Naive Bayes é uma ferramenta essencial no kit do cientista de dados.
Um exemplo clássico é a classificação de e-mails como spam ou não-spam. Atributos: presença de palavras como “grátis”, “urgente”, “clique aqui”. O Naive Bayes calcula a probabilidade de spam dada a presença dessas palavras. Ele é rápido e eficaz, mesmo com milhões de e-mails.
Enunciado do exemplo clássico
Implemente o classificador Naive Bayes gaussiano para o dataset Iris (todas as 4 características). Divida em treino (70%) e teste (30%). Calcule médias e variâncias por classe e por atributo. Classifique os dados de teste e calcule a acurácia, precisão e recall por classe. Plote a matriz de confusão e as distribuições condicionais para um atributo (ex.: comprimento da sépala).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, classification_report # Carregar dados iris = load_iris() X = iris.data # 4 atributos y = iris.target nomes = iris.target_names # Dividir X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # Implementação do Naive Bayes Gaussiano do zero class NaiveBayesGaussiano: def fit(self, X, y): self.classes = np.unique(y) self.n_classes = len(self.classes) self.n_atributos = X.shape[1] # Priores self.priors = np.array([np.mean(y == c) for c in self.classes]) # Médias e variâncias por classe e atributo self.means = np.zeros((self.n_classes, self.n_atributos)) self.vars = np.zeros((self.n_classes, self.n_atributos)) for idx, c in enumerate(self.classes): X_c = X[y == c] self.means[idx, :] = np.mean(X_c, axis=0) self.vars[idx, :] = np.var(X_c, axis=0) + 1e-9 # evitar divisão por zero def predict_proba(self, X): n_amostras = X.shape[0] probs = np.zeros((n_amostras, self.n_classes)) for idx, c in enumerate(self.classes): # Calcular log-verossimilhança para cada atributo log_lik = -0.5 * np.sum(np.log(2 * np.pi * self.vars[idx, :])) log_lik -= 0.5 * np.sum(((X - self.means[idx, :])**2) / self.vars[idx, :], axis=1) log_lik += np.log(self.priors[idx]) probs[:, idx] = log_lik # Converter para probabilidades (softmax) max_log = np.max(probs, axis=1, keepdims=True) exp_probs = np.exp(probs - max_log) return exp_probs / np.sum(exp_probs, axis=1, keepdims=True) def predict(self, X): probs = self.predict_proba(X) return self.classes[np.argmax(probs, axis=1)] # Treinar nb = NaiveBayesGaussiano() nb.fit(X_train, y_train) # Prever y_pred = nb.predict(X_test) y_probs = nb.predict_proba(X_test) # Métricas acuracia = np.mean(y_pred == y_test) print(f"Acurácia: {acuracia:.3f}") print("\nRelatório de classificação:") print(classification_report(y_test, y_pred, target_names=nomes)) # Matriz de confusão cm = confusion_matrix(y_test, y_pred) # Gráficos plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=nomes).plot(ax=plt.gca(), cmap='Blues') plt.title(f'Matriz de Confusão (Acurácia = {acuracia:.3f})') plt.subplot(1, 2, 2) # Distribuições condicionais para o primeiro atributo (comprimento da sépala) atr_idx = 0 x_vals = np.linspace(X[:, atr_idx].min()-0.5, X[:, atr_idx].max()+0.5, 200) for c in nb.classes: mean = nb.means[c, atr_idx] var = nb.vars[c, atr_idx] pdf = (1 / np.sqrt(2 * np.pi * var)) * np.exp(-0.5 * ((x_vals - mean)**2) / var) plt.plot(x_vals, pdf, label=f'{nomes[c]} (μ={mean:.2f}, σ={np.sqrt(var):.2f})') # Histograma dos dados de treino plt.hist(X_train[y_train==c, atr_idx], bins=8, density=True, alpha=0.2) plt.xlabel('Comprimento da sépala (cm)') plt.ylabel('Densidade') plt.title('Distribuições Condicionais - Atributo 0') plt.legend() plt.grid(True) plt.tight_layout() plt.show() # Exemplo de previsão com probabilidades nova_flor = np.array([[5.2, 3.5, 1.5, 0.2]]) probs = nb.predict_proba(nova_flor) pred = nb.predict(nova_flor) print(f"\nNova flor com características {nova_flor[0]}:") for i, nome in enumerate(nomes): print(f" P({nome}) = {probs[0][i]:.3f}") print(f"Classe predita: {nomes[pred[0]]}") |
Este código implementa o Naive Bayes gaussiano do zero. As médias e variâncias são estimadas por ML para cada classe e atributo. As distribuições condicionais mostram a separabilidade das classes. A matriz de confusão valida o bom desempenho do classificador. Para iniciantes, este exemplo conecta a teoria à prática de forma completa. O classificador Naive Bayes é, portanto, uma ferramenta poderosa e acessível.