k-NN, Naive Bayes
Por que k-NN e Naive Bayes ainda importam
k-Vizinhos Mais Próximos (k-Nearest Neighbors, k-NN) e Naive Bayes (NB) costumam ser ensinados cedo porque são simples. Eles também ainda são usados em sistemas reais porque são:
- Baselines fortes (strong baselines): surpreendentemente competitivos em muitos cenários.
- Rápidos para iterar: escolhas de modelagem mínimas, poucos hiperparâmetros.
- Bons “checks de formato”: se modelos complexos não os superam, algo pode estar errado (atributos, vazamento, avaliação etc.).
Eles têm sucesso por razões diferentes:
- k-NN depende de uma hipótese de similaridade (similarity assumption): “pontos próximos no espaço de atributos tendem a compartilhar rótulos”.
- Naive Bayes depende de uma hipótese de independência condicional (conditional independence assumption): “os atributos são independentes dado a classe”.
Ambas as hipóteses frequentemente estão “erradas” no sentido estrito, mas ainda assim os métodos podem funcionar muito bem.
k-Vizinhos Mais Próximos (k-NN)
Ideia central e hipóteses
k-NN é um método baseado em instâncias (instance-based), não paramétrico (non-parametric). Não há uma fase explícita de treinamento que aprenda parâmetros (além de indexar os dados). Para prever para um novo ponto x, ele:
- Encontra os
kpontos de treinamento mais próximos dexsob uma métrica de distância escolhida. - Agrega seus rótulos (voto majoritário para classificação, média para regressão).
Hipótese-chave: a função de rótulo é localmente suave no espaço de atributos escolhido — pontos próximos devem ter saídas semelhantes.
Isso torna o k-NN altamente dependente de:
- a representação de atributos
- a métrica de distância
- a escala dos atributos
Se o seu espaço de atributos corresponde à noção real de similaridade, k-NN pode ser muito forte. Se não, ele falha de forma contundente.
Algoritmo (classificação)
Dado o conjunto de treinamento (x_i, y_i):
- Calcule as distâncias
d(x, x_i)para todos os pontos de treinamento. - Seja
N_k(x)o conjunto de índices daskmenores distâncias. - Prediga:
- Sem pesos:
ŷ = mode({ y_i : i ∈ N_k(x) }) - Ponderado pela distância: peso do voto
w_i = 1 / (d(x, x_i) + ε)ouexp(-d^2 / σ^2)
- Sem pesos:
Métricas de distância: o “modelo” dentro do k-NN
Escolhas comuns:
- Euclidiana (L2): padrão para atributos contínuos e com escalas semelhantes.
- Manhattan (L1): às vezes mais robusta em alta dimensionalidade.
- Distância do cosseno (cosine distance): comum para embeddings de texto esparsos ou vetores TF-IDF (foca no ângulo, não na magnitude).
- Hamming: codificações binárias/categóricas.
- Métricas aprendidas (learned metrics): via Aprendizado de Métrica para fazer as distâncias corresponderem à similaridade semântica.
Nota prática: para tipos mistos de atributos ou similaridade complexa, o k-NN frequentemente funciona melhor quando você investe em aprendizado de representação (embeddings) em vez de ficar ajustando k.
Considerações práticas
Escalonamento de atributos não é opcional
Distâncias não têm sentido se um atributo domina pela escala. Abordagens padrão:
- Padronização (média zero, variância unitária)
- Escalonamento min-max
- Normalização para similaridade do cosseno
Ao usar validação cruzada, o escalonamento deve ser ajustado apenas nos folds de treino para evitar vazamento.
Maldição da dimensionalidade
Em alta dimensionalidade, as distâncias tornam-se menos informativas: vizinhos mais próximos e mais distantes podem estar a distâncias semelhantes. Isso pode fazer o k-NN degradar rapidamente, a menos que:
- a dimensão intrínseca seja baixa, ou
- você reduza a dimensionalidade (veja Redução de Dimensionalidade), ou
- você aprenda um espaço de embedding melhor (veja Aprendizado de Métrica).
Escolhendo `k`
kpequeno → baixo viés, alta variância (sensível a ruído).kgrande → viés mais alto, fronteira de decisão mais suave.
Regra prática: ajuste k com validação; valores ímpares ajudam a evitar empates em classificação binária.
Custo computacional
- Custo de “treino”: baixo (armazenar dados).
- Custo de predição (ingênuo): O(n · d) por consulta, onde
né o número de pontos de treino,do número de atributos.
Acelerações:
- KD-tree / Ball tree (efetivas em dimensionalidade baixa/moderada).
- Vizinhos mais próximos aproximados (approximate nearest neighbors) (HNSW, IVF, quantização de produto) para recuperação em larga escala. Essas ideias também aparecem em Sistemas de Recomendação e busca semântica.
Quando k-NN funciona bem
- Conjuntos de dados pequenos a médios em que armazenar todos os pontos é viável.
- Espaços de atributos bem estruturados (bons embeddings, distância significativa).
- Fronteiras de classe não lineares sem necessidade de treinamento de modelo.
- Tarefas de similaridade com cold-start (por exemplo, “encontrar usuários/itens/documentos semelhantes”).
Quando k-NN tem dificuldades
- Atributos brutos de alta dimensionalidade sem boa representação.
ngrande com restrições de latência (a menos que use indexação de ANN).- Classes fortemente desbalanceadas (vizinhos provavelmente dominados pela classe majoritária, a menos que você tenha cuidado).
- Muitos atributos irrelevantes (a distância fica ruidosa).
Exemplo: classificação k-NN no scikit-learn
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
model = make_pipeline(
StandardScaler(),
KNeighborsClassifier(n_neighbors=5, weights="distance", metric="minkowski", p=2)
)
model.fit(X_train, y_train)
pred = model.predict(X_test)
print(classification_report(y_test, pred))
Principais conclusões do exemplo:
- Use um pipeline para que o escalonamento seja aplicado corretamente.
- Experimente
weights="distance"quando você espera que vizinhos mais próximos sejam mais confiáveis.
Naive Bayes (NB)
Regra de Bayes e o modelo Naive Bayes
Naive Bayes é um modelo probabilístico, tipicamente paramétrico (parametric), generativo (generative). Ele modela a distribuição conjunta:
- Escolha uma classe
yde acordo comP(y) - Gere atributos
x = (x1, x2, ..., xd)a partir deP(x | y)
Pela regra de Bayes:
P(y | x) ∝ P(y) * P(x | y)
A hipótese “naive” é:
P(x | y) = Π_j P(x_j | y) (os atributos são condicionalmente independentes dado a classe)
Assim, a regra de classificação torna-se:
ŷ = argmax_y [ log P(y) + Σ_j log P(x_j | y) ]
Usar logaritmos evita underflow numérico e transforma produtos em somas.
Por que a hipótese de independência ainda pode funcionar
Mesmo quando os atributos são correlacionados, Naive Bayes ainda pode classificar bem porque:
- a classificação depende de escores relativos entre classes, não de probabilidades perfeitamente calibradas
- erros nas estimativas de probabilidade podem se cancelar
- com atributos esparsos de alta dimensionalidade (por exemplo, texto), a hipótese é “menos errada” na prática
Dito isso, as saídas de probabilidade frequentemente são mal calibradas; você pode precisar de calibração se as decisões dependerem de probabilidades.
Variantes comuns de Naive Bayes
A escolha depende do tipo de atributo:
Naive Bayes Multinomial (multinomial naive bayes) (contagens de texto)
Para contagens de palavras (bag-of-words):
x_j= contagem do tokenjP(x | y)é multinomial com probabilidades de tokens específicas por classe
Frequentemente usado para detecção de spam, classificação de tópicos, sentimento.
Tipicamente combinado com:
- bag-of-words ou n-grams
- atributos de contagem ou TF-IDF (TF-IDF não é estritamente multinomial, mas funciona bem empiricamente)
Naive Bayes Bernoulli (bernoulli naive bayes) (atributos binários)
Para indicadores binários (palavra presente/ausente):
- útil quando a presença importa mais do que a frequência
Naive Bayes Gaussiano (gaussian naive bayes) (atributos contínuos)
Assume:
x_j | y ~ Normal(μ_{y,j}, σ^2_{y,j})
Funciona como um baseline rápido para dados contínuos, mas pode ser sensível a distribuições não gaussianas e ao escalonamento de atributos.
Naive Bayes Complementar (complement naive bayes)
Uma variante projetada para funcionar melhor em classificação de texto desbalanceada, modelando estatísticas de “não a classe”.
Suavização: evitando probabilidades zero
Em Naive Bayes Multinomial/Bernoulli, se uma palavra nunca aparece em uma classe no treinamento, então P(word | class) = 0, o que pode zerar toda a verossimilhança.
Suavização de Laplace/aditiva (laplace/additive smoothing) corrige isso:
P(word=j | y) = (count(j,y) + α) / (total_count(y) + α*V)
α = 1é suavização de Laplaceαmenor pode funcionar melhor em vocabulários grandes
Considerações práticas
Velocidade de treinamento e inferência
NB é extremamente rápido:
- o treinamento é essencialmente contar ocorrências de atributos por classe
- a predição é um produto escalar dos atributos com log-probabilidades
Isso torna NB uma escolha forte para:
- classificação de texto em tempo real
- espaços de atributos esparsos grandes
- baselines rápidos em pipelines de aprendizado de máquina
Interpretabilidade
Parâmetros de NB frequentemente são interpretáveis:
- quais tokens são mais indicativos de cada classe
- raciocínio no estilo log-odds (embora tenha cuidado com atributos correlacionados “contando duas vezes” a evidência)
Relação com modelos lineares
NB produz uma regra de decisão linear no espaço de atributos para variantes comuns. Pode parecer com Regressão Linear/Logística, mas:
- NB é generativo (modela
P(x|y)eP(y)) - regressão logística é discriminativa (discriminative) (modela
P(y|x)diretamente) A regressão logística frequentemente vence com dados suficientes; NB pode vencer com pouquíssimos dados ou texto esparso de altíssima dimensionalidade.
Exemplo: classificação de spam com NB Multinomial
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
texts = [
"cheap pills buy now", "limited time offer", "meeting agenda for tomorrow",
"project update and timeline", "win money win prizes", "let's schedule a call"
]
labels = [1, 1, 0, 0, 1, 0] # 1=spam, 0=ham
X_train, X_test, y_train, y_test = train_test_split(
texts, labels, test_size=0.33, random_state=0, stratify=labels
)
model = make_pipeline(
TfidfVectorizer(ngram_range=(1,2), min_df=1),
MultinomialNB(alpha=0.5)
)
model.fit(X_train, y_train)
pred = model.predict(X_test)
print(classification_report(y_test, pred))
Notas:
TfidfVectorizercom bigramas frequentemente melhora o desempenho.- Para atributos de contagem pura,
CountVectorizertambém é comum. - Se seu conjunto de dados for desbalanceado, considere ComplementNB e avalie com métricas além de acurácia.
Comparando k-NN vs Naive Bayes
Forças e fraquezas em resumo
k-NN
- Prós: fronteiras não lineares flexíveis; simples; pode ser muito preciso com bons embeddings; sem treino.
- Contras: lento na inferência sem indexação; sensível a escalonamento e atributos irrelevantes; tem dificuldades em alta dimensionalidade.
Naive Bayes
- Prós: extremamente rápido; forte para texto/dados esparsos; funciona bem com poucos dados; simples e razoavelmente interpretável.
- Contras: a hipótese de independência pode estimar mal probabilidades; pode ser superado por modelos discriminativos com dados suficientes; a calibração pode ser ruim.
Como escolher na prática
Escolha k-NN quando:
- você tem uma métrica de distância significativa (ou embeddings aprendidos)
- o conjunto de dados não é grande demais, ou você pode usar índices de ANN
- as fronteiras de decisão provavelmente são não lineares
- você quer um baseline forte “baseado em similaridade” (comum em recuperação e recomendação)
Escolha Naive Bayes quando:
- os atributos são esparsos e de alta dimensionalidade (texto)
- você precisa de treinamento/inferência extremamente rápidos
- você tem poucos dados rotulados e quer um baseline robusto
- interpretabilidade no nível de atributo importa (por exemplo, quais palavras impulsionam o spam)
Se você estiver trabalhando com dados tabulares e quiser forte desempenho, considere também Árvores de Decisão & Ensembles como próximo passo; para classificação baseada em margem, veja SVMs.
Armadilhas comuns e boas práticas
Armadilhas de k-NN
- Vazamento de dados via pré-processamento: sempre ajuste escaladores/codificadores dentro dos folds de validação cruzada (use pipelines).
- Ignorar desbalanceamento de classes: considere ponderação por distância, votação ponderada por classe, ou reamostragem.
- Escolher a distância errada: cosseno frequentemente supera Euclidiana para vetores esparsos.
- Rótulos ruidosos/outliers:
kpequeno fará overfit; considerekmaior ou variantes de vizinho mais próximo editado/condensado.
Armadilhas de Naive Bayes
- Contagens zero sem suavização: sempre use
alpha > 0para multinomial/bernoulli. - Modelo de atributos incompatível: use Multinomial/Bernoulli para texto, Gaussiano para contínuos (como baseline).
- Probabilidades excessivamente confiantes: se você usa probabilidades para limiares de decisão, considere calibração (por exemplo, regressão isotônica) e valide com cuidado.
- Atributos correlacionados: NB pode “contar duas vezes” a evidência; seleção de atributos ou migração para regressão logística pode ajudar.
Onde eles se encaixam em um fluxo de trabalho moderno de ML
Apesar da ascensão do aprendizado profundo, k-NN e NB continuam valiosos:
- Como baselines de primeira linha para pipelines de classificação/regressão.
- Como componentes dentro de sistemas maiores:
- k-NN para recuperação por vizinho mais próximo, busca por similaridade, deduplicação e recomendação baseada em embeddings (veja Sistemas de Recomendação).
- Naive Bayes para triagem rápida de texto, filtros de spam e bootstrap de rótulos.
- Como ferramentas de diagnóstico:
- Se k-NN com um bom embedding falha, a representação pode estar fraca.
- Se NB falha em texto, atributos ou tokenização podem ser o gargalo.
Em resumo: estes são modelos “simples” cuja eficácia depende menos de otimização sofisticada e mais de escolher atributos que correspondam às suas hipóteses.