Kernel Density Estimation
Histograms jump with bin edges. KDE centers a smooth bump on every point and averages them into a curve with no bins to argue about.
Why Does This Exist?
Histograms lie by binning: shift the edges and modes appear or vanish, while high dimensions make bins explode exponentially. Parametric fits lie by shape, because data are rarely exactly Gaussian. Analysts need a smooth, bin-free picture of where data concentrate before modeling.
KDE delivers it with : one kernel per point, averaged, with bandwidth setting bump width and Gaussian kernels as the default. It needs only descriptive statistics as background and pairs with resampling in bootstrap and resampling.
The one idea you need first
A density integrates to 1 and runs tall where data crowd. Each kernel bump carries mass, so the average integrates to 1 automatically. Bandwidth is the only knob: small follows every point, large flattens everything.
Think of It Like This
Sand piles instead of buckets
A histogram sorts sand into buckets, so moving the walls changes the skyline. KDE drops one small sand pile on each grain and lets them merge into dunes.
Pile width is bandwidth: fine piles spike at every grain, wide piles flatten the desert. The mapping holds pile for kernel and dune for density.
Where it stops: sand piles are physical and local, while KDE sums globally per query, which turns expensive on large without trees or FFT.
How It Actually Works
Bias shrinks as while variance shrinks as , the classic tradeoff minimized near in one dimension with integrated squared error . Silverman rule starts Gaussian-ish cases. Multivariate KDE needs full bandwidth matrices and degrades fast with dimension: effective samples shrink exponentially, so past about five dimensions prefer parametric or projection methods.
Worked example
Eight points with Gaussian at . The normalizer is .
Neighbors dominate: for and , and each. Each contributes . Next points add little: gives with for , gives with for , and contributes essentially zero. Summing all eight gives .
Bandwidth moves the answer as theory predicts. With the same falls to about while points spike near . With the curve flattens near to everywhere.
Code
The snippet evaluates the same Gaussian KDE at one grid point, so the hand total can be checked directly.
import numpy as np
x = np.array([1.0, 1.5, 2.0, 2.2, 3.0, 3.5, 5.0, 5.2])h = 0.3grid = np.array([2.1])dens = np.exp(-0.5 * ((grid[:, None] - x) / h) ** 2).sum(axis=1)dens = dens / (x.size * h * np.sqrt(2 * np.pi))print(round(float(dens[0]), 2)) # -> 0.34Hand sum and code agree at 0.34. Change to 0.05 or 2.0 and watch spike versus flatten.
Watch Out For
Trusting default bandwidths blindly
Silverman assumes near-Gaussian data and oversmooths multimodality: two real humps merge into one and analysts conclude one segment. Undersmoothed defaults do the reverse and invent modes from noise.
Plot several bandwidths across a decade of . When the mode count changes, the default decided the conclusion, not the data.
KDE on high dimensions or bounded edges
In ten dimensions neighborhoods sit empty and bumps never overlap, so the curve is spikes on a plain. On bounded data, symmetric kernels leak mass across the edge and understate near-zero density.
Cap KDE at low dimensions, use boundary correction or logs near edges, and switch families past about five dimensions. When most queries see one bump, dimensionality won.
The Quick Version
- KDE averages one -mass bump per point, with no bins and one bandwidth knob.
- Bias scales as and variance as , with optimal in one dimension.
- The eight-point example at gives .
- Tiny spikes on noise while huge flattens real modes, so scan a decade of bandwidths.
- Past about five dimensions or on hard boundaries, correct the edges or switch methods.
- Naive queries cost each, so use trees or FFT at scale.