1

我有一个一维离散数据集。在这个集合上,我想用 sklearn 的内置函数进行核密度估计:

from sklearn.neighbors.kde import KernelDensity

data = ... # array of shape [5000, 1]

## perform kde with gaussian kernels
kde = KernelDensity(kernel='gaussian', bandwidth=0.8).fit(data.reshape(-1, 1))

在 kde 的实例方法的帮助下score_samples,我能够绘制出对底层密度函数的合理估计:

用kde创建的pdf

## code for plot
X_plot = np.linspace(-5, 100, 10000)[:, np.newaxis]
log_dens = kde.score_samples(X_plot)

plt.plot(X_plot[:, 0], np.exp(log_dens))

我想使用这个分布来执行一个样本 KS 测试。我发现 scipy 已经实现了这个功能。在此处查看文档。它说:

scipy.stats.kstest(rvs, cdf, args=(), N=20, alternative='two-sided', mode='approx')

rvs:str、数组或可调用

如果是字符串,它应该是 scipy.stats 中的分布名称。如果是数组,它应该是随机变量观察值的一维数组。如果是可调用的,它应该是一个生成随机变量的函数;它需要有一个关键字参数大小。

cdf : str 或可调用

如果是字符串,它应该是 scipy.stats 中的分布名称。如果 rvs 是字符串,则 cdf 可以为 False 或与 rvs 相同。如果是可调用对象,则该可调用对象用于计算 cdf。

基本上,rvs 是新的样本数据,而 cdf 是累积分布函数(pdf 的积分)。我无法找到如何访问在 sklearn 中计算 pdf 的函数,以便我可以集成它并将其提供给 kstest。

有人知道如何到达那里吗?另外,如果这种方法有任何替代方法,请告诉我。

4

1 回答 1

0

您可以简单地集成score_samples以获得 cdf。 scipy.integrate.quad可能会奏效。

** 编辑 ** 这似乎score_samples是日志密度,但是当未记录时集成为 1。虽然确实需要一些重塑,但不幸的是,scipy 集成边界不接受数组。

def cdf(y):
    return functools.partial(
        scipy.integrate.quad,
        lambda x: np.exp(kde.score_samples(np.array([x]).reshape(-1,1)))[0],
        -np.inf
    )(y)[0]

def array_cdf(X):
    return np.array(list(map(cdf, X)))

scipy.stats.kstest(data, array_cdf)
于 2018-10-22T11:37:32.420 回答