用scipy高斯核密度估计来计算CDF逆

时间:2017-11-21 16:28:04

标签: python numpy scipy scientific-computing

gaussian_kde中的scipy.stats函数有一个函数evaluate,可以返回输入点的PDF值。我正在尝试使用gaussian_kde来估算逆CDF。动机是生成一些输入数据的蒙特卡洛实现,其统计分布使用KDE进行数值估计。是否有一个绑定到gaussian_kde的方法用于此目的?

以下示例显示了高斯分布情况下该如何工作。首先,我展示如何进行PDF计算以设置我想要实现的特定API:

import numpy as np 
from scipy.stats import norm, gaussian_kde

npts_kde = int(5e3)
n = np.random.normal(loc=0, scale=1, size=npts_kde)
kde = gaussian_kde(n)

npts_sample = int(1e3)
x = np.linspace(-3, 3, npts_sample)
kde_pdf = kde.evaluate(x)
norm_pdf = norm.pdf(x)

Demo of KDE approximation of the PDF of a normal distribution

有一种类似的简单方法来计算逆CDF吗? norm函数有一个非常方便的isf函数,可以完成这个:

cdf_value = np.sort(np.random.rand(npts_sample))
cdf_inv = norm.isf(1 - cdf_value)

Demo of desired KDE approximation of the CDF of a normal distribution

kde_gaussian是否存在此功能?或者从已经实现的方法构建这样的函数是否直接?

2 个答案:

答案 0 :(得分:1)

方法integrate_box_1d可以用来计算CDF,但它没有矢量化;你需要循环点。如果内存不是问题,以向量形式重写其source code(实质上只是调用special.ndtr)可能会加快速度。

from scipy.special import ndtr
stdev = np.sqrt(kde.covariance)[0, 0]
pde_cdf = ndtr(np.subtract.outer(x, n)).mean(axis=1)
plot(x, pde_cdf)

反函数的图是plot(pde_cdf, x)。如果目标是计算特定点的反函数,请考虑使用the inverse of interpolating spline,插入CDF的计算值。

答案 1 :(得分:1)

您可以使用一些python技巧来快速且有效地估计CDF(基于this answer):

    from scipy.special import ndtr
    cdf = tuple(ndtr(np.ravel(item - kde.dataset) / kde.factor).mean()
                for item in x)

它的工作速度与this answer一样快,但是具有线性(len(kde.dataset))的空间复杂度,而不是二次(实际上是len(kde.dataset) * len(x))的空间。

接下来要做的就是使用逆逼近,例如从statsmodels开始。