Bandwidth Selection

Bandwidth selection maximizes leave-one-out or k-fold log-likelihood.

Default grid

When grid=None, kern.BandwidthSelector calls kern.default_bandwidth_grid(). The default is a 64-point logarithmic grid centered on Silverman’s rule-of-thumb bandwidth [Silverman 1986].

"""Select a bandwidth for one kernel using log-likelihood."""

import numpy as np

from kern import BandwidthSelector, default_bandwidth_grid


rng = np.random.default_rng(1)
data = rng.normal(size=1_000)

# Omit grid to use the default.
automatic = BandwidthSelector(
    kernel="gaussian",
    cv="loo",
).fit(data)

# Or construct and pass a custom grid.
grid = default_bandwidth_grid(data, size=64, minimum=0.05, maximum=0.8)
custom = BandwidthSelector(
    grid=grid,
    kernel="epanechnikov",
    cv=5,
    parallel="evaluation",
).fit(data)

print(automatic.kernel_, automatic.best_bandwidth_)
print(custom.kernel_, custom.best_bandwidth_)

Custom grid

Pass any positive one-dimensional array as grid:

selector = BandwidthSelector(
    grid=[0.05, 0.1, 0.2, 0.4],
    kernel="cosine",
    cv=5,
).fit(data)

Bandwidth selection always uses exactly one kernel. Mappings are not accepted for grid or kernel.

Bounded KDE

Pass bounded=True to select a bandwidth for kern.BoundedKernelDensity. bounded_method accepts the same values as kern.BoundedKernelDensity: "reflected", "beta", or None for regular unbounded KDE behavior.

selector = BandwidthSelector(
    grid=[0.05, 0.1, 0.2],
    bounded=True,
    bounded_method="beta",
).fit(data)

Parallel loop

parallel="grid" evaluates bandwidth candidates concurrently. Each individual LOO or k-fold evaluation is serial.

parallel="evaluation" walks the grid serially and parallelizes each individual LOO or k-fold KDE evaluation.

parallel="auto" uses evaluation parallelism for a single bandwidth and for small grids over large datasets. It otherwise parallelizes the grid.

Bounded KDE bandwidth selection uses the bounded density functions directly and does not use the C-level parallel scorer.