我正在努力为小输入范围实现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无法实现我的实现:
我做错了什么,我该如何纠正?我需要klearns实现KDE所以不能使用其他算法。
答案 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
。