sklearn:KDE不适合小值

时间:2017-07-11 15:29:53

标签: python scikit-learn gaussian kde

我正在努力为小输入范围实现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);

enter image description here

# 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)

enter image description here

工作正常。但是,将'divisor'变量更改为100,scipy和seaborn可以处理较小的数据值。 Sklearn的KDE无法实现我的实现:

enter image description here

我做错了什么,我该如何纠正?我需要klearns实现KDE所以不能使用其他算法。

1 个答案:

答案 0 :(得分:2)

核密度估计称为非参数方法,但实际上它有一个名为带宽的参数。

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