Estimativa de Densidade por Kernel (Kernel Density Estimation, KDE)

Visão geral

Estimação de Densidade por Kernel (Kernel Density Estimation, KDE) é uma forma não paramétrica de estimar uma função densidade de probabilidade (probability density function, PDF) desconhecida (p(x)) a partir de amostras i.i.d. (independentes e identicamente distribuídas) (x_1,\dots,x_n). “Não paramétrica” aqui significa que a KDE não assume uma forma funcional fixa (como uma gaussiana (Gaussian)) com um pequeno número de parâmetros. Em vez disso, ela constrói a estimativa colocando uma “elevação” suave (um núcleo (kernel)) em cada ponto de dados e fazendo a média dessas elevações.

A KDE é amplamente usada para:

  • Análise exploratória de dados: suavizar histogramas; visualizar densidades em 1D/2D.
  • Detecção de anomalias: pontos em regiões de baixa densidade podem ser sinalizados como outliers (veja Detecção de Anomalias).
  • Raciocínio baseado em densidade: estimar verossimilhanças para modelos ou regras a jusante.
  • Amostragem generativa (generative sampling) (limitada): amostrar por reamostragem (resampling) de pontos + adição de ruído (funciona melhor em baixas dimensões).

O principal desafio prático da KDE é a largura de banda (bandwidth) (força de suavização). Sua principal limitação teórica é que ela escala mal com a dimensionalidade, uma manifestação da Maldição da Dimensionalidade.

O estimador de KDE

De histogramas a densidades suaves

Um histograma estima a densidade contando amostras em bins. É simples, mas é sensível às bordas dos bins e à largura dos bins. A KDE substitui bins rígidos por núcleos suaves, reduzindo artefatos de borda e produzindo uma estimativa diferenciável.

KDE univariada

Dadas amostras (x_1,\dots,x_n \in \mathbb{R}), a KDE é:

[ \hat{p}h(x) ;=; \frac{1}{n h}\sum{i=1}^n K!\left(\frac{x-x_i}{h}\right) ]

  • (K(\cdot)) é o núcleo (uma função não negativa que integra para 1).
  • (h>0) é a largura de banda (parâmetro de suavização).
  • Cada termo é um núcleo centrado em (x_i); a média produz uma estimativa de densidade.

Interpretação: (\hat{p}_h(x)) é a média da “influência” de pontos próximos, onde o que significa “próximo” é controlado por (h).

KDE multivariada

Para (x \in \mathbb{R}^d), uma forma comum é:

[ \hat{p}H(x) ;=; \frac{1}{n}\sum{i=1}^n |H|^{-1/2}, K!\left(H^{-1/2}(x-x_i)\right) ]

  • (H) é uma matriz de largura de banda (bandwidth matrix) (d\times d) (simétrica definida positiva).
  • Se (H = h^2 I), a suavização é isotrópica e controlada por um único escalar (h).
  • Se (H) é diagonal, cada dimensão tem sua própria largura de banda.
  • Um (H) completo pode modelar correlações (mas é mais difícil de escolher/estimar de forma confiável).

Uma escolha comum é o núcleo gaussiano (Gaussian kernel):

[ K(u) = (2\pi)^{-d/2}\exp\left(-\frac{1}{2}|u|^2\right) ]

Nesse caso, a KDE se torna uma mistura uniforme de gaussianas centradas nos pontos de dados.

Escolhas de núcleo e largura de banda

Escolha do núcleo (geralmente menos importante)

Muitos núcleos funcionam, desde que sejam densidades válidas (integrem para 1). Núcleos comuns incluem:

  • Gaussiano: suave, suporte infinito; o mais popular na prática.
  • Epanechnikov: suporte compacto; ótimo no sentido do erro quadrático integrado médio (mean integrated squared error, MISE) sob algumas suposições.
  • Top-hat / uniforme: compacto, mas pode parecer “blocudo”.
  • Exponencial / cosseno: usados ocasionalmente em configurações específicas.

Em muitas situações práticas, a escolha do núcleo tem um efeito modesto em comparação com a largura de banda. O gaussiano é um padrão forte por conta da suavidade e da conveniência numérica.

Largura de banda: o principal ajuste (compromisso viés–variância (bias–variance tradeoff))

A largura de banda controla a suavização:

  • (h) pequeno: estimativa cheia de picos, baixo viés, alta variância (overfitting).
  • (h) grande: estimativa excessivamente suave, alto viés, baixa variância (underfitting).

Esse é o clássico compromisso viés–variância em estimação de densidade.

Regras práticas

Para KDE gaussiana em 1D, heurísticas populares incluem:

  • Regra de Scott: (h \propto \sigma, n^{-1/(d+4)})
  • Regra de Silverman (variante 1D): (h \approx 0.9 \min(\sigma,\text{IQR}/1.34),n^{-1/5})

Elas são rápidas, frequentemente servem como boas linhas de base e são comumente implementadas em bibliotecas científicas.

Seleção orientada por dados

Métodos mais robustos de seleção de largura de banda otimizam um objetivo:

  • Máxima verossimilhança / log-verossimilhança leave-one-out (leave-one-out log-likelihood, LOO-LL)
    Escolher (h) para maximizar (\sum_i \log \hat{p}_{-i,h}(x_i)) (densidade estimada sem o ponto (i) para reduzir viés).
  • Validação cruzada por mínimos quadrados (least-squares cross-validation, LSCV)
    Minimiza uma estimativa do erro quadrático integrado.
  • Métodos plug-in (plug-in methods) (por exemplo, Sheather–Jones em 1D)
    Estimam quantidades desconhecidas em fórmulas de largura de banda assintoticamente ótimas.

Em pipelines de aprendizado de máquina (machine learning), é comum tratar a largura de banda como um hiperparâmetro (hyperparameter) ajustado por validação cruzada (cross-validation) (veja Validação Cruzada).

KDE adaptativa (largura de banda variável)

A KDE padrão usa uma largura de banda para todos os pontos. A KDE adaptativa (adaptive KDE) usa uma largura de banda menor em regiões densas e maior em regiões esparsas (por exemplo, via distâncias de k-vizinhos mais próximos (k-nearest neighbors, k-NN)). Isso pode melhorar o desempenho em densidades com múltiplas escalas, mas aumenta a complexidade e o esforço de ajuste. Também se conecta conceitualmente à estimação de densidade via raios de vizinhança (relacionado a K-Vizinhos Mais Próximos (KNN)).

Detalhes práticos de implementação

Pré-processamento: a escala importa muito

Em KDE multivariada, a distância determina os pesos do núcleo. Se as features tiverem escalas diferentes, a KDE pode se comportar mal. Práticas comuns:

  • Padronizar features contínuas (média zero, variância unitária).
  • Usar branqueamento (whitening) / PCA se existirem correlações fortes (veja Redução de Dimensionalidade).
  • Considerar transformações apropriadas ao domínio:
    • transformação log para variáveis positivas com caudas pesadas
    • transformação logística para variáveis limitadas em ([0,1])

Se você mistura tipos de features heterogêneos (contínuas + categóricas), a KDE “pura” geralmente é inadequada sem núcleos especializados.

Avaliando KDE: grade vs consultas pontuais

  • Visualização: avaliar em uma grade 1D densa ou em uma malha 2D e então plotar.
  • Pontuação de novos pontos: avaliar (\hat{p}(x)) ou (\log \hat{p}(x)) em pontos de consulta.

A maioria dos sistemas práticos usa o log da densidade (log density) por estabilidade numérica, especialmente em dimensões moderadas.

Complexidade computacional e acelerações

Calcular KDE de forma ingênua em (m) pontos de consulta custa:

  • Tempo: (O(nm)) avaliações de núcleo
  • Memória: (O(1)) memória extra (streaming é possível), mas armazenar todos os pontos custa (O(n))

Isso pode ser caro para grandes conjuntos de dados.

Acelerações comuns:

  • Aproximações baseadas em árvores (árvore KD (KD-tree) / Ball-tree) para núcleos de suporte compacto e às vezes para núcleos gaussianos.
  • Convolução baseada em FFT (transformada rápida de Fourier (FFT)) em 1D ou em grades (transforma KDE em histograma + suavização).
  • Aproximações aleatórias para misturas gaussianas (menos padrão para KDE do que para métodos de núcleo supervisionados).
  • Subamostragem / conjuntos-núcleo (coresets): aproximar a densidade usando pontos representativos.

O KernelDensity do Scikit-learn pode usar métodos baseados em árvores em alguns cenários; o gaussian_kde do SciPy usa álgebra linear eficiente, mas ainda escala aproximadamente de forma quadrática no número de dimensões para operações de covariância e linearmente com (n) por consulta.

Viés de fronteira

Se o suporte verdadeiro for limitado (por exemplo, (x \ge 0)), núcleos simétricos (como o gaussiano) “vazam” massa para fora do domínio perto das fronteiras, causando viés de fronteira (boundary bias).

Mitigações:

  • Reflexão: adicionar amostras refletidas perto da fronteira.
  • Núcleos com correção de fronteira: núcleos especializados que respeitam o suporte.
  • Transformar para (\mathbb{R}): por exemplo, transformação log para variáveis positivas, e então KDE no espaço transformado (lembre-se do jacobiano se for converter densidades de volta).

KDE ponderada

Se amostras tiverem pesos (w_i \ge 0) (amostragem por importância (importance sampling), reponderação, desbalanceamento de classes), use:

[ \hat{p}(x)=\frac{1}{\sum_i w_i}\sum_i w_i, K_h(x-x_i) ]

Muitas bibliotecas suportam pesos de amostra diretamente ou via replicação de dados.

Exemplos práticos (Python)

Exemplo 1: KDE 1D para visualização

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KernelDensity

# Synthetic data: mixture of Gaussians
rng = np.random.default_rng(0)
x = np.concatenate([
    rng.normal(-2.0, 0.7, size=400),
    rng.normal( 1.5, 0.4, size=600),
])[:, None]  # sklearn expects 2D

# Fit KDE (Gaussian kernel)
kde = KernelDensity(kernel="gaussian", bandwidth=0.4).fit(x)

# Evaluate on a grid
grid = np.linspace(-6, 6, 400)[:, None]
logp = kde.score_samples(grid)        # log density
p = np.exp(logp)

plt.figure()
plt.hist(x[:, 0], bins=40, density=True, alpha=0.3, label="hist")
plt.plot(grid[:, 0], p, label="KDE")
plt.legend()
plt.show()

O que observar:

  • Reduzir a largura de banda (por exemplo, 0.2) mostrará múltiplos picos estreitos (possivelmente overfitting).
  • Aumentar a largura de banda (por exemplo, 1.0) irá fundir modos (suavização excessiva).

Exemplo 2: Seleção de largura de banda via log-verossimilhança com validação cruzada

import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KernelDensity

rng = np.random.default_rng(1)
x = rng.standard_t(df=3, size=800)[:, None]  # heavy-tailed distribution

params = {"bandwidth": np.logspace(-1.2, 0.6, 30)}  # ~0.06 to ~4
grid = GridSearchCV(
    KernelDensity(kernel="gaussian"),
    params,
    cv=5,
    scoring="neg_log_loss",  # not directly compatible; see note below
)

# NOTE: sklearn doesn't provide a built-in KDE neg-log-loss scorer for unsupervised data.
# Instead, we can implement CV manually using score_samples or use GridSearchCV with a custom scorer.

Como a KDE é não supervisionada, o ajuste de largura de banda frequentemente exige:

  • um loop de validação cruzada personalizado que maximize a log-verossimilhança em validação via score_samples, ou
  • seletores especializados de largura de banda para KDE (comuns em bibliotecas de estatística).

Um esboço simples de validação cruzada manual:

from sklearn.model_selection import KFold

def cv_loglik(x, bandwidth, n_splits=5):
    kf = KFold(n_splits=n_splits, shuffle=True, random_state=0)
    scores = []
    for train_idx, test_idx in kf.split(x):
        kde = KernelDensity(bandwidth=bandwidth).fit(x[train_idx])
        scores.append(kde.score(x[test_idx]))  # sum of log densities
    return np.mean(scores)

bandwidths = np.logspace(-1.2, 0.6, 30)
best_h = max(bandwidths, key=lambda h: cv_loglik(x, h))
print("best bandwidth:", best_h)

Exemplo 3: KDE para detecção de anomalias (limiarização por densidade)

Uma abordagem não supervisionada comum:

  1. Ajustar a KDE em dados de treinamento “normais”.
  2. Pontuar novos pontos pelo log da densidade.
  3. Sinalizar pontos com log da densidade abaixo de um limiar (por exemplo, 1º percentil).
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KernelDensity

# X_train: normal data (n x d), X_test: mixed normal/anomalous
scaler = StandardScaler()
Xtr = scaler.fit_transform(X_train)
Xte = scaler.transform(X_test)

kde = KernelDensity(kernel="gaussian", bandwidth=0.8).fit(Xtr)

logp_train = kde.score_samples(Xtr)
threshold = np.quantile(logp_train, 0.01)  # 1% lowest-density as cutoff

logp_test = kde.score_samples(Xte)
is_anomaly = logp_test < threshold

Ressalvas:

  • Em dimensões mais altas, as densidades da KDE podem ficar mal calibradas e extremamente pequenas em escala absoluta. Os limiares devem ser validados com cuidado.
  • Se a distribuição dos dados mudar ao longo do tempo (drift), a KDE deve ser reajustada ou atualizada.

Para uma visão mais ampla de detecção de outliers baseada em densidade e alternativas (por exemplo, isolation forests, one-class SVM), veja Detecção de Anomalias.

Por que a KDE tem dificuldades em altas dimensões

A KDE é um exemplo clássico da Maldição da Dimensionalidade: muitos métodos que dependem de vizinhanças locais tornam-se ineficazes conforme a dimensão (d) cresce.

Intuição: vizinhanças “locais” deixam de ser locais

Em altas dimensões:

  • A maior parte do volume de uma bola fica perto de sua fronteira.
  • Distâncias entre pontos tendem a se concentrar (vizinhos mais próximos e mais distantes não diferem tanto em relação à escala).
  • Os dados ficam esparsos: para manter uma fração fixa de massa de probabilidade dentro de uma vizinhança de raio pequeno, o raio precisa crescer rapidamente com (d).

Como a KDE faz a média de núcleos com base na distância, isso significa:

  • Com largura de banda pequena, quase nenhum ponto cai em uma vizinhança significativa → densidades próximas de zero e alta variância.
  • Com largura de banda grande, núcleos se sobrepõem amplamente → suavização excessiva e alto viés.

Taxas de convergência pioram com a dimensionalidade

Sob suposições padrão de suavidade, a taxa ótima do erro quadrático integrado médio (MISE) para KDE se comporta aproximadamente como:

[ \text{MISE} \sim n^{-\frac{4}{4+d}} ]

À medida que (d) aumenta, o expoente (\frac{4}{4+d}) diminui, então você precisa de dramaticamente mais amostras para obter a mesma precisão.

Consequências práticas em aprendizado de máquina

  • A KDE é excelente para visualização em 1D–2D e frequentemente ainda é útil até ~5–10 dimensões com dados suficientes e pré-processamento cuidadoso.
  • Acima disso, ela tende a se tornar pouco confiável, a menos que os dados estejam sobre uma variedade (manifold) de dimensão menor (por exemplo, vetores de incorporação (embeddings) em que a dimensão efetiva é pequena).

Mitigações

Se a KDE estiver com dificuldades, estratégias comuns incluem:

  • Redução de dimensionalidade primeiro: aplicar PCA/UMAP para comprimir para uma dimensão pequena e então ajustar a KDE nesse espaço (veja Redução de Dimensionalidade).
    Isso é comum para estimação de densidade em embeddings aprendidos.
  • Usar um modelo de densidade paramétrico (parametric density model): por exemplo, Modelos de Mistura Gaussiana podem ser mais eficientes em amostras em dimensões moderadas a altas quando a suposição de mistura gaussiana é razoável.
  • Usar modelos especializados de densidade em altas dimensões: fluxos normalizantes (normalizing flows), modelos autorregressivos (autoregressive models), modelos de difusão (diffusion models) (frequentemente além do escopo da KDE clássica).
  • Modelar razões de densidade (density ratios) em vez de densidades quando apenas comparações importam (comum em aprendizado de máquina moderno; evita dificuldades de estimação de densidade absoluta).

KDE em contexto: métodos relacionados e conexões

  • Modelos de Mistura Gaussiana (Gaussian Mixture Models, GMMs): KDE com um núcleo gaussiano se assemelha a um modelo de mistura gaussiana com um componente por ponto de dados e pesos iguais, mas modelos de mistura gaussiana aprendem um número menor de componentes via EM, frequentemente escalando melhor (veja Modelos de Mistura Gaussiana).
  • Estimação de densidade por k-NN: estima densidade expandindo uma bola até conter (k) vizinhos; tradeoffs bem relacionados e também sofre em alto (d) (veja K-Vizinhos Mais Próximos (KNN)).
  • Métodos de núcleo (kernel methods): a KDE usa núcleos para construir uma função a partir de dados, mas trata-se de estimação de densidade e não de aprendizado supervisionado. A ideia compartilhada — representar funções via avaliações de núcleo — é conceitualmente relacionada (veja Métodos de Núcleo).
  • Processos Gaussianos (Gaussian Processes): também usam núcleos, mas para distribuições sobre funções em vez de densidades sobre entradas (veja Processos Gaussianos).

Quando usar KDE (e quando não usar)

Boas escolhas:

  • Visualizar distribuições unimodais/multimodais em 1D/2D
  • Suavizar medições ruidosas
  • Detecção de anomalias baseada em densidade em baixas dimensões
  • Estimação de densidade para pequenos conjuntos de features após cuidadosa padronização

Más escolhas:

  • Dados tabulares brutos de alta dimensionalidade com muitas features
  • Features contínuas/categóricas misturadas sem tratamento especializado
  • Cenários que exigem pontuação rápida com (n) muito grande e restrições rígidas de latência (a menos que se use aproximação)
  • Situações em que verossimilhanças calibradas em alta dimensão importam (a KDE frequentemente se torna enganosa)

Resumo

A KDE estima uma densidade de probabilidade por média de núcleos centrados nas amostras, tornando-se uma ferramenta flexível e intuitiva para estimação de densidade e visualização. Na prática, a largura de banda domina o desempenho: ela controla a suavização e deve ser escolhida com cuidado (regras práticas, métodos plug-in ou verossimilhança com validação cruzada). A KDE é simples de implementar e útil em baixas dimensões, mas tem dificuldades conforme a dimensionalidade cresce, tanto estatisticamente (piores taxas de convergência) quanto geometricamente (concentração de distâncias) — uma consequência direta da Maldição da Dimensionalidade.