python - 使用 scipy 的 gaussian_kde 和 sklearn 的 KernelDensity 进行核密度估计会导致不同的结果
问题描述
我从两个叠加的正态分布中创建了一些数据,然后应用sklearn.neighbors.KernelDensity和scipy.stats.gaussian_kde来估计密度函数。但是,使用相同的带宽 (1.0) 和相同的内核,两种方法都会产生不同的结果。有人可以解释一下原因吗?感谢帮助。
您可以在下面找到重现该问题的代码:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
import seaborn as sns
from sklearn.neighbors import KernelDensity
n = 10000
dist_frac = 0.1
x1 = np.random.normal(-5,2,int(n*dist_frac))
x2 = np.random.normal(5,3,int(n*(1-dist_frac)))
x = np.concatenate((x1,x2))
np.random.shuffle(x)
eval_points = np.linspace(np.min(x), np.max(x))
kde_sk = KernelDensity(bandwidth=1.0, kernel='gaussian')
kde_sk.fit(x.reshape([-1,1]))
y_sk = np.exp(kde_sk.score_samples(eval_points.reshape(-1,1)))
kde_sp = gaussian_kde(x, bw_method=1.0)
y_sp = kde_sp.pdf(eval_points)
sns.kdeplot(x)
plt.plot(eval_points, y_sk)
plt.plot(eval_points, y_sp)
plt.legend(['seaborn','scikit','scipy'])
如果我将 scipy 带宽更改为 0.25,两种方法的结果看起来大致相同。
解决方案
scipy.stats.gaussian_kde 和 sklearn.neighbors.KernelDensity 中的带宽是什么意思是不一样的。Scipy.stats.gaussian_kde 使用带宽因子https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html。对于一维核密度估计,应用以下公式:
sklearn.neighbors.KernelDensity 的带宽 = scipy.stats.gaussian_kde 的带宽因子 * 样本的标准偏差
对于您的估计,这可能意味着您的标准差等于 4。
我想参考获取 SciPy 的 gaussian_kde 函数使用的带宽以获取更多信息。
推荐阅读
- python - NumPy right_shift 给出全零
- php - Postgres pg_dump 永远不会结束
- python - 将趋势线添加到 matplotlib 线图 python
- amazon-web-services - 按实例计算的成本和使用情况,无需手动标记
- common-lisp - 如何捕捉 Common Lisp 中的错误信息?
- python - 如何在 jupyter notebook 上安装 chartify?
- java - Spring WebFlux - 返回 Mono.subscribe() 中调用的 Consumer 返回的值;
- karate - 空手道 - 如何仅在一个环境中运行特定场景?
- powershell - power shell 移动特定文件
- java - 从kafka中的投票记录创建批次