在python中,如何返回通过sklearn的函数KernelDensity估计的分布的平均值(或期望值)?

在python中,如何返回通过sklearn的函数KernelDensity估计的分布的平均值(或期望值)?,python,scikit-learn,statsmodels,kernel-density,Python,Scikit Learn,Statsmodels,Kernel Density,我的问题是,如何返回估计的“kde”的均值和方差?或者您知道有没有其他软件包可以轻松输出均值或方差值,例如print kde.mean()或print kde.get_参数(mean) 一般来说,您需要以数字方式进行此操作。我建议两种不同的方法: 整合 蒙特卡罗模拟 这些方法适用于任何内核和任何带宽 整合 利用这样一个事实,即一旦我们知道概率密度函数,我们就可以通过积分轻松计算均值和方差 请注意,在scikit learn中,方法score\u samples返回log pdf,因此需要“

我的问题是,如何返回估计的“kde”的均值和方差?或者您知道有没有其他软件包可以轻松输出均值或方差值,例如
print kde.mean()
print kde.get_参数(mean)


一般来说,您需要以数字方式进行此操作。我建议两种不同的方法:

  • 整合
  • 蒙特卡罗模拟
这些方法适用于任何内核和任何带宽

整合 利用这样一个事实,即一旦我们知道概率密度函数,我们就可以通过积分轻松计算均值和方差

请注意,在
scikit learn
中,方法
score\u samples
返回log pdf,因此需要“exp”它

蒙特卡罗模拟 这里的想法是简单地从KDE中取样,并通过样本均值和方差估计总体均值和方差


代码 输出:

TL;DR version - Mean:           3.5605148164179368
Integration version - Mean:    (3.5604536291684905, 1.9311947816995413e-08)
TL;DR version - Variance:       6.646077637181225
Integration version - Variance: 6.644042199345121
意思是: 集成:3.560582852075697 蒙特卡洛:3.5595633705830934

差异: 集成:6.645066811078639 蒙特卡洛:6.646732489654485

原则 我遇到了同样的情况,您可以在
statsmodels
库中找到一个有效的Expection实现,但有趣的是,它正在修补
scipy
,而不是在自己的库中执行相同的功能

它们似乎有
expect()
expect\u v2()
expect\u discrete()
,在另一个答案中使用了类似的技术,使用
scipy.integrate.quad
进行数值积分

TL;DR版本 另外,如果您像我一样懒惰,使用
statsmodels
推断的默认采样,您可以通过将数值积分替换为
density
support
的点积来快速获得期望值。在大多数情况下,它可能“足够近”

import numpy as np
import statsmodels.api as sm
import scipy

N = 100
np.random.seed(1)
X = np.concatenate((np.random.normal(0, 1, int(0.3 * N)),np.random.normal(5, 1, int(0.7 * N))))[:, np.newaxis]

X_plot = np.linspace(-5, 10, 1000)[:, np.newaxis]

kde = sm.nonparametric.KDEUnivariate(X)
kde.fit(kernel='gau', bw=0.5)

mean1 = np.dot(kde.density, kde.support) / kde.density.sum()
mean2 = scipy.integrate.quad(lambda x: kde.evaluate(x)  * x, kde.support[0], kde.support[-1])
print('TL;DR version - Mean:', mean1)
print('Integration version - Mean:', mean2)

print('TL;DR version - Variance:', np.dot(kde.density, kde.support**2) / kde.density.sum() - mean1**2)
print('Integration version - Variance:', scipy.integrate.quad(lambda x: kde.evaluate(x)  * x**2, kde.support[0], kde.support[-1])[0] - mean2[0]**2)
输出:

TL;DR version - Mean:           3.5605148164179368
Integration version - Mean:    (3.5604536291684905, 1.9311947816995413e-08)
TL;DR version - Variance:       6.646077637181225
Integration version - Variance: 6.644042199345121
四边形和圆点的区别 请注意,由于缺少
evaluate()
,因此
quad
方法将不适用于非高斯核。例如,如果在合适的时候传递
kernel='epa',fft=False
,唯一的方法是当前使用
numpy.dot
。这在未来的版本中可能会发生变化

作为一个有趣的效果,seaborn库依赖于
statsmodels
来显示它的kde,但是由于上述原因,它只适用于Gaussian。对于cdf,它将显示高斯cdf,即使指定了不同的cdf;pdf似乎仍然遵守kerenel规范

参考文献

如果存储库发生变化[1月22日最新提交bfa3e69],也会在此处复制,但是如果将此算法与
statsmodels
一起使用,则可能必须将
pdf
调用替换为
evaluate
调用

TL;DR version - Mean:           3.5605148164179368
Integration version - Mean:    (3.5604536291684905, 1.9311947816995413e-08)
TL;DR version - Variance:       6.646077637181225
Integration version - Variance: 6.644042199345121