我正在努力为小输入范围实现 KDE 的 scikit-learn 实现。以下代码有效。将除数变量增加到 100,KDE 陷入困境:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
from sklearn.neighbors import KernelDensity
# make data:
np.random.seed(0)
divisor = 1
gaussian1 = (3 * np.random.randn(1700))/divisor
gaussian2 = (9 + 1.5 * np.random.randn(300)) / divisor
gaussian_mixture = np.hstack([gaussian1, gaussian2])
# illustrate proper KDE with seaborn:
sns.distplot(gaussian_mixture);
# now implement in sklearn:
x_grid = np.linspace(min(gaussian1), max(gaussian2), 200)
kde_skl = KernelDensity(bandwidth=0.5)
kde_skl.fit(gaussian_mixture[:, np.newaxis])
# score_samples() returns the log-likelihood of the samples
log_pdf = kde_skl.score_samples(x_grid[:, np.newaxis])
pdf = np.exp(log_pdf)
fig, ax = plt.subplots(1, 1, sharey=True, figsize=(7, 4))
ax.plot(x_grid, pdf, linewidth=3, alpha=0.5)
工作正常。但是,将“divisor”变量更改为 100,scipy 和 seaborn 可以处理较小的数据值。 Sklearn 的 KDE 无法与我的实现配合使用:
我做错了什么以及如何纠正?我需要 KDE 的 sklearns 实现,因此无法使用其他算法。
最佳答案
核密度估计被称为非参数方法,但实际上它有一个称为带宽的参数。
每个 KDE 应用程序都需要这个参数集!
当你做seaborn-plot时:
sns.distplot(gaussian_mixture);
您没有提供任何带宽,并且seaborn 使用默认启发式(scott 或 silverman)。它们使用数据以依赖的方式选择一些带宽。
您的 sklearn 代码如下所示:
kde_skl = KernelDensity(bandwidth=0.5)
有固定/恒定的带宽!这可能会给您带来麻烦,并且可能就是这里的原因。但这至少是值得一看的东西。一般来说,人们会结合 sklearn 的 KDE 和 GridSearchCV 作为交叉验证工具来选择一个好的带宽。在许多情况下,这会更慢,但比上面的启发式方法更好。
遗憾的是,您没有解释为什么要使用 sklearn 的 KDE。我个人对 3 个热门候选者的评分是 statsmodels > sklearn > scipy
。
关于python - sklearn : KDE not working for small values,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45038795/