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:
- Ajustar a KDE em dados de treinamento “normais”.
- Pontuar novos pontos pelo log da densidade.
- 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.