如何基于两个高斯KDE估计值计算KL散度?
计算两个高斯KDE之间的KL散度及分布距离
先解决你疑惑的PDF值大于1的问题
概率密度(PDF)本身可以大于1,它不是概率,而是概率的变化率。比如均匀分布U(0, 0.5)的PDF恒为2,完全符合定义,所以你看到PDF大于1是正常现象,不影响后续计算。
两种可行的KL散度计算方法
KL散度的定义是:$D_{KL}(P||Q) = \mathbb{E}_P\left[\log\frac{P(x)}{Q(x)}\right] = \int P(x)\log\frac{P(x)}{Q(x)}dx$,对于KDE拟合的分布,我们可以用以下两种方法近似计算:
方法1:网格采样+数值积分
通过在覆盖数据范围的密集网格上计算PDF,再用数值积分近似KL散度:
import numpy as np from scipy import stats from scipy.integrate import trapezoid # 生成示例数据 dataset1 = np.random.rand(50) dataset2 = np.random.rand(49) # 拟合KDE kernel1 = stats.gaussian_kde(dataset1) kernel2 = stats.gaussian_kde(dataset2) # 确定采样范围(覆盖两个数据集的极值,适当扩展避免边界偏差) min_val = min(dataset1.min(), dataset2.min()) - 0.1 max_val = max(dataset1.max(), dataset2.max()) + 0.1 # 生成密集采样点 x = np.linspace(min_val, max_val, 1000) # 计算两个KDE在采样点上的PDF值(加极小值避免log(0)) pdf1 = kernel1(x) + 1e-12 pdf2 = kernel2(x) + 1e-12 # 用梯形法计算积分,近似KL散度 kl_div = trapezoid(pdf1 * np.log(pdf1 / pdf2), x) print(f"KL散度(P||Q): {kl_div:.4f}")
方法2:蒙特卡洛采样
从P分布(kernel1)采样,通过样本均值近似期望:
# 从kernel1对应分布采样大量样本 samples = kernel1.resample(size=10000)[0] # 计算采样点的PDF值 pdf1 = kernel1(samples) + 1e-12 pdf2 = kernel2(samples) + 1e-12 # 样本均值近似KL散度 kl_div_mc = np.mean(np.log(pdf1 / pdf2)) print(f"蒙特卡洛估计KL散度(P||Q): {kl_div_mc:.4f}")
对称分布距离:JS散度
KL散度是不对称的($D_{KL}(P||Q) \neq D_{KL}(Q||P)$),如果需要对称的分布距离,可以使用JS散度:
# 计算混合分布的PDF pdf_mix = 0.5 * pdf1 + 0.5 * pdf2 # 计算JS散度 js_div = 0.5 * trapezoid(pdf1 * np.log(pdf1 / pdf_mix), x) + 0.5 * trapezoid(pdf2 * np.log(pdf2 / pdf_mix), x) print(f"JS散度: {js_div:.4f}")
内容的提问来源于stack exchange,提问作者f.leno
相关产品推荐
相关产品推荐

